mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-09 02:52:04 +08:00
ITS#6625 concurrency patch from Doug Leavitt @ Oracle .com
This commit is contained in:
parent
026713f497
commit
0f30db1c46
714
doc/drafts/draft-zeilenga-ldap-c-api-concurrency-xx.txt
Normal file
714
doc/drafts/draft-zeilenga-ldap-c-api-concurrency-xx.txt
Normal file
@ -0,0 +1,714 @@
|
||||
INTERNET-DRAFT Kurt D. Zeilenga
|
||||
Intended Category: Standards Track OpenLDAP Foundation
|
||||
Extends: draft-ietf-ldapext-ldap-c-api-03.txt
|
||||
Expires: 28 March 2000
|
||||
28 September 1999
|
||||
|
||||
LDAP C API Concurrency Extensions
|
||||
<draft-zeilenga-ldap-c-api-concurrency-00.txt>
|
||||
|
||||
1. Status of this Memo
|
||||
|
||||
This document is an Internet-Draft and is in full conformance with all
|
||||
provisions of Section 10 of RFC2026.
|
||||
|
||||
This draft document will be submitted to the RFC Editor as a Standards
|
||||
Track document. Distribution of this memo is unlimited. Technical
|
||||
discussion of this document will take place on the IETF LDAP Extension
|
||||
Working Group mailing list <ietf-ldapext@netscape.com>. Please send
|
||||
editorial comments directly to the author <Kurt@OpenLDAP.org>.
|
||||
|
||||
Internet-Drafts are working documents of the Internet Engineering Task
|
||||
Force (IETF), its areas, and its working groups. Note that other
|
||||
groups may also distribute working documents as Internet-Drafts.
|
||||
|
||||
Internet-Drafts are draft documents valid for a maximum of six months
|
||||
and may be updated, replaced, or obsoleted by other documents at any
|
||||
time. It is inappropriate to use Internet-Drafts as reference
|
||||
material or to cite them other than as "work in progress."
|
||||
|
||||
The list of current Internet-Drafts can be accessed at
|
||||
http://www.ietf.org/ietf/1id-abstracts.txt
|
||||
|
||||
The list of Internet-Draft Shadow Directories can be accessed at
|
||||
http://www.ietf.org/shadow.html.
|
||||
|
||||
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||
|
||||
Please see the Copyright section near the end of this document for
|
||||
more information.
|
||||
|
||||
2. Abstract
|
||||
|
||||
This document defines extensions to the LDAP C API to support use in
|
||||
concurrent execution environments. The document describes and defines
|
||||
|
||||
Zeilenga [Page 1]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
requirements for multiple concurrency levels: thread safe, session
|
||||
thread safe, and operation thread safe.
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", and "MAY" in this document are
|
||||
to be interpreted as described in RFC 2119 [KEYW].
|
||||
|
||||
3. Introduction
|
||||
|
||||
This document extends the LDAP C API [CAPI] specification to support
|
||||
use in concurrent execution environments. The extensions add powerful
|
||||
concurrent processing capabilities to the simple to use CAPI. This
|
||||
document provides an overview of different levels of concurrent
|
||||
execution support and offers a number of CAPI "features" to provide
|
||||
capabilities at these levels.
|
||||
|
||||
The remainder of this section describes three levels of concurrent
|
||||
execution: thread safe, session thread safe, operation thread safe
|
||||
APIs.
|
||||
|
||||
3.1. Thread Safe
|
||||
|
||||
An implementation which allows applications to safely execute in
|
||||
concurrent execution environments where the application provides
|
||||
necessary synchronization to ensure serialization of CAPI usage is
|
||||
considered to be "thread safe." Applications may execute non-CAPI
|
||||
calls in concurrent execution contexts when using thread safe
|
||||
implementations.
|
||||
|
||||
3.2. Session Thread Safe
|
||||
|
||||
A "thread safe" implementation which allows CAPI calls associated with
|
||||
different LDAP sessions to proceed asychronously is considered to be
|
||||
"session thread safe."
|
||||
|
||||
3.3. Operation Thread Safe
|
||||
|
||||
A "session thread safe" implementation which allows CAPI calls
|
||||
associated with different LDAP operations to proceed asychronously is
|
||||
considered to be "operation thread safe".
|
||||
|
||||
4. Basic Thread Safe Feature
|
||||
|
||||
Zeilenga [Page 2]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
This section details requirements for the thread safe CAPI feature.
|
||||
Implementations fulfilling these requirements are said to support the
|
||||
LDAP_API_FEATURE_THREAD_SAFE feature and SHOULD advertise this support
|
||||
as detailed below. This feature SHOULD be provided by
|
||||
implementations.
|
||||
|
||||
Implementations of this feature MUST implement the LDAP error handling
|
||||
extension [ERRNO].
|
||||
|
||||
Implementations of this feature MUST allow non-CAPI calls to proceed
|
||||
asynchronously.
|
||||
|
||||
Implementations of this feature MUST NOT use any non-thread safe call
|
||||
or mechanism provided by C environment or operating system. An
|
||||
example of non-reentrant calls is the UNIX strtok() function. Example
|
||||
of a non-reentrant mechanism is global (i.e.: non-thread specific)
|
||||
errno.
|
||||
|
||||
5. Session Thread Safe Feature
|
||||
|
||||
This section details requirements for the session thread safe CAPI
|
||||
feature. Implementations fulfilling these requirements are said to
|
||||
support the LDAP_API_FEATURE_SESSION_THREAD_SAFE feature and SHOULD
|
||||
advertise this support as detailed below. This feature is
|
||||
RECOMMENDED.
|
||||
|
||||
5.1. Prerequisite Features
|
||||
|
||||
Implementations providing this feature MUST provide and advertise both
|
||||
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO [ERRNO] and
|
||||
LDAP_API_FEATURE_THREAD_SAFE.
|
||||
|
||||
5.2. Atomic Session Handles
|
||||
|
||||
Implementations providing this feature SHOULD ensure that operations
|
||||
upon a given session handle are atomic. Implementations which provide
|
||||
atomic session handles SHOULD advertise the feature
|
||||
LDAP_API_FEATURE_ATOMIC_SESSION_HANDLES.
|
||||
|
||||
5.3. Concurrency Requirements
|
||||
|
||||
Implementations providing this feature MUST not restrict CAPI calls
|
||||
acting upon a given LDAP session to a particular execution context.
|
||||
Applications MAY use a session handle on any thread. Applications
|
||||
|
||||
Zeilenga [Page 3]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
MUST NOT assume that operations upon a session are atomic.
|
||||
|
||||
Implementations providing this feature MUST allow CAPI calls acting
|
||||
upon different LDAP sessions to safely proceed asynchronously.
|
||||
|
||||
Implementations providing this feature MUST allow CAPI calls not
|
||||
acting upon an LDAP session to safely proceed asynchronously.
|
||||
|
||||
6. Operation Thread Safe Feature
|
||||
|
||||
This section details requirements for the operation thread safe CAPI
|
||||
feature based upon a duplicate session handles mechanism.
|
||||
|
||||
Implementations fulfilling these requirements are said to support the
|
||||
LDAP_API_FEATURE_DUPLICATE_SESSION_HANDLES feature and SHOULD
|
||||
advertise this support as detailed below. This feature is OPTIONAL.
|
||||
|
||||
6.1. Prerequisite Features
|
||||
|
||||
Implementations of this feature MUST provide and advertise
|
||||
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO [ERRNO],
|
||||
LDAP_API_FEATURE_THREAD_SAFE, LDAP_API_FEATURE_SESSION_THREAD_SAFE,
|
||||
and LDAP_API_FEATURE_ATOMIC_SESSION_HANDLES.
|
||||
|
||||
6.2. Duplicated Session Handles
|
||||
|
||||
Implementations of this feature MUST support duplicated session
|
||||
handles.
|
||||
|
||||
As defined in CAPI, a session handle refers to an LDAP session
|
||||
encompassing connections with one or more servers, associated message
|
||||
results, a set of properties (options), and state information. This
|
||||
feature provides a mechanism for a handle to be duplicated. A session
|
||||
handle and its duplicates are considered siblings. Each sibling
|
||||
session handle refers to the same LDAP session and message results.
|
||||
Some properties and state are specific to a handle and others shared
|
||||
between siblings as detailed below.
|
||||
|
||||
CAPI calls made on a handle are atomic. Calls made on sibling (or
|
||||
other) handles MAY proceed asynchronously.
|
||||
|
||||
Session handles are duplicated using ldap_dup() and destroyed using
|
||||
ldap_destroy(). Use of duplicated session handles with CAPI calls
|
||||
have the following semantics detailed in the sections below.
|
||||
|
||||
Zeilenga [Page 4]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
6.2.1. Creating and Destroying duplicated sessions
|
||||
|
||||
Implementations of this feature are required to provide two new
|
||||
routines: LDAP *ldap_dup( ld ); int ldap_destroy( ld );
|
||||
|
||||
Parameters are: ld The session handle
|
||||
|
||||
The ldap_dup() function returns a duplicate of a session handle. The
|
||||
returned session handle may be used concurrently with the original
|
||||
session handle as described below. ldap_dup returns NULL if it is not
|
||||
able to duplicate the session handle and sets LDAP_OPT_ERROR_NUMBER
|
||||
and ldap_errno indicating the nature of the failure.
|
||||
|
||||
The ldap_destroy() function destroys the session handle. If the
|
||||
session handle has no siblings, ldap_destroy behaves exactly like
|
||||
ldap_unbind. If the session handle has siblings, the resources
|
||||
assocated with the handle are released and the siblings remain valid.
|
||||
ldap_destroy() returns LDAP_SUCCESS or an error number indicating the
|
||||
nature of failure. Regardless of returned value, the handle SHOULD be
|
||||
considered invalid and MUST not be used in subsequent calls. Attempts
|
||||
to use a destroyed session handle MUST NOT result in
|
||||
LDAP_INVALID_SESSION error being reported. Implementations SHOULD
|
||||
report LDAP_PARAM_ERROR in such cases.
|
||||
|
||||
6.2.2. ldap_unbind and siblings
|
||||
|
||||
When ldap_unbind() is called on a session handle with siblings, the
|
||||
siblings become invalid. The siblings must be destroyed using
|
||||
ldap_destroy(). All attempts to obtain the siblings'
|
||||
LDAP_OPT_ERROR_NUMBER will return LDAP_INVALID_SESSION. Any use other
|
||||
than ldap_destroy() or reading LDAP_OPT_ERROR_NUMBER will fail with an
|
||||
LDAP_INVALID_SESSION error being reported.
|
||||
|
||||
6.2.3. ldap_result()
|
||||
|
||||
Message queues are shared between siblings. Results of operations on
|
||||
a duplicated session handles are accessible to all sibling session
|
||||
handles.
|
||||
|
||||
Applications desiring results associated with a specific operation
|
||||
SHOULD provide the appropriate msgid to ldap_result(). Applications
|
||||
SHOULD avoid calling ldap_result() with LDAP_RES_ANY as such may
|
||||
"steal" and return results which an operation on a sibling requires to
|
||||
complete.
|
||||
|
||||
Zeilenga [Page 5]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
6.2.4. Session Options
|
||||
|
||||
The following CAPI options access values shared between siblings:
|
||||
|
||||
LDAP_OPT_API_INFO LDAP_OPT_DESC LDAP_OPT_REFERRALS
|
||||
LDAP_OPT_PROTOCOL_VERSION LDAP_OPT_API_FEATURE_INFO
|
||||
LDAP_OPT_HOST_NAME
|
||||
|
||||
The following CAPI options access values specific to a sibling:
|
||||
|
||||
LDAP_OPT_DEREF LDAP_OPT_SIZELIMIT LDAP_OPT_TIMELIMIT
|
||||
LDAP_OPT_RESTART LDAP_OPT_CLIENT_CONTROLS
|
||||
LDAP_OPT_SERVER_CONTROLS LDAP_OPT_ERROR_NUMBER
|
||||
LDAP_OPT_ERROR_STRING LDAP_OPT_MATCHED_DN
|
||||
|
||||
6.2.4.1. LDAP_OPT_SESSION_REFCNT
|
||||
|
||||
In addition, implementations MUST provide the READ-ONLY, shared
|
||||
LDAP_OPT_SESSION_REFCNT option. LDAP_OPT_SESSION_REFCNT returns the
|
||||
reference count associated with the supplied session handle argument.
|
||||
The session handle argument is required. The outvalue argument should
|
||||
be a pointer to an integer. Example use:
|
||||
|
||||
int refcount(LDAP *ld) {
|
||||
|
||||
#ifdef LDAP_OPT_SESSION_REFCNT
|
||||
|
||||
if(ld != NULL) {
|
||||
int refcnt, rc;
|
||||
rc = ldap_get_option(ld,
|
||||
LDAP_OPT_SESSION_REFCNT, &refcnt);
|
||||
|
||||
if(rc == LDAP_OPT_SUCCESS) {
|
||||
return refcnt;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
7. Advertising Features
|
||||
|
||||
This document REQUIRES that supported features with the name in the
|
||||
form LDAP_API_FEATURE_x be advertised to consumers of the CAPI as
|
||||
|
||||
Zeilenga [Page 6]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
follows:
|
||||
|
||||
SHOULD provide the macro LDAP_API_FEATURE_x with the value
|
||||
of 1000 + revision number of this draft (i.e.: 1000+0 for
|
||||
this 0 revision of the draft).
|
||||
|
||||
MUST provide the CAPI extension "x" when returning API
|
||||
information upon LDAP_OPT_API_INFO option access, and
|
||||
|
||||
MUST provide feature info for "x" via LDAP_OPT_FEATURE_INFO
|
||||
option mechanism. The feature version provided MUST match
|
||||
the value LDAP_API_FEATURE_x macro
|
||||
|
||||
where x is replaced appropriately.
|
||||
|
||||
As implementations may not provide macros for all features,
|
||||
applications SHOULD use LDAP_OPT_API_INFO to determine which features
|
||||
are provided by a given implementation.
|
||||
|
||||
8. Changes to the C API specification
|
||||
|
||||
8.1. New Symbols
|
||||
|
||||
This extension introduces the following macros:
|
||||
|
||||
LDAP_API_FEATURE_ATOMIC_SESSION_HANDLES
|
||||
LDAP_API_FEATURE_DUPLICATE_SESSION_HANDLES
|
||||
LDAP_API_FEATURE_SESSION_THREAD_SAFE
|
||||
LDAP_API_FEATURE_THREAD_SAFE
|
||||
LDAP_API_FEATURE_OPERATION_THREAD_SAFE LDAP_INVALID_SESSION
|
||||
LDAP_OPT_SESSION_REFCNT
|
||||
|
||||
This extension introduces these new functions:
|
||||
|
||||
ldap_destroy() ldap_dup()
|
||||
|
||||
This extension introduces no new typedefs nor structure names.
|
||||
|
||||
8.2. Duplicated Session Handles
|
||||
|
||||
This extension introduces duplicated session handles and requirements
|
||||
for handling duplicated session handles. Semantics of non-duplicated
|
||||
session handles are not affected by this introduction. However, the
|
||||
semantics of calls upon duplicate session handles differs as described
|
||||
in the extension.
|
||||
|
||||
Zeilenga [Page 7]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
9. Security Considerations
|
||||
|
||||
None taken, none given.
|
||||
|
||||
10. Copyright
|
||||
|
||||
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain it
|
||||
or assist in its implementation may be prepared, copied, published and
|
||||
distributed, in whole or in part, without restriction of any kind,
|
||||
provided that the above copyright notice and this paragraph are
|
||||
included on all such copies and derivative works. However, this
|
||||
document itself may not be modified in any way, such as by removing
|
||||
the copyright notice or references to the Internet Society or other
|
||||
Internet organizations, except as needed for the purpose of
|
||||
developing Internet standards in which case the procedures for
|
||||
copyrights defined in the Internet Standards process must be followed,
|
||||
or as required to translate it into languages other than English.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked by the Internet Society or its successors or assigns.
|
||||
|
||||
This document and the information contained herein is provided on an
|
||||
"AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE INTERNET
|
||||
ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
|
||||
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
11. Bibliography
|
||||
|
||||
[CAPI] M. Smith, T. Howes, A. Herron, M. Wahl, A. Anantha, "The
|
||||
C LDAP Application Program Interface", INTERNET-DRAFT, <draft-
|
||||
ietf-ldapext-ldap-c-api-03.txt> + LDAPext discussions, June 1999.
|
||||
|
||||
[ERRNO] K. Zeilenga, "LDAP C API Error Reporting Extension",
|
||||
INTERNET-DRAFT, <draft-zeilenga-ldap-c-api-errno-00.txt>,
|
||||
June 1999.
|
||||
|
||||
[KEYW] S. Bradner, "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", RFC 2119, March 1997.
|
||||
|
||||
Zeilenga [Page 8]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Concurrency Extensions 28 September 1999
|
||||
|
||||
[LDAP] M. Wahl, T. Howes, S. Kille, "Lightweight Directory
|
||||
Access Protocol (v3)", RFC 2251, December 1997.
|
||||
|
||||
13. Author's Address
|
||||
|
||||
Kurt D. Zeilenga
|
||||
OpenLDAP Foundation
|
||||
<Kurt@OpenLDAP.org>
|
||||
|
||||
This document expires on 28 March 2000.
|
||||
|
||||
Zeilenga [Page 9]
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
INTERNET-DRAFT Kurt D. Zeilenga
|
||||
Intended Category: Standards Track OpenLDAP Foundation
|
||||
Extends: draft-ietf-ldapext-ldap-c-api-03.txt
|
||||
Expires: 28 March 2000
|
||||
28 September 1999
|
||||
|
||||
LDAP C API Error Reporting Extension
|
||||
<draft-zeilenga-ldap-c-api-errno-00.txt>
|
||||
|
||||
1. Status of this Memo
|
||||
|
||||
This document is an Internet-Draft and is in full conformance with all
|
||||
provisions of Section 10 of RFC2026.
|
||||
|
||||
This draft document will be submitted to the RFC Editor as a Standards
|
||||
Track document. Distribution of this memo is unlimited. Technical
|
||||
discussion of this document will take place on the IETF LDAP Extension
|
||||
Working Group mailing list <ietf-ldapext@netscape.com>. Please send
|
||||
editorial comments directly to the author <Kurt@OpenLDAP.org>.
|
||||
|
||||
Internet-Drafts are working documents of the Internet Engineering Task
|
||||
Force (IETF), its areas, and its working groups. Note that other
|
||||
groups may also distribute working documents as Internet-Drafts.
|
||||
|
||||
Internet-Drafts are draft documents valid for a maximum of six months
|
||||
and may be updated, replaced, or obsoleted by other documents at any
|
||||
time. It is inappropriate to use Internet-Drafts as reference
|
||||
material or to cite them other than as ``work in progress.''
|
||||
|
||||
The list of current Internet-Drafts can be accessed at
|
||||
http://www.ietf.org/ietf/1id-abstracts.txt
|
||||
|
||||
The list of Internet-Draft Shadow Directories can be accessed at
|
||||
http://www.ietf.org/shadow.html.
|
||||
|
||||
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||
|
||||
Please see the Copyright section near the end of this document for
|
||||
more information.
|
||||
|
||||
2. Abstract
|
||||
|
||||
This document defines a manatory extension to the LDAP C API to
|
||||
provide error reporting for all API calls. The mechanism is
|
||||
nonintrusive and can, optionally, support concurrent execution
|
||||
environments.
|
||||
|
||||
Zeilenga [Page 1]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||
|
||||
The key words ``MUST'', ``MUST NOT'', ``REQUIRED'', ``SHALL'', ``SHALL
|
||||
NOT'', ``SHOULD'', ``SHOULD NOT'', ``RECOMMENDED'', and ``MAY'' in
|
||||
this document are to be interpreted as described in RFC 2119 [KEYW].
|
||||
|
||||
3. Background and Intent of Use
|
||||
|
||||
The LDAP [LDAP] C API [CAPI] provides an interface which (due to
|
||||
legacy compatibiity issues) does not provide a consistent mechanism
|
||||
for reporting errors. A large number of the calls within the
|
||||
specification have no mechanism to indicate the nature of a failure.
|
||||
The usefulness of a CAPI without a consistent, easy to use, error
|
||||
reporting mechanism is limited.
|
||||
|
||||
This document defines an mandatory extension to the CAPI. All
|
||||
implementations of the CAPI MUST provide this extension.
|
||||
|
||||
The extension details additional requirements for error reporting.
|
||||
Implementations MUST fulfill all other CAPI error reporting
|
||||
requirements.
|
||||
|
||||
4. Error Handling Extension
|
||||
|
||||
This extension provides a mechanism that applications MAY use to
|
||||
obtain an LDAP error number indicating the nature of the failure
|
||||
associated with the last failed CAPI call.
|
||||
|
||||
Implementations MUST provide access to an LDAP error number (CAPI,
|
||||
Section 9) resulting from the last failed CAPI call via the symbol
|
||||
ldap_errno. The last failed CAPI call may be within the global
|
||||
context or within the current execution context.
|
||||
|
||||
The ldap_errno MUST evaluate to a modifiable lvalue that has type
|
||||
'int', the value of which is set to a LDAP error number. It is
|
||||
unspecified whether ldap_errno is a macro or an identifier declared
|
||||
with external linkage. If a macro definition is suppressed in order
|
||||
to access an actual object, or a program defines an identifier with
|
||||
the name ldap_errno, the behavior is undefined.
|
||||
|
||||
Applications MUST access ldap_errno within the same concurrent
|
||||
execution context, commonly a thread, in which the failure occurred.
|
||||
The value of ldap_errno is LDAP_SUCCESS (0) if no API failure has
|
||||
occurred within the supported context and the user has not assigned a
|
||||
value within the supported context.
|
||||
|
||||
Zeilenga [Page 2]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||
|
||||
Implementations SHALL NOT update the ldap_errno value upon successful
|
||||
CAPI call completion.
|
||||
|
||||
Implementations providing a current execution context specific
|
||||
ldap_errno MUST advertise the feature LDAP_API_CONTEXT_SPECIFIC_ERRNO
|
||||
as described in Section 6. Implementation of
|
||||
LDAP_API_CONTEXT_SPECIFIC_ERRNO is RECOMMENDED.
|
||||
|
||||
4.1. Reporting Server Errors
|
||||
|
||||
It is not a CAPI failure for a server to return an error number.
|
||||
Implementations SHALL NOT assign error results returned by servers to
|
||||
ldap_errno.
|
||||
|
||||
4.2. Implementation Specific Reporting
|
||||
|
||||
The CAPI specification stated that the caller may obtain an indication
|
||||
of failure of certain calls (see listed below) using implementation
|
||||
specific and/or operating system specific requirements.
|
||||
Implementations are NOT REQUIRED to support any implementation
|
||||
specific and/or operating system mechanism for ANY call detailed by
|
||||
the CAPI specification or its extensions.
|
||||
|
||||
Affected calls include ldap_init(), ldap_open(), and ber_*().
|
||||
|
||||
4.3. Example
|
||||
|
||||
The following is an example showing how an application may obtain the
|
||||
error information resulting from a failed CAPI calls:
|
||||
|
||||
int msgid;
|
||||
LDAP *ld = ldap_init("localhost", 389);
|
||||
|
||||
if(ld == NULL) {
|
||||
printf("ldap_init failed, ldap_errno=%d (%s)\n",
|
||||
ldap_errno, ldap_err2string(ldap_errno));
|
||||
|
||||
printf("unable to initialize LDAP session\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
msgid = ldap_simple_bind(ld, NULL, NULL);
|
||||
|
||||
if(msgid == -1) {
|
||||
int err = ldap_errno;
|
||||
|
||||
if (err != LDAP_SUCCESS ) {
|
||||
|
||||
Zeilenga [Page 3]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||
|
||||
/* API failure */
|
||||
printf("ldap_simple_bind failure: ldap_errno=%d (%s)\n",
|
||||
err, ldap_err2string(err));
|
||||
|
||||
} else {
|
||||
int lderr, rc;
|
||||
|
||||
printf("ldap_simple_bind failed\n");
|
||||
|
||||
rc = ldap_get_option(ld,
|
||||
LDAP_OPT_ERROR_NUMBER, &lderr);
|
||||
|
||||
if(rc == LDAP_OPT_SUCCESS) {
|
||||
printf(" reason=%d (%s)\n",
|
||||
lderr, ldap_err2string(lderr));
|
||||
|
||||
} else {
|
||||
printf("ldap_get_option failed, ldap_errno=%d (%s)\n",
|
||||
ldap_errno, ldap_err2string(ldap_errno)); }
|
||||
}
|
||||
|
||||
goto unbind;
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
unbind: if(ldap_unbind(ld) != 0) {
|
||||
printf("ldap_unbind failed, ldap_errno=%d (%s)\n",
|
||||
ldap_errno, ldap_error2str(ldap_errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
5. Advertising Features
|
||||
|
||||
This document REQUIRES that supported features with the name in the
|
||||
form LDAP_API_FEATURE_x be advertised to consumers of the CAPI as
|
||||
follows:
|
||||
|
||||
SHOULD provide the macro LDAP_API_FEATURE_x with the value
|
||||
of 1000 + revision number of this draft (i.e.: 1000+0 for
|
||||
this 0 revision of the draft).
|
||||
|
||||
MUST provide the CAPI extension "x" when returning API
|
||||
information upon LDAP_OPT_API_INFO option access, and
|
||||
|
||||
Zeilenga [Page 4]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||
|
||||
MUST provide feature info for "x" via LDAP_OPT_FEATURE_INFO
|
||||
option mechanism. The feature version provided MUST match
|
||||
the value LDAP_API_FEATURE_x macro
|
||||
|
||||
where x is replaced appropriately.
|
||||
|
||||
As implementations may not provide macros for all features,
|
||||
applications SHOULD use LDAP_OPT_API_INFO to determine which features
|
||||
are provided by a given implementation.
|
||||
|
||||
6. Changes to the LDAP C API
|
||||
|
||||
This section provides a summary of changes to the CAPI specification.
|
||||
|
||||
6.1. LDAP_API_VERSION
|
||||
|
||||
LDAP_API_VERSION should be set to the RFC number of this extension if
|
||||
and when it is published as a Standards Track RFC. (see purpose of
|
||||
this draft above).
|
||||
|
||||
Until such time as this document is published as an RFC,
|
||||
implementations should use the value specified by CAPI plus 100 + 10 *
|
||||
the number of this draft.
|
||||
|
||||
For the third draft of CAPI and this 0 revision of draft, the value of
|
||||
2103 ((2000+3) + (100+10*0)) should be used.
|
||||
|
||||
6.2. New Symbols
|
||||
|
||||
This extension introduces two new symbols:
|
||||
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO ldap_errno
|
||||
|
||||
LDAP_API_FEATURE_CONTEXT_SPECIFIC_ERRNO is a macro. ldap_errno MAY be
|
||||
a MACRO.
|
||||
|
||||
This extension indroductes no new functions, typedefs, or structure
|
||||
names.
|
||||
|
||||
6.3. Implementation/System Specific Error Handling
|
||||
|
||||
This extensions removes any requirements that implementations to use
|
||||
implementation and/or operating system specific error reporting
|
||||
mechanisms.
|
||||
|
||||
Zeilenga [Page 5]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||
|
||||
7. Security Considerations
|
||||
|
||||
None taken, none given.
|
||||
|
||||
8. Copyright
|
||||
|
||||
Copyright 1999, The Internet Society. All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain it
|
||||
or assist in its implementation may be prepared, copied, published and
|
||||
distributed, in whole or in part, without restriction of any kind,
|
||||
provided that the above copyright notice and this paragraph are
|
||||
included on all such copies and derivative works. However, this
|
||||
document itself may not be modified in any way, such as by removing
|
||||
the copyright notice or references to the Internet Society or other
|
||||
Internet organizations, except as needed for the purpose of
|
||||
developing Internet standards in which case the procedures for
|
||||
copyrights defined in the Internet Standards process must be followed,
|
||||
or as required to translate it into languages other than English.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked by the Internet Society or its successors or assigns.
|
||||
|
||||
This document and the information contained herein is provided on an
|
||||
"AS IS" basis and THE AUTHORS, THE INTERNET SOCIETY, AND THE INTERNET
|
||||
ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
|
||||
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
9. Bibliography
|
||||
|
||||
[CAPI] M. Smith, T. Howes, A. Herron, M. Wahl, A. Anantha,
|
||||
"The C LDAP Application Program Interface", INTERNET-DRAFT,
|
||||
<draft-ietf-ldapext-ldap-c-api-03.txt> + LDAPext discussions,
|
||||
June 1999.
|
||||
|
||||
[KEYW] S. Bradner, "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", RFC 2119, March 1997.
|
||||
|
||||
[LDAP] M. Wahl, T. Howes, S. Kille, "Lightweight Directory
|
||||
Access Protocol (v3)", RFC 2251, December 1997.
|
||||
|
||||
Zeilenga [Page 6]
|
||||
|
||||
INTERNET-DRAFT LDAP C API Error Reporting Extension 28 September 1999
|
||||
|
||||
10. Author's Address
|
||||
|
||||
Kurt D. Zeilenga
|
||||
OpenLDAP Foundation
|
||||
<Kurt@OpenLDAP.org>
|
||||
|
||||
This document expires on 28 March 2000.
|
||||
|
||||
Zeilenga [Page 7]
|
126
doc/man/man3/ldap_dup.3
Normal file
126
doc/man/man3/ldap_dup.3
Normal file
@ -0,0 +1,126 @@
|
||||
.TH LDAP_OPEN 3 "RELEASEDATE" "OpenLDAP LDVERSION"
|
||||
.\" $OpenLDAP$
|
||||
.\" Copyright 1998-2010 The OpenLDAP Foundation All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
ldap_dup, ldap_destroy, \- Duplicate and destroy LDAP session handles
|
||||
.SH LIBRARY
|
||||
OpenLDAP LDAP (libldap, \-lldap)
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.ft B
|
||||
#include <ldap.h>
|
||||
.LP
|
||||
.ft B
|
||||
LDAP *ldap_dup(
|
||||
.RS
|
||||
.ft B
|
||||
LDAP *\fIold\fB );
|
||||
.RE
|
||||
.LP
|
||||
.ft B
|
||||
int ldap_destroy(
|
||||
.RS
|
||||
.ft B
|
||||
LDAP *\fIold\fB );
|
||||
.RE
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
.B ldap_dup()
|
||||
duplicates an existing LDAP
|
||||
.RB ( "LDAP *" )
|
||||
session handle.
|
||||
The new session handle may be used concurrently with the
|
||||
original session handle.
|
||||
In a threaded environment, different threads may execute concurrent
|
||||
requests on the same connection/session without fear of contamination.
|
||||
Each session handle manages its own private error results.
|
||||
.LP
|
||||
.B ldap_destroy()
|
||||
destroys an existing session handle.
|
||||
.LP
|
||||
The
|
||||
.B ldap_dup()
|
||||
and
|
||||
.B ldap_destroy()
|
||||
functions are used in conjunction with a "thread safe" version
|
||||
of
|
||||
.B libldap
|
||||
.RB ( libldap_r )
|
||||
to enable operation thread safe API calls, so that a single session
|
||||
may be simultaneously used across multiple threads with consistent
|
||||
error handling.
|
||||
.LP
|
||||
When a session is created through the use of one of the session creation
|
||||
functions including
|
||||
.BR ldap_open (3),
|
||||
.BR ldap_init (3),
|
||||
.BR ldap_initialize (3)
|
||||
or
|
||||
.BR ldap_init_fd (3)
|
||||
an
|
||||
.B "LDAP *"
|
||||
session handle is returned to the application.
|
||||
The session handle may be shared amongst threads, however the
|
||||
error codes are unique to a session handle.
|
||||
Multiple threads performing different operations using the same
|
||||
session handle will result in inconsistent error codes and
|
||||
return values.
|
||||
.LP
|
||||
To prevent this confusion,
|
||||
.B ldap_dup()
|
||||
is used duplicate an existing session handle so that multiple threads
|
||||
can share the session, and maintain consistent error information
|
||||
and results.
|
||||
.LP
|
||||
The message queues for a session are shared between sibling session handles.
|
||||
Results of operations on a sibling session handles are accessible
|
||||
to all the sibling session handles.
|
||||
Applications desiring results associated with a specific operation
|
||||
should provide the appropriate msgid to
|
||||
.BR ldap_result() .
|
||||
Applications should avoid calling
|
||||
.B ldap_result()
|
||||
with
|
||||
.B LDAP_RES_ANY
|
||||
as that may "steal" and return results in the calling thread
|
||||
that another operation in a different thread, using a
|
||||
different session handle, may require to complete.
|
||||
.LP
|
||||
When
|
||||
.B ldap_unbind()
|
||||
is called on a session handle with siblings, all the
|
||||
siblings become invalid.
|
||||
.LP
|
||||
Siblings must be destroyed using
|
||||
.BR ldap_destroy() .
|
||||
Session handle resources associated with the original
|
||||
.RB ( "LDAP *" )
|
||||
will be freed when the last session handle is destroyed or when
|
||||
.B ldap_unbind()
|
||||
is called, if no other session handles currently exist.
|
||||
.SH ERRORS
|
||||
If an error occurs,
|
||||
.B ldap_dup()
|
||||
will return NULL and
|
||||
.I errno
|
||||
should be set appropriately.
|
||||
.B ldap_destroy()
|
||||
will directly return the LDAP code associated to the error (or
|
||||
.I LDAP_SUCCESS
|
||||
in case of success);
|
||||
.I errno
|
||||
should be set as well whenever appropriate.
|
||||
.SH SEE ALSO
|
||||
.BR ldap_open (3),
|
||||
.BR ldap_init (3),
|
||||
.BR ldap_initialize (3),
|
||||
.BR ldap_init_fd (3),
|
||||
.BR errno (3)
|
||||
.SH ACKNOWLEDGEMENTS
|
||||
This work is based on the previously proposed
|
||||
.B LDAP C API Concurrency Extensions
|
||||
draft
|
||||
.BR ( draft-zeilenga-ldap-c-api-concurrency-00.txt )
|
||||
effort.
|
||||
.so ../Project
|
1
doc/man/man3/ldap_dup.3.links
Normal file
1
doc/man/man3/ldap_dup.3.links
Normal file
@ -0,0 +1 @@
|
||||
ldap_destroy.3
|
@ -322,6 +322,15 @@ must be
|
||||
the library duplicates the controls passed via
|
||||
.BR invalue .
|
||||
.TP
|
||||
.B LDAP_OPT_SESSION_REFCNT
|
||||
Returns the reference count associated with the LDAP handle passed in as
|
||||
.BR ld ;
|
||||
.BR outvalue
|
||||
must be a
|
||||
.BR "int *" .
|
||||
This is a read-only, handle-specific option.
|
||||
This option is OpenLDAP specific.
|
||||
.TP
|
||||
.B LDAP_OPT_SIZELIMIT
|
||||
Sets/gets the value that defines the maximum number of entries
|
||||
to be returned by a search operation.
|
||||
|
@ -59,7 +59,9 @@ LDAP_BEGIN_DECL
|
||||
defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) )
|
||||
/* -lldap may or may not be thread safe */
|
||||
/* -lldap_r, if available, is always thread safe */
|
||||
# define LDAP_API_FEATURE_THREAD_SAFE 1
|
||||
# define LDAP_API_FEATURE_THREAD_SAFE 1
|
||||
# define LDAP_API_FEATURE_SESSION_THREAD_SAFE 1
|
||||
# define LDAP_API_FEATURE_OPERATION_THREAD_SAFE 1
|
||||
#endif
|
||||
#if defined( LDAP_THREAD_SAFE ) && \
|
||||
defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE )
|
||||
@ -135,6 +137,7 @@ LDAP_BEGIN_DECL
|
||||
#define LDAP_OPT_DEFBASE 0x5009 /* searchbase */
|
||||
#define LDAP_OPT_CONNECT_ASYNC 0x5010 /* create connections asynchronously */
|
||||
#define LDAP_OPT_CONNECT_CB 0x5011 /* connection callbacks */
|
||||
#define LDAP_OPT_SESSION_REFCNT 0x5012 /* session reference count */
|
||||
|
||||
/* OpenLDAP TLS options */
|
||||
#define LDAP_OPT_X_TLS 0x6000
|
||||
@ -1519,6 +1522,10 @@ ldap_initialize LDAP_P((
|
||||
LDAP **ldp,
|
||||
LDAP_CONST char *url ));
|
||||
|
||||
LDAP_F( LDAP * )
|
||||
ldap_dup LDAP_P((
|
||||
LDAP *old ));
|
||||
|
||||
/*
|
||||
* in tls.c
|
||||
*/
|
||||
@ -1931,6 +1938,10 @@ ldap_unbind_ext_s LDAP_P((
|
||||
LDAPControl **serverctrls,
|
||||
LDAPControl **clientctrls));
|
||||
|
||||
LDAP_F( int )
|
||||
ldap_destroy LDAP_P((
|
||||
LDAP *ld));
|
||||
|
||||
#if LDAP_DEPRECATED
|
||||
LDAP_F( int )
|
||||
ldap_unbind LDAP_P(( /* deprecated, use ldap_unbind_ext */
|
||||
|
@ -69,6 +69,11 @@ typedef pthread_key_t ldap_int_thread_key_t;
|
||||
typedef pthread_rwlock_t ldap_int_thread_rdwr_t;
|
||||
#endif
|
||||
|
||||
#ifndef LDO_MUTEX_NULL
|
||||
#define LDO_MUTEX_NULL ,PTHREAD_MUTEX_INITIALIZER
|
||||
#define MUTEX_FIRSTCREATE(m)
|
||||
#endif
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#elif defined ( HAVE_MACH_CTHREADS )
|
||||
@ -91,6 +96,11 @@ typedef struct mutex ldap_int_thread_mutex_t;
|
||||
typedef struct condition ldap_int_thread_cond_t;
|
||||
typedef cthread_key_t ldap_int_thread_key_t;
|
||||
|
||||
#ifndef LDO_MUTEX_NULL
|
||||
#define LDO_MUTEX_NULL ,MUTEX_INITIALIZER
|
||||
#define MUTEX_FIRSTCREATE(m)
|
||||
#endif
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#elif defined( HAVE_GNU_PTH )
|
||||
@ -115,6 +125,11 @@ typedef pth_key_t ldap_int_thread_key_t;
|
||||
typedef pth_rwlock_t ldap_int_thread_rdwr_t;
|
||||
#endif
|
||||
|
||||
#ifndef LDO_MUTEX_NULL
|
||||
#define LDO_MUTEX_NULL ,PTH_MUTEX_INIT
|
||||
#define MUTEX_FIRSTCREATE(m)
|
||||
#endif
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#elif defined( HAVE_THR )
|
||||
@ -143,7 +158,10 @@ typedef thread_key_t ldap_int_thread_key_t;
|
||||
#define LDAP_THREAD_HAVE_SETCONCURRENCY 1
|
||||
#endif
|
||||
|
||||
LDAP_END_DECL
|
||||
#ifndef LDO_MUTEX_NULL
|
||||
#define LDO_MUTEX_NULL ,DEFAULTMUTEX
|
||||
#define MUTEX_FIRSTCREATE(m)
|
||||
#endif
|
||||
|
||||
#elif defined(HAVE_NT_THREADS)
|
||||
/*************************************
|
||||
@ -162,6 +180,11 @@ typedef HANDLE ldap_int_thread_mutex_t;
|
||||
typedef HANDLE ldap_int_thread_cond_t;
|
||||
typedef DWORD ldap_int_thread_key_t;
|
||||
|
||||
#ifndef LDO_MUTEX_NULL
|
||||
#define LDO_MUTEX_NULL ,(HANDLE)0
|
||||
#define MUTEX_FIRSTCREATE(m) (!m ? 0 : ldap_pvt_thread_mutex_init(&m) )
|
||||
#endif
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#else
|
||||
@ -186,6 +209,11 @@ typedef int ldap_int_thread_key_t;
|
||||
#define LDAP_THREAD_HAVE_TPOOL 1
|
||||
typedef int ldap_int_thread_pool_t;
|
||||
|
||||
#ifndef LDO_MUTEX_NULL
|
||||
#define LDO_MUTEX_NULL
|
||||
#define MUTEX_FIRSTCREATE(m)
|
||||
#endif
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* no threads support */
|
||||
|
@ -206,7 +206,7 @@ start_again:;
|
||||
* LDAP_NEXT_MSGID(ld, i);
|
||||
*/
|
||||
|
||||
i = ++(ld)->ld_msgid;
|
||||
LDAP_NEXT_MSGID(ld, i);
|
||||
#ifdef LDAP_CONNECTIONLESS
|
||||
if ( LDAP_IS_UDP(ld) ) {
|
||||
struct sockaddr sa = {0};
|
||||
@ -216,11 +216,14 @@ start_again:;
|
||||
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
|
||||
LDAP_VERSION2 )
|
||||
{
|
||||
char *dn = ld->ld_options.ldo_cldapdn;
|
||||
char *dn;
|
||||
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
|
||||
dn = ld->ld_options.ldo_cldapdn;
|
||||
if (!dn) dn = "";
|
||||
err = ber_printf( ber, "{isti", /* '}' */
|
||||
i, dn,
|
||||
LDAP_REQ_ABANDON, msgid );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -287,10 +290,7 @@ start_again:;
|
||||
}
|
||||
}
|
||||
|
||||
/* ld_abandoned is actually protected by the ld_res_mutex;
|
||||
* give up the ld_req_mutex and get the other */
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
|
||||
|
||||
/* use bisection */
|
||||
i = 0;
|
||||
@ -304,8 +304,7 @@ start_again:;
|
||||
ld->ld_errno = LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||
return( ld->ld_errno );
|
||||
}
|
||||
|
||||
|
@ -416,7 +416,7 @@ ldap_int_sasl_bind(
|
||||
void *ssl;
|
||||
|
||||
rc = 0;
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
|
||||
|
||||
if ( sd == AC_SOCKET_INVALID ) {
|
||||
@ -434,7 +434,7 @@ ldap_int_sasl_bind(
|
||||
}
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
if( rc != 0 ) return ld->ld_errno;
|
||||
|
||||
oldctx = ld->ld_defconn->lconn_sasl_authctx;
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "lutil.h"
|
||||
|
||||
struct ldapoptions ldap_int_global_options =
|
||||
{ LDAP_UNINITIALIZED, LDAP_DEBUG_NONE };
|
||||
{ LDAP_UNINITIALIZED, LDAP_DEBUG_NONE LDO_MUTEX_NULL };
|
||||
|
||||
#define ATTR_NONE 0
|
||||
#define ATTR_BOOL 1
|
||||
@ -510,6 +510,13 @@ ldap_int_destroy_global_options(void)
|
||||
*/
|
||||
void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl )
|
||||
{
|
||||
MUTEX_FIRSTCREATE(gopts->ldo_mutex);
|
||||
LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
|
||||
if (gopts->ldo_valid == LDAP_INITIALIZED) {
|
||||
/* someone else got here first */
|
||||
LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
|
||||
return;
|
||||
}
|
||||
if (dbglvl)
|
||||
gopts->ldo_debug = *dbglvl;
|
||||
else
|
||||
@ -573,6 +580,7 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl
|
||||
gopts->ldo_keepalive_idle = 0;
|
||||
|
||||
gopts->ldo_valid = LDAP_INITIALIZED;
|
||||
LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -174,6 +174,7 @@ typedef struct ldaplist {
|
||||
/*
|
||||
* structure representing get/set'able options
|
||||
* which have global defaults.
|
||||
* Protect access to this struct with ldo_mutex
|
||||
*/
|
||||
struct ldapoptions {
|
||||
short ldo_valid;
|
||||
@ -182,6 +183,12 @@ struct ldapoptions {
|
||||
#define LDAP_VALID_SESSION 0x2
|
||||
#define LDAP_TRASHED_SESSION 0xFF
|
||||
int ldo_debug;
|
||||
#ifdef LDAP_R_COMPILE
|
||||
ldap_pvt_thread_mutex_t ldo_mutex;
|
||||
#else
|
||||
#define LDO_MUTEX_NULL
|
||||
#define MUTEX_FIRSTCREATE(m)
|
||||
#endif
|
||||
#ifdef LDAP_CONNECTIONLESS
|
||||
#define LDAP_IS_UDP(ld) ((ld)->ld_options.ldo_is_udp)
|
||||
void* ldo_peer; /* struct sockaddr* */
|
||||
@ -361,24 +368,27 @@ typedef struct ldapreqinfo {
|
||||
* structure representing an ldap connection
|
||||
*/
|
||||
|
||||
struct ldap {
|
||||
Sockbuf *ld_sb; /* socket descriptor & buffer */
|
||||
struct ldap_common {
|
||||
Sockbuf *ldc_sb; /* socket descriptor & buffer */
|
||||
#define ld_sb ldc->ldc_sb
|
||||
|
||||
struct ldapoptions ld_options;
|
||||
/* protected by ldo_mutex */
|
||||
struct ldapoptions ldc_options;
|
||||
#define ld_options ldc->ldc_options
|
||||
|
||||
#define ld_valid ld_options.ldo_valid
|
||||
#define ld_debug ld_options.ldo_debug
|
||||
|
||||
#define ld_deref ld_options.ldo_deref
|
||||
#define ld_timelimit ld_options.ldo_timelimit
|
||||
#define ld_sizelimit ld_options.ldo_sizelimit
|
||||
#define ld_timelimit ld_options.ldo_timelimit
|
||||
#define ld_sizelimit ld_options.ldo_sizelimit
|
||||
|
||||
#define ld_defbinddn ld_options.ldo_defbinddn
|
||||
#define ld_defbinddn ld_options.ldo_defbinddn
|
||||
#define ld_defbase ld_options.ldo_defbase
|
||||
#define ld_defhost ld_options.ldo_defhost
|
||||
#define ld_defport ld_options.ldo_defport
|
||||
|
||||
#define ld_refhoplimit ld_options.ldo_refhoplimit
|
||||
#define ld_refhoplimit ld_options.ldo_refhoplimit
|
||||
|
||||
#define ld_sctrls ld_options.ldo_sctrls
|
||||
#define ld_cctrls ld_options.ldo_cctrls
|
||||
@ -390,36 +400,79 @@ struct ldap {
|
||||
#define ld_urllist_params ld_options.ldo_urllist_params
|
||||
|
||||
#define ld_version ld_options.ldo_version
|
||||
|
||||
unsigned short ld_lberoptions;
|
||||
|
||||
ber_int_t ld_errno;
|
||||
char *ld_error;
|
||||
char *ld_matched;
|
||||
char **ld_referrals;
|
||||
ber_len_t ld_msgid;
|
||||
|
||||
/* do not mess with these */
|
||||
LDAPRequest *ld_requests; /* list of outstanding requests */
|
||||
LDAPMessage *ld_responses; /* list of outstanding responses */
|
||||
|
||||
#ifdef LDAP_R_COMPILE
|
||||
ldap_pvt_thread_mutex_t ld_conn_mutex;
|
||||
ldap_pvt_thread_mutex_t ld_req_mutex;
|
||||
ldap_pvt_thread_mutex_t ld_res_mutex;
|
||||
#define ld_ldopts_mutex ld_options.ldo_mutex
|
||||
#endif
|
||||
|
||||
ber_len_t ld_nabandoned;
|
||||
ber_int_t *ld_abandoned; /* array of abandoned requests */
|
||||
unsigned short ldc_lberoptions;
|
||||
#define ld_lberoptions ldc->ldc_lberoptions
|
||||
|
||||
LDAPCache *ld_cache; /* non-null if cache is initialized */
|
||||
/* protected by msgid_mutex */
|
||||
ber_len_t ldc_msgid;
|
||||
#define ld_msgid ldc->ldc_msgid
|
||||
|
||||
/* do not mess with these */
|
||||
/* protected by req_mutex */
|
||||
LDAPRequest *ldc_requests; /* list of outstanding requests */
|
||||
/* protected by res_mutex */
|
||||
LDAPMessage *ldc_responses; /* list of outstanding responses */
|
||||
#define ld_requests ldc->ldc_requests
|
||||
#define ld_responses ldc->ldc_responses
|
||||
|
||||
#ifdef LDAP_R_COMPILE
|
||||
ldap_pvt_thread_mutex_t ldc_msgid_mutex;
|
||||
ldap_pvt_thread_mutex_t ldc_conn_mutex;
|
||||
ldap_pvt_thread_mutex_t ldc_req_mutex;
|
||||
ldap_pvt_thread_mutex_t ldc_res_mutex;
|
||||
ldap_pvt_thread_mutex_t ldc_abandon_mutex;
|
||||
#define ld_msgid_mutex ldc->ldc_msgid_mutex
|
||||
#define ld_conn_mutex ldc->ldc_conn_mutex
|
||||
#define ld_req_mutex ldc->ldc_req_mutex
|
||||
#define ld_res_mutex ldc->ldc_res_mutex
|
||||
#define ld_abandon_mutex ldc->ldc_abandon_mutex
|
||||
#endif
|
||||
|
||||
/* protected by abandon_mutex */
|
||||
ber_len_t ldc_nabandoned;
|
||||
ber_int_t *ldc_abandoned; /* array of abandoned requests */
|
||||
#define ld_nabandoned ldc->ldc_nabandoned
|
||||
#define ld_abandoned ldc->ldc_abandoned
|
||||
|
||||
/* unused by libldap */
|
||||
LDAPCache *ldc_cache; /* non-null if cache is initialized */
|
||||
#define ld_cache ldc->ldc_cache
|
||||
|
||||
/* do not mess with the rest though */
|
||||
|
||||
LDAPConn *ld_defconn; /* default connection */
|
||||
LDAPConn *ld_conns; /* list of server connections */
|
||||
void *ld_selectinfo; /* platform specifics for select */
|
||||
/* protected by conn_mutex */
|
||||
LDAPConn *ldc_defconn; /* default connection */
|
||||
#define ld_defconn ldc->ldc_defconn
|
||||
LDAPConn *ldc_conns; /* list of server connections */
|
||||
#define ld_conns ldc->ldc_conns
|
||||
void *ldc_selectinfo;/* platform specifics for select */
|
||||
#define ld_selectinfo ldc->ldc_selectinfo
|
||||
|
||||
/* ldap_common refcnt - free only if 0 */
|
||||
#ifdef LDAP_R_COMPILE
|
||||
ldap_pvt_thread_mutex_t ldc_mutex;
|
||||
#define ld_ldcmutex ldc->ldc_mutex
|
||||
#endif
|
||||
/* protected by ldc_mutex */
|
||||
unsigned int ldc_refcnt;
|
||||
#define ld_ldcrefcnt ldc->ldc_refcnt
|
||||
};
|
||||
|
||||
struct ldap {
|
||||
/* thread shared */
|
||||
struct ldap_common *ldc;
|
||||
|
||||
/* thread specific */
|
||||
ber_int_t ld_errno;
|
||||
char *ld_error;
|
||||
char *ld_matched;
|
||||
char **ld_referrals;
|
||||
};
|
||||
|
||||
#define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION )
|
||||
#define LDAP_TRASHED(ld) ( (ld)->ld_valid == LDAP_TRASHED_SESSION )
|
||||
#define LDAP_TRASH(ld) ( (ld)->ld_valid = LDAP_TRASHED_SESSION )
|
||||
@ -448,9 +501,9 @@ LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_gssapi_mutex;
|
||||
|
||||
#ifdef LDAP_R_COMPILE
|
||||
#define LDAP_NEXT_MSGID(ld, id) \
|
||||
LDAP_MUTEX_LOCK( &(ld)->ld_req_mutex ); \
|
||||
LDAP_MUTEX_LOCK( &(ld)->ld_msgid_mutex ); \
|
||||
id = ++(ld)->ld_msgid; \
|
||||
LDAP_MUTEX_UNLOCK( &(ld)->ld_req_mutex )
|
||||
LDAP_MUTEX_UNLOCK( &(ld)->ld_msgid_mutex )
|
||||
#else
|
||||
#define LDAP_NEXT_MSGID(ld, id) id = ++(ld)->ld_msgid
|
||||
#endif
|
||||
@ -584,8 +637,11 @@ LDAP_F (ber_int_t) ldap_send_initial_request( LDAP *ld, ber_tag_t msgtype,
|
||||
LDAP_F (BerElement *) ldap_alloc_ber_with_options( LDAP *ld );
|
||||
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 (int) ldap_send_server_request( LDAP *ld, BerElement *ber,
|
||||
ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist,
|
||||
LDAPConn *lc, LDAPreqinfo *bind, int noconn, int m_res );
|
||||
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 (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
|
||||
|
@ -35,11 +35,11 @@
|
||||
#include "ldap-int.h"
|
||||
#include "ldap_log.h"
|
||||
|
||||
/* Caller should hold the req_mutex if simultaneous accesses are possible */
|
||||
/* Caller must hold the conn_mutex since simultaneous accesses are possible */
|
||||
int ldap_open_defconn( LDAP *ld )
|
||||
{
|
||||
ld->ld_defconn = ldap_new_connection( ld,
|
||||
&ld->ld_options.ldo_defludp, 1, 1, NULL );
|
||||
&ld->ld_options.ldo_defludp, 1, 1, NULL, 0, 0 );
|
||||
|
||||
if( ld->ld_defconn == NULL ) {
|
||||
ld->ld_errno = LDAP_SERVER_DOWN;
|
||||
@ -74,7 +74,9 @@ ldap_open( LDAP_CONST char *host, int port )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
rc = ldap_open_defconn( ld );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
|
||||
if( rc < 0 ) {
|
||||
ldap_ld_free( ld, 0, NULL, NULL );
|
||||
@ -114,8 +116,19 @@ ldap_create( LDAP **ldp )
|
||||
return( LDAP_NO_MEMORY );
|
||||
}
|
||||
|
||||
if ( (ld->ldc = (struct ldap_common *) LDAP_CALLOC( 1,
|
||||
sizeof(struct ldap_common) )) == NULL ) {
|
||||
LDAP_FREE( (char *)ld );
|
||||
return( LDAP_NO_MEMORY );
|
||||
}
|
||||
/* copy the global options */
|
||||
LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
|
||||
AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
|
||||
#ifdef LDAP_R_COMPILE
|
||||
/* Properly initialize the structs mutex */
|
||||
ldap_pvt_thread_mutex_init( &(ld->ld_ldopts_mutex) );
|
||||
#endif
|
||||
LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
|
||||
|
||||
ld->ld_valid = LDAP_VALID_SESSION;
|
||||
|
||||
@ -159,10 +172,14 @@ ldap_create( LDAP **ldp )
|
||||
if ( ld->ld_sb == NULL ) goto nomem;
|
||||
|
||||
#ifdef LDAP_R_COMPILE
|
||||
ldap_pvt_thread_mutex_init( &ld->ld_msgid_mutex );
|
||||
ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
|
||||
ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
|
||||
ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
|
||||
ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
|
||||
ldap_pvt_thread_mutex_init( &ld->ld_abandon_mutex );
|
||||
ldap_pvt_thread_mutex_init( &ld->ld_ldcmutex );
|
||||
#endif
|
||||
ld->ld_ldcrefcnt = 1;
|
||||
*ldp = ld;
|
||||
return LDAP_SUCCESS;
|
||||
|
||||
@ -265,8 +282,9 @@ ldap_init_fd(
|
||||
}
|
||||
}
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
/* Attach the passed socket as the LDAP's connection */
|
||||
conn = ldap_new_connection( ld, NULL, 1, 0, NULL);
|
||||
conn = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
|
||||
if( conn == NULL ) {
|
||||
ldap_unbind_ext( ld, NULL, NULL );
|
||||
return( LDAP_NO_MEMORY );
|
||||
@ -276,6 +294,7 @@ ldap_init_fd(
|
||||
ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
|
||||
ld->ld_defconn = conn;
|
||||
++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
|
||||
switch( proto ) {
|
||||
case LDAP_PROTO_TCP:
|
||||
@ -331,6 +350,7 @@ ldap_init_fd(
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* Protected by ld_conn_mutex */
|
||||
int
|
||||
ldap_int_open_connection(
|
||||
LDAP *ld,
|
||||
@ -434,8 +454,9 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
|
||||
int rc;
|
||||
LDAPConn *c;
|
||||
LDAPRequest *lr;
|
||||
LDAP *ld;
|
||||
|
||||
rc = ldap_create( ldp );
|
||||
rc = ldap_create( &ld );
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
*ldp = NULL;
|
||||
return( rc );
|
||||
@ -444,7 +465,7 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
|
||||
/* Make it appear that a search request, msgid 0, was sent */
|
||||
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
|
||||
if( lr == NULL ) {
|
||||
ldap_unbind_ext( *ldp, NULL, NULL );
|
||||
ldap_unbind_ext( ld, NULL, NULL );
|
||||
*ldp = NULL;
|
||||
return( LDAP_NO_MEMORY );
|
||||
}
|
||||
@ -453,13 +474,15 @@ 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 */
|
||||
(*ldp)->ld_requests = lr;
|
||||
ld->ld_requests = lr;
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
/* Attach the passed socket as the *LDAP's connection */
|
||||
c = ldap_new_connection( *ldp, NULL, 1, 0, NULL);
|
||||
c = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
|
||||
if( c == NULL ) {
|
||||
ldap_unbind_ext( *ldp, NULL, NULL );
|
||||
ldap_unbind_ext( ld, NULL, NULL );
|
||||
*ldp = NULL;
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
return( LDAP_NO_MEMORY );
|
||||
}
|
||||
ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
|
||||
@ -469,15 +492,39 @@ ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
|
||||
#endif
|
||||
ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
|
||||
LBER_SBIOD_LEVEL_PROVIDER, NULL );
|
||||
(*ldp)->ld_defconn = c;
|
||||
ld->ld_defconn = c;
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
|
||||
/* Add the connection to the *LDAP's select pool */
|
||||
ldap_mark_select_read( *ldp, c->lconn_sb );
|
||||
ldap_mark_select_write( *ldp, c->lconn_sb );
|
||||
ldap_mark_select_read( ld, c->lconn_sb );
|
||||
ldap_mark_select_write( ld, c->lconn_sb );
|
||||
|
||||
/* Make this connection an LDAP V3 protocol connection */
|
||||
rc = LDAP_VERSION3;
|
||||
ldap_set_option( *ldp, LDAP_OPT_PROTOCOL_VERSION, &rc );
|
||||
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &rc );
|
||||
*ldp = ld;
|
||||
|
||||
return( LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
LDAP *
|
||||
ldap_dup( LDAP *old )
|
||||
{
|
||||
LDAP *ld;
|
||||
|
||||
if ( old == NULL ) {
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_dup\n", 0, 0, 0 );
|
||||
|
||||
if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
LDAP_MUTEX_LOCK( &old->ld_ldcmutex );
|
||||
ld->ldc = old->ldc;
|
||||
old->ld_ldcrefcnt++;
|
||||
LDAP_MUTEX_UNLOCK( &old->ld_ldcmutex );
|
||||
return ( ld );
|
||||
}
|
||||
|
@ -96,6 +96,7 @@ ldap_get_option(
|
||||
void *outvalue)
|
||||
{
|
||||
struct ldapoptions *lo;
|
||||
int rc = LDAP_OPT_ERROR;
|
||||
|
||||
/* Get pointer to global option structure */
|
||||
lo = LDAP_INT_GLOBAL_OPT();
|
||||
@ -122,19 +123,21 @@ ldap_get_option(
|
||||
return LDAP_OPT_ERROR;
|
||||
}
|
||||
|
||||
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||
|
||||
switch(option) {
|
||||
case LDAP_OPT_API_INFO: {
|
||||
struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
|
||||
|
||||
if(info == NULL) {
|
||||
/* outvalue must point to an apiinfo structure */
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
|
||||
if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
|
||||
/* api info version mismatch */
|
||||
info->ldapai_info_version = LDAP_API_INFO_VERSION;
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
|
||||
info->ldapai_api_version = LDAP_API_VERSION;
|
||||
@ -158,7 +161,8 @@ ldap_get_option(
|
||||
info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
|
||||
info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
|
||||
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
} break;
|
||||
|
||||
case LDAP_OPT_DESC:
|
||||
@ -168,74 +172,86 @@ ldap_get_option(
|
||||
}
|
||||
|
||||
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_SOCKBUF:
|
||||
if( ld == NULL ) break;
|
||||
*(Sockbuf **)outvalue = ld->ld_sb;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_TIMEOUT:
|
||||
/* the caller has to free outvalue ! */
|
||||
if ( lo->ldo_tm_api.tv_sec < 0 ) {
|
||||
*(void **)outvalue = NULL;
|
||||
} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) {
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_NETWORK_TIMEOUT:
|
||||
/* the caller has to free outvalue ! */
|
||||
if ( lo->ldo_tm_net.tv_sec < 0 ) {
|
||||
*(void **)outvalue = NULL;
|
||||
} else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) {
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_DEREF:
|
||||
* (int *) outvalue = lo->ldo_deref;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_SIZELIMIT:
|
||||
* (int *) outvalue = lo->ldo_sizelimit;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_TIMELIMIT:
|
||||
* (int *) outvalue = lo->ldo_timelimit;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_REFERRALS:
|
||||
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_RESTART:
|
||||
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_PROTOCOL_VERSION:
|
||||
* (int *) outvalue = lo->ldo_version;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_SERVER_CONTROLS:
|
||||
* (LDAPControl ***) outvalue =
|
||||
ldap_controls_dup( lo->ldo_sctrls );
|
||||
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_CLIENT_CONTROLS:
|
||||
* (LDAPControl ***) outvalue =
|
||||
ldap_controls_dup( lo->ldo_cctrls );
|
||||
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_HOST_NAME:
|
||||
* (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_URI:
|
||||
* (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_DEFBASE:
|
||||
if( lo->ldo_defbase == NULL ) {
|
||||
@ -243,12 +259,13 @@ ldap_get_option(
|
||||
} else {
|
||||
* (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
|
||||
}
|
||||
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_CONNECT_ASYNC:
|
||||
* (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_CONNECT_CB:
|
||||
{
|
||||
@ -263,7 +280,8 @@ ldap_get_option(
|
||||
}
|
||||
}
|
||||
}
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_RESULT_CODE:
|
||||
if(ld == NULL) {
|
||||
@ -271,7 +289,8 @@ ldap_get_option(
|
||||
break;
|
||||
}
|
||||
* (int *) outvalue = ld->ld_errno;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_DIAGNOSTIC_MESSAGE:
|
||||
if(ld == NULL) {
|
||||
@ -284,8 +303,8 @@ ldap_get_option(
|
||||
} else {
|
||||
* (char **) outvalue = LDAP_STRDUP(ld->ld_error);
|
||||
}
|
||||
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_MATCHED_DN:
|
||||
if(ld == NULL) {
|
||||
@ -298,8 +317,8 @@ ldap_get_option(
|
||||
} else {
|
||||
* (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
|
||||
}
|
||||
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_REFERRAL_URLS:
|
||||
if(ld == NULL) {
|
||||
@ -312,28 +331,31 @@ ldap_get_option(
|
||||
} else {
|
||||
* (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
|
||||
}
|
||||
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_API_FEATURE_INFO: {
|
||||
LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
|
||||
int i;
|
||||
|
||||
if(info == NULL) return LDAP_OPT_ERROR;
|
||||
if(info == NULL)
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
|
||||
if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
|
||||
/* api info version mismatch */
|
||||
info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
|
||||
if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
|
||||
if(info->ldapaif_name == NULL)
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
|
||||
for(i=0; features[i].ldapaif_name != NULL; i++) {
|
||||
if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
|
||||
info->ldapaif_version =
|
||||
features[i].ldapaif_version;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -341,41 +363,54 @@ ldap_get_option(
|
||||
|
||||
case LDAP_OPT_DEBUG_LEVEL:
|
||||
* (int *) outvalue = lo->ldo_debug;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_SESSION_REFCNT:
|
||||
* (int *) outvalue = ld->ld_ldcrefcnt;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_X_KEEPALIVE_IDLE:
|
||||
* (int *) outvalue = lo->ldo_keepalive_idle;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_X_KEEPALIVE_PROBES:
|
||||
* (int *) outvalue = lo->ldo_keepalive_probes;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_X_KEEPALIVE_INTERVAL:
|
||||
* (int *) outvalue = lo->ldo_keepalive_interval;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef HAVE_TLS
|
||||
if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_CYRUS_SASL
|
||||
if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_GSSAPI
|
||||
if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* bad param */
|
||||
break;
|
||||
}
|
||||
|
||||
return LDAP_OPT_ERROR;
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
return ( rc );
|
||||
}
|
||||
|
||||
int
|
||||
@ -386,6 +421,7 @@ ldap_set_option(
|
||||
{
|
||||
struct ldapoptions *lo;
|
||||
int *dbglvl = NULL;
|
||||
int rc = LDAP_OPT_ERROR;
|
||||
|
||||
/* Get pointer to global option structure */
|
||||
lo = LDAP_INT_GLOBAL_OPT();
|
||||
@ -416,14 +452,19 @@ ldap_set_option(
|
||||
lo = &ld->ld_options;
|
||||
}
|
||||
|
||||
switch(option) {
|
||||
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||
|
||||
switch ( option ) {
|
||||
|
||||
/* options with boolean values */
|
||||
case LDAP_OPT_REFERRALS:
|
||||
if(invalue == LDAP_OPT_OFF) {
|
||||
LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
|
||||
} else {
|
||||
LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
|
||||
}
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_RESTART:
|
||||
if(invalue == LDAP_OPT_OFF) {
|
||||
@ -431,7 +472,8 @@ ldap_set_option(
|
||||
} else {
|
||||
LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
|
||||
}
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_CONNECT_ASYNC:
|
||||
if(invalue == LDAP_OPT_OFF) {
|
||||
@ -439,11 +481,10 @@ ldap_set_option(
|
||||
} else {
|
||||
LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
|
||||
}
|
||||
return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
/* options which can withstand invalue == NULL */
|
||||
switch ( option ) {
|
||||
case LDAP_OPT_SERVER_CONTROLS: {
|
||||
LDAPControl *const *controls =
|
||||
(LDAPControl *const *) invalue;
|
||||
@ -453,16 +494,19 @@ ldap_set_option(
|
||||
|
||||
if( controls == NULL || *controls == NULL ) {
|
||||
lo->ldo_sctrls = NULL;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
lo->ldo_sctrls = ldap_controls_dup( controls );
|
||||
|
||||
if(lo->ldo_sctrls == NULL) {
|
||||
/* memory allocation error ? */
|
||||
break;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_CLIENT_CONTROLS: {
|
||||
LDAPControl *const *controls =
|
||||
@ -473,22 +517,25 @@ ldap_set_option(
|
||||
|
||||
if( controls == NULL || *controls == NULL ) {
|
||||
lo->ldo_cctrls = NULL;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
lo->ldo_cctrls = ldap_controls_dup( controls );
|
||||
|
||||
if(lo->ldo_cctrls == NULL) {
|
||||
/* memory allocation error ? */
|
||||
break;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
|
||||
case LDAP_OPT_HOST_NAME: {
|
||||
const char *host = (const char *) invalue;
|
||||
LDAPURLDesc *ludlist = NULL;
|
||||
int rc = LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
|
||||
if(host != NULL) {
|
||||
rc = ldap_url_parsehosts( &ludlist, host,
|
||||
@ -519,13 +566,13 @@ ldap_set_option(
|
||||
ldap_free_urllist(lo->ldo_defludp);
|
||||
lo->ldo_defludp = ludlist;
|
||||
}
|
||||
return rc;
|
||||
break;
|
||||
}
|
||||
|
||||
case LDAP_OPT_URI: {
|
||||
const char *urls = (const char *) invalue;
|
||||
LDAPURLDesc *ludlist = NULL;
|
||||
int rc = LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
|
||||
if(urls != NULL) {
|
||||
rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
|
||||
@ -578,7 +625,7 @@ ldap_set_option(
|
||||
ldap_free_urllist(lo->ldo_defludp);
|
||||
lo->ldo_defludp = ludlist;
|
||||
}
|
||||
return rc;
|
||||
break;
|
||||
}
|
||||
|
||||
case LDAP_OPT_DEFBASE: {
|
||||
@ -587,24 +634,32 @@ ldap_set_option(
|
||||
|
||||
if ( newbase != NULL ) {
|
||||
defbase = LDAP_STRDUP( newbase );
|
||||
if ( defbase == NULL ) return LDAP_NO_MEMORY;
|
||||
if ( defbase == NULL ) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if ( ld != NULL ) {
|
||||
defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
|
||||
if ( defbase == NULL ) return LDAP_NO_MEMORY;
|
||||
if ( defbase == NULL ) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( lo->ldo_defbase != NULL )
|
||||
LDAP_FREE( lo->ldo_defbase );
|
||||
lo->ldo_defbase = defbase;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_DIAGNOSTIC_MESSAGE: {
|
||||
const char *err = (const char *) invalue;
|
||||
|
||||
if(ld == NULL) {
|
||||
/* need a struct ldap */
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
|
||||
if( ld->ld_error ) {
|
||||
@ -615,14 +670,16 @@ ldap_set_option(
|
||||
if ( err ) {
|
||||
ld->ld_error = LDAP_STRDUP(err);
|
||||
}
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_MATCHED_DN: {
|
||||
const char *matched = (const char *) invalue;
|
||||
|
||||
if (ld == NULL) {
|
||||
/* need a struct ldap */
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
|
||||
if( ld->ld_matched ) {
|
||||
@ -633,14 +690,16 @@ ldap_set_option(
|
||||
if ( matched ) {
|
||||
ld->ld_matched = LDAP_STRDUP( matched );
|
||||
}
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_REFERRAL_URLS: {
|
||||
char *const *referrals = (char *const *) invalue;
|
||||
|
||||
if(ld == NULL) {
|
||||
/* need a struct ldap */
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
|
||||
if( ld->ld_referrals ) {
|
||||
@ -650,38 +709,52 @@ ldap_set_option(
|
||||
if ( referrals ) {
|
||||
ld->ld_referrals = ldap_value_dup(referrals);
|
||||
}
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
/* Only accessed from inside this function by ldap_set_rebind_proc() */
|
||||
case LDAP_OPT_REBIND_PROC: {
|
||||
lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
case LDAP_OPT_REBIND_PARAMS: {
|
||||
lo->ldo_rebind_params = (void *)invalue;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
/* Only accessed from inside this function by ldap_set_nextref_proc() */
|
||||
case LDAP_OPT_NEXTREF_PROC: {
|
||||
lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
case LDAP_OPT_NEXTREF_PARAMS: {
|
||||
lo->ldo_nextref_params = (void *)invalue;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
/* Only accessed from inside this function by ldap_set_urllist_proc() */
|
||||
case LDAP_OPT_URLLIST_PROC: {
|
||||
lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
case LDAP_OPT_URLLIST_PARAMS: {
|
||||
lo->ldo_urllist_params = (void *)invalue;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
/* read-only options */
|
||||
case LDAP_OPT_API_INFO:
|
||||
case LDAP_OPT_DESC:
|
||||
case LDAP_OPT_SOCKBUF:
|
||||
case LDAP_OPT_API_FEATURE_INFO:
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
|
||||
/* options which cannot withstand invalue == NULL */
|
||||
case LDAP_OPT_DEREF:
|
||||
@ -698,25 +771,29 @@ ldap_set_option(
|
||||
case LDAP_OPT_X_KEEPALIVE_INTERVAL :
|
||||
if(invalue == NULL) {
|
||||
/* no place to set from */
|
||||
return LDAP_OPT_ERROR;
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
return ( LDAP_OPT_ERROR );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef HAVE_TLS
|
||||
if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
|
||||
return LDAP_OPT_SUCCESS;
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
return ( LDAP_OPT_SUCCESS );
|
||||
#endif
|
||||
#ifdef HAVE_CYRUS_SASL
|
||||
if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
|
||||
return LDAP_OPT_SUCCESS;
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
return ( LDAP_OPT_SUCCESS );
|
||||
#endif
|
||||
#ifdef HAVE_GSSAPI
|
||||
if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 )
|
||||
return LDAP_OPT_SUCCESS;
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
return ( LDAP_OPT_SUCCESS );
|
||||
#endif
|
||||
/* bad param */
|
||||
return LDAP_OPT_ERROR;
|
||||
break; /* LDAP_OPT_ERROR */
|
||||
}
|
||||
|
||||
/* options which cannot withstand invalue == NULL */
|
||||
@ -725,31 +802,38 @@ ldap_set_option(
|
||||
case LDAP_OPT_DEREF:
|
||||
/* FIXME: check value for protocol compliance? */
|
||||
lo->ldo_deref = * (const int *) invalue;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_SIZELIMIT:
|
||||
/* FIXME: check value for protocol compliance? */
|
||||
lo->ldo_sizelimit = * (const int *) invalue;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_TIMELIMIT:
|
||||
/* FIXME: check value for protocol compliance? */
|
||||
lo->ldo_timelimit = * (const int *) invalue;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_TIMEOUT: {
|
||||
const struct timeval *tv =
|
||||
(const struct timeval *) invalue;
|
||||
|
||||
lo->ldo_tm_api = *tv;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_NETWORK_TIMEOUT: {
|
||||
const struct timeval *tv =
|
||||
(const struct timeval *) invalue;
|
||||
|
||||
lo->ldo_tm_net = *tv;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_PROTOCOL_VERSION: {
|
||||
int vers = * (const int *) invalue;
|
||||
@ -758,7 +842,9 @@ ldap_set_option(
|
||||
break;
|
||||
}
|
||||
lo->ldo_version = vers;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_RESULT_CODE: {
|
||||
int err = * (const int *) invalue;
|
||||
@ -769,11 +855,14 @@ ldap_set_option(
|
||||
}
|
||||
|
||||
ld->ld_errno = err;
|
||||
} return LDAP_OPT_SUCCESS;
|
||||
}
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_DEBUG_LEVEL:
|
||||
lo->ldo_debug = * (const int *) invalue;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
case LDAP_OPT_CONNECT_CB:
|
||||
{
|
||||
@ -784,19 +873,24 @@ ldap_set_option(
|
||||
ll->ll_next = lo->ldo_conn_cbs;
|
||||
lo->ldo_conn_cbs = ll;
|
||||
}
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
case LDAP_OPT_X_KEEPALIVE_IDLE:
|
||||
lo->ldo_keepalive_idle = * (const int *) invalue;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
case LDAP_OPT_X_KEEPALIVE_PROBES :
|
||||
lo->ldo_keepalive_probes = * (const int *) invalue;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
case LDAP_OPT_X_KEEPALIVE_INTERVAL :
|
||||
lo->ldo_keepalive_interval = * (const int *) invalue;
|
||||
return LDAP_OPT_SUCCESS;
|
||||
rc = LDAP_OPT_SUCCESS;
|
||||
break;
|
||||
|
||||
}
|
||||
return LDAP_OPT_ERROR;
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
return ( rc );
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -53,6 +53,29 @@
|
||||
#include "ldap-int.h"
|
||||
#include "lber.h"
|
||||
|
||||
/* used by ldap_send_server_request and ldap_new_connection */
|
||||
#ifdef LDAP_R_COMPILE
|
||||
#define LDAP_CONN_LOCK_IF(nolock) \
|
||||
{ if (nolock) LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); }
|
||||
#define LDAP_CONN_UNLOCK_IF(nolock) \
|
||||
{ if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); }
|
||||
#define LDAP_REQ_LOCK_IF(nolock) \
|
||||
{ if (nolock) LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); }
|
||||
#define LDAP_REQ_UNLOCK_IF(nolock) \
|
||||
{ if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); }
|
||||
#define LDAP_RES_LOCK_IF(nolock) \
|
||||
{ if (nolock) LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); }
|
||||
#define LDAP_RES_UNLOCK_IF(nolock) \
|
||||
{ if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); }
|
||||
#else
|
||||
#define LDAP_CONN_LOCK_IF(nolock)
|
||||
#define LDAP_CONN_UNLOCK_IF(nolock)
|
||||
#define LDAP_REQ_LOCK_IF(nolock)
|
||||
#define LDAP_REQ_UNLOCK_IF(nolock)
|
||||
#define LDAP_RES_LOCK_IF(nolock)
|
||||
#define LDAP_RES_UNLOCK_IF(nolock)
|
||||
#endif
|
||||
|
||||
static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any ));
|
||||
static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc ));
|
||||
static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr ));
|
||||
@ -82,10 +105,12 @@ ldap_alloc_ber_with_options( LDAP *ld )
|
||||
void
|
||||
ldap_set_ber_options( LDAP *ld, BerElement *ber )
|
||||
{
|
||||
/* ld_lberoptions is constant, hence no lock */
|
||||
ber->ber_options = ld->ld_lberoptions;
|
||||
}
|
||||
|
||||
|
||||
/* sets needed mutexes - no mutexes set to this point */
|
||||
ber_int_t
|
||||
ldap_send_initial_request(
|
||||
LDAP *ld,
|
||||
@ -98,15 +123,15 @@ ldap_send_initial_request(
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
|
||||
/* not connected yet */
|
||||
rc = ldap_open_defconn( ld );
|
||||
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
if( rc < 0 ) {
|
||||
ber_free( ber, 1 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
return( -1 );
|
||||
} else if ( rc == 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
@ -117,27 +142,33 @@ ldap_send_initial_request(
|
||||
#ifdef LDAP_CONNECTIONLESS
|
||||
if (LDAP_IS_UDP(ld)) {
|
||||
if (msgtype == LDAP_REQ_BIND) {
|
||||
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
|
||||
if (ld->ld_options.ldo_cldapdn)
|
||||
ldap_memfree(ld->ld_options.ldo_cldapdn);
|
||||
ld->ld_options.ldo_cldapdn = ldap_strdup(dn);
|
||||
ber_free( ber, 1 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
return 0;
|
||||
}
|
||||
if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH)
|
||||
{
|
||||
ber_free( ber, 1 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
return LDAP_PARAM_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
rc = ldap_send_server_request( ld, ber, msgid, NULL,
|
||||
NULL, NULL, NULL );
|
||||
NULL, NULL, NULL, 0, 0 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
/* protected by conn_mutex */
|
||||
int
|
||||
ldap_int_flush_request(
|
||||
LDAP *ld,
|
||||
@ -145,6 +176,7 @@ ldap_int_flush_request(
|
||||
{
|
||||
LDAPConn *lc = lr->lr_conn;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) {
|
||||
if ( sock_errno() == EAGAIN ) {
|
||||
/* need to continue write later */
|
||||
@ -171,6 +203,13 @@ ldap_int_flush_request(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* protected by req_mutex
|
||||
* if m_noconn then protect using conn_lock
|
||||
* else already protected with conn_lock
|
||||
* if m_res then also protected by res_mutex
|
||||
*/
|
||||
|
||||
int
|
||||
ldap_send_server_request(
|
||||
LDAP *ld,
|
||||
@ -179,16 +218,20 @@ ldap_send_server_request(
|
||||
LDAPRequest *parentreq,
|
||||
LDAPURLDesc **srvlist,
|
||||
LDAPConn *lc,
|
||||
LDAPreqinfo *bind )
|
||||
LDAPreqinfo *bind,
|
||||
int m_noconn,
|
||||
int m_res )
|
||||
{
|
||||
LDAPRequest *lr;
|
||||
int incparent, rc;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 );
|
||||
|
||||
incparent = 0;
|
||||
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
||||
|
||||
LDAP_CONN_LOCK_IF(m_noconn);
|
||||
if ( lc == NULL ) {
|
||||
if ( srvlist == NULL ) {
|
||||
lc = ld->ld_defconn;
|
||||
@ -200,7 +243,8 @@ ldap_send_server_request(
|
||||
incparent = 1;
|
||||
++parentreq->lr_outrefcnt;
|
||||
}
|
||||
lc = ldap_new_connection( ld, srvlist, 0, 1, bind );
|
||||
lc = ldap_new_connection( ld, srvlist, 0,
|
||||
1, bind, 1, m_res );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -223,11 +267,13 @@ ldap_send_server_request(
|
||||
/* async only occurs if a network timeout is set */
|
||||
|
||||
/* honor network timeout */
|
||||
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
|
||||
if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec )
|
||||
{
|
||||
/* caller will have to call again */
|
||||
ld->ld_errno = LDAP_X_CONNECTING;
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||
/* fallthru */
|
||||
|
||||
default:
|
||||
@ -246,6 +292,7 @@ ldap_send_server_request(
|
||||
/* Forget about the bind */
|
||||
--parentreq->lr_outrefcnt;
|
||||
}
|
||||
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
@ -255,10 +302,13 @@ ldap_send_server_request(
|
||||
if ( LDAP_IS_UDP( ld )) {
|
||||
BerElement tmpber = *ber;
|
||||
ber_rewind( &tmpber );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
|
||||
rc = ber_write( &tmpber, ld->ld_options.ldo_peer,
|
||||
sizeof( struct sockaddr ), 0 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
|
||||
if ( rc == -1 ) {
|
||||
ld->ld_errno = LDAP_ENCODING_ERROR;
|
||||
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@ -276,7 +326,10 @@ ldap_send_server_request(
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
if ( rc ) return rc;
|
||||
if ( rc ) {
|
||||
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||
return rc;
|
||||
}
|
||||
|
||||
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) );
|
||||
if ( lr == NULL ) {
|
||||
@ -287,6 +340,7 @@ ldap_send_server_request(
|
||||
/* Forget about the bind */
|
||||
--parentreq->lr_outrefcnt;
|
||||
}
|
||||
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||
return( -1 );
|
||||
}
|
||||
lr->lr_msgid = msgid;
|
||||
@ -345,6 +399,7 @@ ldap_send_server_request(
|
||||
msgid = -1;
|
||||
}
|
||||
|
||||
LDAP_CONN_UNLOCK_IF(m_noconn);
|
||||
return( msgid );
|
||||
}
|
||||
|
||||
@ -375,18 +430,17 @@ find_tls_ext( LDAPURLDesc *srv )
|
||||
}
|
||||
|
||||
/*
|
||||
* caller must hold ld_req_mutex or be exclusive user of ld
|
||||
* if ( connect != 0 ) or ( bind != NULL ) caller must also hold
|
||||
* ld_req_mutex and ld_res_mutex
|
||||
* always protected by conn_mutex
|
||||
* optionally protected by req_mutex and res_mutex
|
||||
*/
|
||||
|
||||
LDAPConn *
|
||||
ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
int connect, LDAPreqinfo *bind )
|
||||
int connect, LDAPreqinfo *bind, int m_req, int m_res )
|
||||
{
|
||||
LDAPConn *lc;
|
||||
int async = 0;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
|
||||
use_ldsb, connect, (bind != NULL) );
|
||||
/*
|
||||
@ -445,15 +499,10 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
}
|
||||
|
||||
lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
lc->lconn_next = ld->ld_conns;
|
||||
ld->ld_conns = lc;
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
|
||||
if ( connect ) {
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||
|
||||
#ifdef HAVE_TLS
|
||||
if ( lc->lconn_server->lud_exts ) {
|
||||
int rc, ext = find_tls_ext( lc->lconn_server );
|
||||
@ -464,11 +513,13 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
++lc->lconn_refcnt; /* avoid premature free */
|
||||
ld->ld_defconn = lc;
|
||||
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
||||
LDAP_REQ_UNLOCK_IF(m_req);
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
LDAP_RES_UNLOCK_IF(m_res);
|
||||
rc = ldap_start_tls_s( ld, NULL, NULL );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
LDAP_RES_LOCK_IF(m_res);
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
LDAP_REQ_LOCK_IF(m_req);
|
||||
ld->ld_defconn = savedefconn;
|
||||
--lc->lconn_refcnt;
|
||||
|
||||
@ -485,9 +536,6 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
int err = 0;
|
||||
LDAPConn *savedefconn;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||
|
||||
/* Set flag to prevent additional referrals
|
||||
* from being processed on this
|
||||
* connection until the bind has completed
|
||||
@ -507,13 +555,15 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
ld->ld_defconn = lc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0);
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
||||
LDAP_REQ_UNLOCK_IF(m_req);
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
LDAP_RES_UNLOCK_IF(m_res);
|
||||
err = (*ld->ld_rebind_proc)( ld,
|
||||
bind->ri_url, bind->ri_request, bind->ri_msgid,
|
||||
ld->ld_rebind_params );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
LDAP_RES_LOCK_IF(m_res);
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
LDAP_REQ_LOCK_IF(m_req);
|
||||
|
||||
ld->ld_defconn = savedefconn;
|
||||
--lc->lconn_refcnt;
|
||||
@ -538,8 +588,9 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
"anonymous rebind via ldap_sasl_bind(\"\")\n",
|
||||
0, 0, 0);
|
||||
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
||||
LDAP_REQ_UNLOCK_IF(m_req);
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
LDAP_RES_UNLOCK_IF(m_res);
|
||||
rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd,
|
||||
NULL, NULL, &msgid );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
@ -583,8 +634,9 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
}
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
LDAP_RES_LOCK_IF(m_res);
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
LDAP_REQ_LOCK_IF(m_req);
|
||||
ld->ld_defconn = savedefconn;
|
||||
--lc->lconn_refcnt;
|
||||
|
||||
@ -596,11 +648,11 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
|
||||
if ( lc != NULL )
|
||||
lc->lconn_rebind_inprogress = 0;
|
||||
}
|
||||
|
||||
return( lc );
|
||||
}
|
||||
|
||||
|
||||
/* protected by ld_conn_mutex */
|
||||
static LDAPConn *
|
||||
find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
|
||||
/*
|
||||
@ -613,7 +665,7 @@ find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
|
||||
int lcu_port, lsu_port;
|
||||
int found = 0;
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
|
||||
lcu = lc->lconn_server;
|
||||
lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme,
|
||||
@ -637,35 +689,34 @@ find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
|
||||
if ( found )
|
||||
break;
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
return lc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: the caller holds ld_req_mutex
|
||||
*/
|
||||
|
||||
/* protected by ld_conn_mutex */
|
||||
static void
|
||||
use_connection( LDAP *ld, LDAPConn *lc )
|
||||
{
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
++lc->lconn_refcnt;
|
||||
lc->lconn_lastused = time( NULL );
|
||||
}
|
||||
|
||||
|
||||
/* protected by ld_conn_mutex */
|
||||
void
|
||||
ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||
{
|
||||
LDAPConn *tmplc, *prevlc;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldap_free_connection %d %d\n",
|
||||
force, unbind, 0 );
|
||||
|
||||
if ( force || --lc->lconn_refcnt <= 0 ) {
|
||||
/* remove from connections list first */
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
|
||||
for ( prevlc = NULL, tmplc = ld->ld_conns;
|
||||
tmplc != NULL;
|
||||
@ -684,7 +735,6 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||
}
|
||||
prevlc = tmplc;
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
|
||||
/* process connection callbacks */
|
||||
{
|
||||
@ -693,19 +743,23 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||
ldap_conncb *cb;
|
||||
|
||||
lo = &ld->ld_options;
|
||||
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||
if ( lo->ldo_conn_cbs ) {
|
||||
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
|
||||
cb = ll->ll_data;
|
||||
cb->lc_del( ld, lc->lconn_sb, cb );
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
lo = LDAP_INT_GLOBAL_OPT();
|
||||
LDAP_MUTEX_LOCK( &lo->ldo_mutex );
|
||||
if ( lo->ldo_conn_cbs ) {
|
||||
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
|
||||
cb = ll->ll_data;
|
||||
cb->lc_del( ld, lc->lconn_sb, cb );
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
|
||||
}
|
||||
|
||||
if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
|
||||
@ -773,6 +827,7 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||
}
|
||||
|
||||
|
||||
/* Protects self with ld_conn_mutex */
|
||||
#ifdef LDAP_DEBUG
|
||||
void
|
||||
ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
||||
@ -781,6 +836,7 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
||||
char timebuf[32];
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "", 0 );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
|
||||
if ( lc->lconn_server != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "* host: %s port: %d%s\n",
|
||||
@ -817,9 +873,11 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
|
||||
break;
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
}
|
||||
|
||||
|
||||
/* protected by req_mutex and res_mutex */
|
||||
void
|
||||
ldap_dump_requests_and_responses( LDAP *ld )
|
||||
{
|
||||
@ -868,9 +926,11 @@ ldap_dump_requests_and_responses( LDAP *ld )
|
||||
}
|
||||
#endif /* LDAP_DEBUG */
|
||||
|
||||
/* protected by req_mutex */
|
||||
static void
|
||||
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
||||
{
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
/* 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
|
||||
@ -921,11 +981,11 @@ ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
|
||||
LDAP_FREE( lr );
|
||||
}
|
||||
|
||||
/* protected by req_mutex */
|
||||
void
|
||||
ldap_free_request( LDAP *ld, LDAPRequest *lr )
|
||||
{
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n",
|
||||
lr->lr_origid, lr->lr_msgid, 0 );
|
||||
|
||||
@ -993,6 +1053,8 @@ static int ldap_int_nextref(
|
||||
* (OUT) hadrefp = 1 if sucessfully followed referral
|
||||
*
|
||||
* Return value - number of referrals followed
|
||||
*
|
||||
* Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
|
||||
*/
|
||||
int
|
||||
ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp )
|
||||
@ -1008,11 +1070,14 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
|
||||
LDAPreqinfo rinfo;
|
||||
LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 );
|
||||
|
||||
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
||||
*hadrefp = 0;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 );
|
||||
|
||||
unfollowed = NULL;
|
||||
rc = count = 0;
|
||||
|
||||
@ -1184,10 +1249,8 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
|
||||
/* Send the new request to the server - may require a bind */
|
||||
rinfo.ri_msgid = origreq->lr_origid;
|
||||
rinfo.ri_url = refarray[i];
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
rc = ldap_send_server_request( ld, ber, id,
|
||||
origreq, &srv, NULL, &rinfo );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
origreq, &srv, NULL, &rinfo, 0, 1 );
|
||||
if ( rc < 0 ) {
|
||||
/* Failure, try next referral in the list */
|
||||
Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n",
|
||||
@ -1208,6 +1271,7 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char *
|
||||
if ( lc == NULL ) {
|
||||
ld->ld_errno = LDAP_OPERATIONS_ERROR;
|
||||
rc = -1;
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -1253,6 +1317,7 @@ done:
|
||||
|
||||
/*
|
||||
* XXX merging of errors in this routine needs to be improved
|
||||
* Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
|
||||
*/
|
||||
int
|
||||
ldap_chase_referrals( LDAP *ld,
|
||||
@ -1270,6 +1335,9 @@ ldap_chase_referrals( LDAP *ld,
|
||||
LDAPreqinfo rinfo;
|
||||
LDAPConn *lc;
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 );
|
||||
|
||||
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
|
||||
@ -1367,11 +1435,8 @@ ldap_chase_referrals( LDAP *ld,
|
||||
|
||||
rinfo.ri_msgid = origreq->lr_origid;
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
rc = ldap_send_server_request( ld, ber, id,
|
||||
lr, &srv, NULL, &rinfo );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
|
||||
lr, &srv, NULL, &rinfo, 0, 1 );
|
||||
LDAP_FREE( rinfo.ri_url );
|
||||
|
||||
if( rc >= 0 ) {
|
||||
@ -1561,12 +1626,12 @@ re_encode_request( LDAP *ld,
|
||||
}
|
||||
|
||||
|
||||
/* protected by req_mutex */
|
||||
LDAPRequest *
|
||||
ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
|
||||
{
|
||||
LDAPRequest *lr;
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
||||
if ( lr->lr_status == LDAP_REQST_COMPLETED ) {
|
||||
continue; /* Skip completed requests */
|
||||
@ -1576,17 +1641,16 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
|
||||
break;
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
|
||||
return( lr );
|
||||
}
|
||||
|
||||
/* protected by req_mutex */
|
||||
void
|
||||
ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
|
||||
{
|
||||
LDAPRequest *lr;
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
|
||||
if ( lr == lrx ) {
|
||||
if ( lr->lr_refcnt > 0 ) {
|
||||
@ -1607,5 +1671,4 @@ ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
|
||||
} else if ( freeit ) {
|
||||
ldap_free_request( ld, lrx );
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
}
|
||||
|
@ -66,8 +66,8 @@
|
||||
#include "ldap_log.h"
|
||||
#include "lutil.h"
|
||||
|
||||
static int ldap_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid, int *idx ));
|
||||
static int ldap_mark_abandoned LDAP_P(( LDAP *ld, ber_int_t msgid, int idx ));
|
||||
static int ldap_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,
|
||||
LDAPMessage **result ));
|
||||
static ber_tag_t try_read1msg LDAP_P(( LDAP *ld, ber_int_t msgid,
|
||||
@ -120,6 +120,7 @@ ldap_result(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* protected by res_mutex */
|
||||
static LDAPMessage *
|
||||
chkResponseList(
|
||||
LDAP *ld,
|
||||
@ -144,12 +145,10 @@ chkResponseList(
|
||||
|
||||
lastlm = &ld->ld_responses;
|
||||
for ( lm = ld->ld_responses; lm != NULL; lm = nextlm ) {
|
||||
int idx;
|
||||
|
||||
nextlm = lm->lm_next;
|
||||
++cnt;
|
||||
|
||||
if ( ldap_abandoned( ld, lm->lm_msgid, &idx ) ) {
|
||||
if ( ldap_abandoned( ld, lm->lm_msgid ) ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"response list msg abandoned, "
|
||||
"msgid %d message type %s\n",
|
||||
@ -164,7 +163,7 @@ chkResponseList(
|
||||
default:
|
||||
/* there's no need to keep the id
|
||||
* in the abandoned list any longer */
|
||||
ldap_mark_abandoned( ld, lm->lm_msgid, idx );
|
||||
ldap_mark_abandoned( ld, lm->lm_msgid );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -231,6 +230,7 @@ chkResponseList(
|
||||
return lm;
|
||||
}
|
||||
|
||||
/* protected by res_mutex */
|
||||
static int
|
||||
wait4msg(
|
||||
LDAP *ld,
|
||||
@ -284,9 +284,7 @@ wait4msg(
|
||||
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "wait4msg continue ld %p msgid %d all %d\n",
|
||||
(void *)ld, msgid, all );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
ldap_dump_connection( ld, ld->ld_conns, 1 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
ldap_dump_requests_and_responses( ld );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
@ -308,7 +306,6 @@ wait4msg(
|
||||
break;
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
|
||||
if ( !lc_ready ) {
|
||||
int err;
|
||||
@ -328,6 +325,7 @@ wait4msg(
|
||||
{
|
||||
ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
|
||||
LDAP_TIMEOUT);
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
@ -349,8 +347,6 @@ wait4msg(
|
||||
{
|
||||
ldap_int_flush_request( ld, ld->ld_requests );
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
for ( lc = ld->ld_conns;
|
||||
rc == LDAP_MSG_X_KEEP_LOOKING && lc != NULL;
|
||||
lc = lnext )
|
||||
@ -360,25 +356,22 @@ wait4msg(
|
||||
{
|
||||
/* Don't let it get freed out from under us */
|
||||
++lc->lconn_refcnt;
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
rc = try_read1msg( ld, msgid, all, lc, result );
|
||||
lnext = lc->lconn_next;
|
||||
|
||||
/* Only take locks if we're really freeing */
|
||||
if ( lc->lconn_refcnt <= 1 ) {
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
ldap_free_connection( ld, lc, 0, 1 );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
} else {
|
||||
--lc->lconn_refcnt;
|
||||
}
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
} else {
|
||||
lnext = lc->lconn_next;
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
}
|
||||
|
||||
if ( rc == LDAP_MSG_X_KEEP_LOOKING && tvp != NULL ) {
|
||||
@ -432,6 +425,7 @@ wait4msg(
|
||||
}
|
||||
|
||||
|
||||
/* protected by res_mutex, conn_mutex and req_mutex */
|
||||
static ber_tag_t
|
||||
try_read1msg(
|
||||
LDAP *ld,
|
||||
@ -443,7 +437,6 @@ try_read1msg(
|
||||
BerElement *ber;
|
||||
LDAPMessage *newmsg, *l, *prev;
|
||||
ber_int_t id;
|
||||
int idx;
|
||||
ber_tag_t tag;
|
||||
ber_len_t len;
|
||||
int foundit = 0;
|
||||
@ -461,6 +454,8 @@ try_read1msg(
|
||||
assert( lc != NULL );
|
||||
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n",
|
||||
(void *)ld, msgid, all );
|
||||
@ -535,7 +530,7 @@ nextresp3:
|
||||
|
||||
/* if it's been abandoned, toss it */
|
||||
if ( id > 0 ) {
|
||||
if ( ldap_abandoned( ld, id, &idx ) ) {
|
||||
if ( ldap_abandoned( ld, id ) ) {
|
||||
/* the message type */
|
||||
tag = ber_peek_tag( ber, &len );
|
||||
switch ( tag ) {
|
||||
@ -548,7 +543,7 @@ nextresp3:
|
||||
default:
|
||||
/* there's no need to keep the id
|
||||
* in the abandoned list any longer */
|
||||
ldap_mark_abandoned( ld, id, idx );
|
||||
ldap_mark_abandoned( ld, id );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1337,35 +1332,37 @@ ldap_msgdelete( LDAP *ld, int msgid )
|
||||
*
|
||||
* return the location of the message id in the array of abandoned
|
||||
* message ids, or -1
|
||||
*
|
||||
* expects ld_res_mutex to be locked
|
||||
*/
|
||||
static int
|
||||
ldap_abandoned( LDAP *ld, ber_int_t msgid, int *idxp )
|
||||
ldap_abandoned( LDAP *ld, ber_int_t msgid )
|
||||
{
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||
|
||||
assert( idxp != NULL );
|
||||
int ret, idx;
|
||||
assert( msgid >= 0 );
|
||||
|
||||
return ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, idxp );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
|
||||
ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* ldap_mark_abandoned
|
||||
*
|
||||
* expects ld_res_mutex to be locked
|
||||
*/
|
||||
static int
|
||||
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid, int idx )
|
||||
ldap_mark_abandoned( LDAP *ld, ber_int_t msgid )
|
||||
{
|
||||
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
|
||||
int ret, idx;
|
||||
|
||||
/* NOTE: those assertions are repeated in ldap_int_bisect_delete() */
|
||||
assert( idx >= 0 );
|
||||
assert( (unsigned) idx < ld->ld_nabandoned );
|
||||
assert( ld->ld_abandoned[ idx ] == msgid );
|
||||
|
||||
return ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,
|
||||
assert( msgid >= 0 );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );
|
||||
ret = ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &idx );
|
||||
if (ret <= 0) { /* error or already deleted by another thread */
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||
return ret;
|
||||
}
|
||||
/* still in abandoned array, so delete */
|
||||
ret = ldap_int_bisect_delete( &ld->ld_abandoned, &ld->ld_nabandoned,
|
||||
msgid, idx );
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
|
||||
return ret;
|
||||
}
|
||||
|
@ -80,18 +80,44 @@ ldap_ld_free(
|
||||
LDAPMessage *lm, *next;
|
||||
int err = LDAP_SUCCESS;
|
||||
|
||||
LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
|
||||
/* Someone else is still using this ld. */
|
||||
if (ld->ld_ldcrefcnt > 1) { /* but not last thread */
|
||||
/* clean up self only */
|
||||
ld->ld_ldcrefcnt--;
|
||||
if ( ld->ld_error != NULL ) {
|
||||
LDAP_FREE( ld->ld_error );
|
||||
ld->ld_error = NULL;
|
||||
}
|
||||
|
||||
if ( ld->ld_matched != NULL ) {
|
||||
LDAP_FREE( ld->ld_matched );
|
||||
ld->ld_matched = NULL;
|
||||
}
|
||||
if ( ld->ld_referrals != NULL) {
|
||||
LDAP_VFREE(ld->ld_referrals);
|
||||
ld->ld_referrals = NULL;
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
|
||||
LDAP_FREE( (char *) ld );
|
||||
return( err );
|
||||
}
|
||||
|
||||
/* This ld is the last thread. */
|
||||
|
||||
/* 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_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
|
||||
|
||||
/* free and unbind from all open connections */
|
||||
while ( ld->ld_conns != NULL ) {
|
||||
ldap_free_connection( ld, ld->ld_conns, 1, close );
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
|
||||
for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
|
||||
next = lm->lm_next;
|
||||
@ -103,6 +129,7 @@ ldap_ld_free(
|
||||
ld->ld_abandoned = NULL;
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
|
||||
LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex );
|
||||
|
||||
/* final close callbacks */
|
||||
{
|
||||
@ -126,7 +153,7 @@ ldap_ld_free(
|
||||
ld->ld_matched = NULL;
|
||||
}
|
||||
|
||||
if( ld->ld_referrals != NULL) {
|
||||
if ( ld->ld_referrals != NULL) {
|
||||
LDAP_VFREE(ld->ld_referrals);
|
||||
ld->ld_referrals = NULL;
|
||||
}
|
||||
@ -188,22 +215,35 @@ ldap_ld_free(
|
||||
ldap_controls_free( ld->ld_options.ldo_cctrls );
|
||||
ld->ld_options.ldo_cctrls = NULL;
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex );
|
||||
|
||||
ber_sockbuf_free( ld->ld_sb );
|
||||
|
||||
#ifdef LDAP_R_COMPILE
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex );
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &ld->ld_ldcmutex );
|
||||
ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex );
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
LDAP_TRASH(ld);
|
||||
#endif
|
||||
LDAP_FREE( (char *) ld->ldc );
|
||||
LDAP_FREE( (char *) ld );
|
||||
|
||||
return( err );
|
||||
}
|
||||
|
||||
int
|
||||
ldap_destroy( LDAP *ld )
|
||||
{
|
||||
return ( ldap_ld_free( ld, 1, NULL, NULL ) );
|
||||
}
|
||||
|
||||
int
|
||||
ldap_unbind_s( LDAP *ld )
|
||||
{
|
||||
@ -233,7 +273,7 @@ ldap_send_unbind(
|
||||
return( ld->ld_errno );
|
||||
}
|
||||
|
||||
id = ++(ld)->ld_msgid;
|
||||
LDAP_NEXT_MSGID(ld, id);
|
||||
|
||||
/* fill it in */
|
||||
if ( ber_printf( ber, "{itn" /*}*/, id,
|
||||
|
@ -14,17 +14,21 @@
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
|
||||
PROGRAMS = slapd-tester slapd-search slapd-read slapd-addel slapd-modrdn \
|
||||
slapd-modify slapd-bind ldif-filter
|
||||
slapd-modify slapd-bind slapd-mtread ldif-filter
|
||||
|
||||
SRCS = slapd-common.c \
|
||||
slapd-tester.c slapd-search.c slapd-read.c slapd-addel.c \
|
||||
slapd-modrdn.c slapd-modify.c slapd-bind.c ldif-filter.c
|
||||
slapd-modrdn.c slapd-modify.c slapd-bind.c slapd-mtread.c \
|
||||
ldif-filter.c
|
||||
|
||||
LDAP_INCDIR= ../../include
|
||||
LDAP_LIBDIR= ../../libraries
|
||||
|
||||
XLIBS = $(LDAP_LIBLDAP_LA) $(LDAP_LIBLUTIL_A) $(LDAP_LIBLBER_LA)
|
||||
XRLIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLUTIL_A) $(LDAP_LIBLBER_LA)
|
||||
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
|
||||
RLIBS = $(XRLIBS) $(XXLIBS) $(AC_LIBS) $(XXXLIBS)
|
||||
|
||||
|
||||
OBJS = slapd-common.o
|
||||
|
||||
@ -57,3 +61,6 @@ slapd-bind: slapd-bind.o $(OBJS) $(XLIBS)
|
||||
ldif-filter: ldif-filter.o $(XLIBS)
|
||||
$(LTLINK) -o $@ ldif-filter.o $(LIBS)
|
||||
|
||||
slapd-mtread: slapd-mtread.o $(OBJS) $(XRLIBS)
|
||||
$(LTLINK) -o $@ slapd-mtread.o $(OBJS) $(RLIBS)
|
||||
|
||||
|
758
tests/progs/slapd-mtread.c
Normal file
758
tests/progs/slapd-mtread.c
Normal file
@ -0,0 +1,758 @@
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 1999-2009 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
/* ACKNOWLEDGEMENTS:
|
||||
* This work was initially developed by Kurt Spanier for inclusion
|
||||
* in OpenLDAP Software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This tool is a MT reader. It behaves like slapd-read however
|
||||
* with one or more threads simultaneously using the same connection.
|
||||
* If -M is enabled, then M threads will also perfrom write operations.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ldap_pvt_thread.h"
|
||||
|
||||
#include "ac/stdlib.h"
|
||||
|
||||
#include "ac/ctype.h"
|
||||
#include "ac/param.h"
|
||||
#include "ac/socket.h"
|
||||
#include "ac/string.h"
|
||||
#include "ac/unistd.h"
|
||||
#include "ac/wait.h"
|
||||
|
||||
#include "ldap.h"
|
||||
#include "lutil.h"
|
||||
|
||||
#include "ldap_pvt.h"
|
||||
|
||||
#include "slapd-common.h"
|
||||
|
||||
#define MAXCONN 512
|
||||
#define LOOPS 100
|
||||
#define RETRIES 0
|
||||
#define DEFAULT_BASE "ou=people,dc=example,dc=com"
|
||||
|
||||
static int
|
||||
whoami()
|
||||
{
|
||||
int me = ldap_pvt_thread_self();
|
||||
return (me);
|
||||
}
|
||||
|
||||
static void
|
||||
do_conn( char *uri, char *manager, struct berval *passwd,
|
||||
LDAP **ld, int nobind, int maxretries, int conn_num );
|
||||
|
||||
static void
|
||||
do_read( LDAP *ld, char *entry,
|
||||
char **attrs, int noattrs, int nobind, int maxloop,
|
||||
int maxretries, int delay, int force, int chaserefs, int idx );
|
||||
|
||||
static void
|
||||
do_random( LDAP *ld,
|
||||
char *sbase, char *filter, char **attrs, int noattrs, int nobind,
|
||||
int innerloop, int maxretries, int delay, int force, int chaserefs,
|
||||
int idx );
|
||||
|
||||
static void *
|
||||
do_onethread( void *arg );
|
||||
|
||||
static void *
|
||||
do_onerwthread( void *arg );
|
||||
|
||||
#define MAX_THREAD 1024
|
||||
int rt_pass[MAX_THREAD];
|
||||
int rt_fail[MAX_THREAD];
|
||||
int rwt_pass[MAX_THREAD];
|
||||
int rwt_fail[MAX_THREAD];
|
||||
|
||||
/*
|
||||
* Shared globals (command line args)
|
||||
*/
|
||||
LDAP *ld = NULL;
|
||||
char *entry = NULL;
|
||||
char *filter = NULL;
|
||||
int loops = LOOPS;
|
||||
int outerloops = 1;
|
||||
int retries = RETRIES;
|
||||
int delay = 0;
|
||||
int force = 0;
|
||||
int chaserefs = 0;
|
||||
char *srchattrs[] = { "1.1", NULL };
|
||||
char **attrs = srchattrs;
|
||||
int noattrs = 0;
|
||||
int nobind = 0;
|
||||
int threads = 1;
|
||||
int rwthreads = 0;
|
||||
int verbose = 0;
|
||||
|
||||
int noconns = 1;
|
||||
LDAP **lds = NULL;
|
||||
|
||||
static void
|
||||
thread_error(char *string)
|
||||
{
|
||||
char thrstr[BUFSIZ];
|
||||
|
||||
snprintf(thrstr, BUFSIZ, "error on tid: %d: %s", whoami(), string);
|
||||
tester_error( thrstr );
|
||||
}
|
||||
|
||||
static void
|
||||
thread_output(char *string)
|
||||
{
|
||||
char thrstr[BUFSIZ];
|
||||
|
||||
snprintf(thrstr, BUFSIZ, "tid: %d says: %s", whoami(), string);
|
||||
tester_error( thrstr );
|
||||
}
|
||||
|
||||
static void
|
||||
thread_verbose(char *string)
|
||||
{
|
||||
char thrstr[BUFSIZ];
|
||||
|
||||
if (!verbose)
|
||||
return;
|
||||
snprintf(thrstr, BUFSIZ, "tid: %d says: %s", whoami(), string);
|
||||
tester_error( thrstr );
|
||||
}
|
||||
|
||||
static void
|
||||
usage( char *name )
|
||||
{
|
||||
fprintf( stderr,
|
||||
"usage: %s "
|
||||
"-H <uri> | ([-h <host>] -p <port>) "
|
||||
"-D <manager> "
|
||||
"-w <passwd> "
|
||||
"-e <entry> "
|
||||
"[-A] "
|
||||
"[-C] "
|
||||
"[-F] "
|
||||
"[-N] "
|
||||
"[-v] "
|
||||
"[-c connections] "
|
||||
"[-f filter] "
|
||||
"[-i <ignore>] "
|
||||
"[-l <loops>] "
|
||||
"[-L <outerloops>] "
|
||||
"[-m threads] "
|
||||
"[-M threads] "
|
||||
"[-r <maxretries>] "
|
||||
"[-t <delay>] "
|
||||
"[-T <attrs>] "
|
||||
"[<attrs>] "
|
||||
"\n",
|
||||
name );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
int
|
||||
main( int argc, char **argv )
|
||||
{
|
||||
int i;
|
||||
char *uri = NULL;
|
||||
char *host = "localhost";
|
||||
int port = -1;
|
||||
char *manager = NULL;
|
||||
struct berval passwd = { 0, NULL };
|
||||
ldap_pvt_thread_t rtid[MAX_THREAD], rwtid[MAX_THREAD];
|
||||
char outstr[BUFSIZ];
|
||||
int ptpass;
|
||||
int testfail = 0;
|
||||
|
||||
|
||||
tester_init( "slapd-mtread", TESTER_READ );
|
||||
|
||||
/* by default, tolerate referrals and no such object */
|
||||
tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
|
||||
|
||||
while ( (i = getopt( argc, argv, "ACc:D:e:Ff:H:h:i:L:l:M:m:p:r:t:T:w:v" )) != EOF ) {
|
||||
switch ( i ) {
|
||||
case 'A':
|
||||
noattrs++;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
chaserefs++;
|
||||
break;
|
||||
|
||||
case 'H': /* the server uri */
|
||||
uri = strdup( optarg );
|
||||
break;
|
||||
|
||||
case 'h': /* the servers host */
|
||||
host = strdup( optarg );
|
||||
|
||||
case 'i':
|
||||
tester_ignore_str2errlist( optarg );
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
nobind++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'p': /* the servers port */
|
||||
if ( lutil_atoi( &port, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D': /* the servers manager */
|
||||
manager = strdup( optarg );
|
||||
break;
|
||||
|
||||
case 'w': /* the server managers password */
|
||||
passwd.bv_val = strdup( optarg );
|
||||
passwd.bv_len = strlen( optarg );
|
||||
memset( optarg, '*', passwd.bv_len );
|
||||
break;
|
||||
|
||||
case 'c': /* the number of connections */
|
||||
if ( lutil_atoi( &noconns, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e': /* DN to search for */
|
||||
entry = strdup( optarg );
|
||||
break;
|
||||
|
||||
case 'f': /* the search request */
|
||||
filter = strdup( optarg );
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
force++;
|
||||
break;
|
||||
|
||||
case 'l': /* the number of loops */
|
||||
if ( lutil_atoi( &loops, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L': /* the number of outerloops */
|
||||
if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M': /* the number of R/W threads */
|
||||
if ( lutil_atoi( &rwthreads, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
if (rwthreads > MAX_THREAD)
|
||||
rwthreads = MAX_THREAD;
|
||||
break;
|
||||
|
||||
case 'm': /* the number of threads */
|
||||
if ( lutil_atoi( &threads, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
if (threads > MAX_THREAD)
|
||||
threads = MAX_THREAD;
|
||||
break;
|
||||
|
||||
case 'r': /* the number of retries */
|
||||
if ( lutil_atoi( &retries, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 't': /* delay in seconds */
|
||||
if ( lutil_atoi( &delay, optarg ) != 0 ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
attrs = ldap_str2charray( optarg, "," );
|
||||
if ( attrs == NULL ) {
|
||||
usage( argv[0] );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
usage( argv[0] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (( entry == NULL ) || ( port == -1 && uri == NULL ))
|
||||
usage( argv[0] );
|
||||
|
||||
if ( *entry == '\0' ) {
|
||||
fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
|
||||
argv[0] );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
if ( argv[optind] != NULL ) {
|
||||
attrs = &argv[optind];
|
||||
}
|
||||
|
||||
if (noconns < 1)
|
||||
noconns = 1;
|
||||
if (noconns > MAXCONN)
|
||||
noconns = MAXCONN;
|
||||
lds = (LDAP **) calloc( sizeof(LDAP *), noconns);
|
||||
if (lds == NULL) {
|
||||
fprintf( stderr, "%s: Memory error: calloc noconns.\n",
|
||||
argv[0] );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
uri = tester_uri( uri, host, port );
|
||||
/* One connection and one connection only */
|
||||
do_conn( uri, manager, &passwd, &ld, nobind, retries, 0 );
|
||||
lds[0] = ld;
|
||||
for(i = 1; i < noconns; i++) {
|
||||
do_conn( uri, manager, &passwd, &lds[i], nobind, retries, i );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_initialize();
|
||||
|
||||
snprintf(outstr, BUFSIZ, "MT Test Start: conns: %d (%s)", noconns, uri);
|
||||
tester_error(outstr);
|
||||
snprintf(outstr, BUFSIZ, "Threads: RO: %d RW: %d", threads, rwthreads);
|
||||
tester_error(outstr);
|
||||
|
||||
/* Set up read only threads */
|
||||
for ( i = 0; i < threads; i++ ) {
|
||||
ldap_pvt_thread_create( &rtid[i], 0, do_onethread, (void*)i);
|
||||
snprintf(outstr, BUFSIZ, "Created RO thread %d [%d]", i, rtid[i]);
|
||||
thread_verbose(outstr);
|
||||
}
|
||||
/* Set up read/write threads */
|
||||
for ( i = 0; i < rwthreads; i++ ) {
|
||||
ldap_pvt_thread_create( &rwtid[i], 0, do_onerwthread, (void*)i);
|
||||
snprintf(outstr, BUFSIZ, "Created RW thread %d [%d]", i, rwtid[i]);
|
||||
thread_verbose(outstr);
|
||||
}
|
||||
|
||||
ptpass = outerloops * loops;
|
||||
|
||||
/* wait for read only threads to complete */
|
||||
for ( i = 0; i < threads; i++ )
|
||||
ldap_pvt_thread_join(rtid[i], NULL);
|
||||
/* wait for read/write threads to complete */
|
||||
for ( i = 0; i < rwthreads; i++ )
|
||||
ldap_pvt_thread_join(rwtid[i], NULL);
|
||||
|
||||
for(i = 0; i < noconns; i++) {
|
||||
if ( lds[i] != NULL ) {
|
||||
ldap_unbind_ext( lds[i], NULL, NULL );
|
||||
}
|
||||
}
|
||||
free( lds );
|
||||
|
||||
for ( i = 0; i < threads; i++ ) {
|
||||
snprintf(outstr, BUFSIZ, "RO thread %d pass=%d fail=%d", i,
|
||||
rt_pass[i], rt_fail[i]);
|
||||
tester_error(outstr);
|
||||
if (rt_fail[i] != 0 || rt_pass[i] != ptpass) {
|
||||
snprintf(outstr, BUFSIZ, "FAIL RO thread %d", i);
|
||||
tester_error(outstr);
|
||||
testfail++;
|
||||
}
|
||||
}
|
||||
for ( i = 0; i < rwthreads; i++ ) {
|
||||
snprintf(outstr, BUFSIZ, "RW thread %d pass=%d fail=%d", i,
|
||||
rwt_pass[i], rwt_fail[i]);
|
||||
tester_error(outstr);
|
||||
if (rwt_fail[i] != 0 || rwt_pass[i] != ptpass) {
|
||||
snprintf(outstr, BUFSIZ, "FAIL RW thread %d", i);
|
||||
tester_error(outstr);
|
||||
testfail++;
|
||||
}
|
||||
}
|
||||
snprintf(outstr, BUFSIZ, "MT Test complete" );
|
||||
tester_error(outstr);
|
||||
|
||||
if (testfail)
|
||||
exit( EXIT_FAILURE );
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
static void *
|
||||
do_onethread( void *arg )
|
||||
{
|
||||
int i, j, thisconn;
|
||||
LDAP **mlds;
|
||||
int me = whoami();
|
||||
char thrstr[BUFSIZ];
|
||||
int rc, refcnt = 0;
|
||||
int myidx = (int)arg;
|
||||
|
||||
mlds = (LDAP **) calloc( sizeof(LDAP *), noconns);
|
||||
if (mlds == NULL) {
|
||||
thread_error( "Memory error: thread calloc for noconns" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
for ( j = 0; j < outerloops; j++ ) {
|
||||
for(i = 0; i < noconns; i++) {
|
||||
mlds[i] = ldap_dup(lds[i]);
|
||||
if (mlds[i] == NULL) {
|
||||
thread_error( "ldap_dup error" );
|
||||
}
|
||||
}
|
||||
rc = ldap_get_option(mlds[0], LDAP_OPT_SESSION_REFCNT, &refcnt);
|
||||
snprintf(thrstr, BUFSIZ,
|
||||
"RO Thread: %d conns: %d refcnt: %d (rc = %d)",
|
||||
me, noconns, refcnt, rc);
|
||||
thread_verbose(thrstr);
|
||||
|
||||
thisconn = (me + j) % noconns;
|
||||
if (thisconn < 0 || thisconn >= noconns)
|
||||
thisconn = 0;
|
||||
if (mlds[thisconn] == NULL) {
|
||||
thread_error("(failed to dup)");
|
||||
tester_perror( "ldap_dup", "(failed to dup)" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
snprintf(thrstr, BUFSIZ, "Thread %d using conn %d", me, thisconn);
|
||||
thread_verbose(thrstr);
|
||||
if ( filter != NULL ) {
|
||||
do_random( mlds[thisconn], entry, filter, attrs,
|
||||
noattrs, nobind, loops, retries, delay, force,
|
||||
chaserefs, myidx );
|
||||
|
||||
} else {
|
||||
do_read( mlds[thisconn], entry, attrs,
|
||||
noattrs, nobind, loops, retries, delay, force,
|
||||
chaserefs, myidx );
|
||||
}
|
||||
for(i = 0; i < noconns; i++) {
|
||||
(void) ldap_destroy(mlds[i]);
|
||||
mlds[i] = NULL;
|
||||
}
|
||||
}
|
||||
free( mlds );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
static void *
|
||||
do_onerwthread( void *arg )
|
||||
{
|
||||
int i, j, thisconn;
|
||||
LDAP **mlds, *ld;
|
||||
int me = whoami();
|
||||
char thrstr[BUFSIZ];
|
||||
char dn[256], uids[32], cns[32], *base;
|
||||
LDAPMod *attrp[5], attrs[4];
|
||||
char *oc_vals[] = { "top", "OpenLDAPperson", NULL };
|
||||
char *cn_vals[] = { NULL, NULL };
|
||||
char *sn_vals[] = { NULL, NULL };
|
||||
char *uid_vals[] = { NULL, NULL };
|
||||
int ret;
|
||||
int adds = 0;
|
||||
int dels = 0;
|
||||
int rc, refcnt = 0;
|
||||
int myidx = (int)arg;
|
||||
|
||||
mlds = (LDAP **) calloc( sizeof(LDAP *), noconns);
|
||||
if (mlds == NULL) {
|
||||
thread_error( "Memory error: thread calloc for noconns" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
snprintf(uids, 32, "rwtest%04.4d", me);
|
||||
snprintf(cns, 32, "rwtest%04.4d", me);
|
||||
/* add setup */
|
||||
for (i = 0; i < 4; i++) {
|
||||
attrp[i] = &attrs[i];
|
||||
attrs[i].mod_op = 0;
|
||||
}
|
||||
attrp[4] = NULL;
|
||||
attrs[0].mod_type = "objectClass";
|
||||
attrs[0].mod_values = oc_vals;
|
||||
attrs[1].mod_type = "cn";
|
||||
attrs[1].mod_values = cn_vals;
|
||||
cn_vals[0] = &cns[0];
|
||||
attrs[2].mod_type = "sn";
|
||||
attrs[2].mod_values = sn_vals;
|
||||
sn_vals[0] = &cns[0];
|
||||
attrs[3].mod_type = "uid";
|
||||
attrs[3].mod_values = uid_vals;
|
||||
uid_vals[0] = &uids[0];
|
||||
|
||||
for ( j = 0; j < outerloops; j++ ) {
|
||||
for(i = 0; i < noconns; i++) {
|
||||
mlds[i] = ldap_dup(lds[i]);
|
||||
if (mlds[i] == NULL) {
|
||||
thread_error( "ldap_dup error" );
|
||||
}
|
||||
}
|
||||
rc = ldap_get_option(mlds[0], LDAP_OPT_SESSION_REFCNT, &refcnt);
|
||||
snprintf(thrstr, BUFSIZ,
|
||||
"RW Thread: %d conns: %d refcnt: %d (rc = %d)",
|
||||
me, noconns, refcnt, rc);
|
||||
thread_verbose(thrstr);
|
||||
|
||||
thisconn = (me + j) % noconns;
|
||||
if (thisconn < 0 || thisconn >= noconns)
|
||||
thisconn = 0;
|
||||
if (mlds[thisconn] == NULL) {
|
||||
thread_error("(failed to dup)");
|
||||
tester_perror( "ldap_dup", "(failed to dup)" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
snprintf(thrstr, BUFSIZ, "START RW Thread %d using conn %d",
|
||||
me, thisconn);
|
||||
thread_verbose(thrstr);
|
||||
|
||||
ld = mlds[thisconn];
|
||||
if (entry != NULL)
|
||||
base = entry;
|
||||
else
|
||||
base = DEFAULT_BASE;
|
||||
snprintf(dn, 256, "cn=%s,%s", cns, base);
|
||||
|
||||
adds = 0;
|
||||
dels = 0;
|
||||
for (i = 0; i < loops; i++) {
|
||||
ret = ldap_add_ext_s(ld, dn, &attrp[0], NULL, NULL);
|
||||
if (ret == LDAP_SUCCESS) {
|
||||
adds++;
|
||||
ret = ldap_delete_ext_s(ld, dn, NULL, NULL);
|
||||
if (ret == LDAP_SUCCESS) {
|
||||
dels++;
|
||||
rwt_pass[myidx]++;
|
||||
} else {
|
||||
thread_output(ldap_err2string(ret));
|
||||
rwt_fail[myidx]++;
|
||||
}
|
||||
} else {
|
||||
thread_output(ldap_err2string(ret));
|
||||
rwt_fail[myidx]++;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(thrstr, BUFSIZ,
|
||||
"INNER STOP RW Thread %d using conn %d (%d/%d)",
|
||||
me, thisconn, adds, dels);
|
||||
thread_verbose(thrstr);
|
||||
|
||||
for(i = 0; i < noconns; i++) {
|
||||
(void) ldap_destroy(mlds[i]);
|
||||
mlds[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free( mlds );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
do_conn( char *uri, char *manager, struct berval *passwd,
|
||||
LDAP **ldp, int nobind, int maxretries, int conn_num )
|
||||
{
|
||||
LDAP *ld = NULL;
|
||||
int version = LDAP_VERSION3;
|
||||
int i = 0, do_retry = maxretries;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char thrstr[BUFSIZ];
|
||||
|
||||
retry:;
|
||||
ldap_initialize( &ld, uri );
|
||||
if ( ld == NULL ) {
|
||||
snprintf( thrstr, BUFSIZ, "connection: %d", conn_num );
|
||||
tester_error( thrstr );
|
||||
tester_perror( "ldap_initialize", NULL );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
|
||||
(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
|
||||
chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
|
||||
|
||||
if ( do_retry == maxretries ) {
|
||||
snprintf( thrstr, BUFSIZ, "do_conn #%d\n", conn_num );
|
||||
thread_verbose( thrstr );
|
||||
}
|
||||
|
||||
if ( nobind == 0 ) {
|
||||
rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
snprintf( thrstr, BUFSIZ, "connection: %d", conn_num );
|
||||
tester_error( thrstr );
|
||||
tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
|
||||
switch ( rc ) {
|
||||
case LDAP_BUSY:
|
||||
case LDAP_UNAVAILABLE:
|
||||
if ( do_retry > 0 ) {
|
||||
ldap_unbind_ext( ld, NULL, NULL );
|
||||
ld = NULL;
|
||||
do_retry--;
|
||||
if ( delay != 0 ) {
|
||||
sleep( delay );
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
/* fallthru */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
}
|
||||
*ldp = ld;
|
||||
}
|
||||
|
||||
static void
|
||||
do_random( LDAP *ld,
|
||||
char *sbase, char *filter, char **srchattrs, int noattrs, int nobind,
|
||||
int innerloop, int maxretries, int delay, int force, int chaserefs,
|
||||
int idx )
|
||||
{
|
||||
int i = 0, do_retry = maxretries;
|
||||
char *attrs[ 2 ];
|
||||
int rc = LDAP_SUCCESS;
|
||||
int nvalues = 0;
|
||||
char **values = NULL;
|
||||
LDAPMessage *res = NULL, *e = NULL;
|
||||
char thrstr[BUFSIZ];
|
||||
|
||||
attrs[ 0 ] = LDAP_NO_ATTRS;
|
||||
attrs[ 1 ] = NULL;
|
||||
|
||||
snprintf( thrstr, BUFSIZ,
|
||||
"Read(%d): base=\"%s\", filter=\"%s\".\n",
|
||||
innerloop, sbase, filter );
|
||||
thread_verbose( thrstr );
|
||||
|
||||
rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
|
||||
filter, attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res );
|
||||
switch ( rc ) {
|
||||
case LDAP_SIZELIMIT_EXCEEDED:
|
||||
case LDAP_TIMELIMIT_EXCEEDED:
|
||||
case LDAP_SUCCESS:
|
||||
nvalues = ldap_count_entries( ld, res );
|
||||
if ( nvalues == 0 ) {
|
||||
if ( rc ) {
|
||||
tester_ldap_error( ld, "ldap_search_ext_s", NULL );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
values = malloc( ( nvalues + 1 ) * sizeof( char * ) );
|
||||
for ( i = 0, e = ldap_first_entry( ld, res ); e != NULL; i++, e = ldap_next_entry( ld, e ) )
|
||||
{
|
||||
values[ i ] = ldap_get_dn( ld, e );
|
||||
}
|
||||
values[ i ] = NULL;
|
||||
|
||||
ldap_msgfree( res );
|
||||
|
||||
if ( do_retry == maxretries ) {
|
||||
snprintf( thrstr, BUFSIZ,
|
||||
"Read base=\"%s\" filter=\"%s\" got %d values.\n",
|
||||
sbase, filter, nvalues );
|
||||
thread_verbose( thrstr );
|
||||
}
|
||||
|
||||
for ( i = 0; i < innerloop; i++ ) {
|
||||
int r = ((double)nvalues)*rand()/(RAND_MAX + 1.0);
|
||||
|
||||
do_read( ld, values[ r ],
|
||||
srchattrs, noattrs, nobind, 1, maxretries,
|
||||
delay, force, chaserefs, idx );
|
||||
}
|
||||
for( i = 0; i < nvalues; i++) {
|
||||
if (values[i] != NULL)
|
||||
free( values[i] );
|
||||
}
|
||||
free( values );
|
||||
break;
|
||||
|
||||
default:
|
||||
tester_ldap_error( ld, "ldap_search_ext_s", NULL );
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf( thrstr, BUFSIZ, "Search done (%d).\n", rc );
|
||||
thread_verbose( thrstr );
|
||||
}
|
||||
|
||||
static void
|
||||
do_read( LDAP *ld, char *entry,
|
||||
char **attrs, int noattrs, int nobind, int maxloop,
|
||||
int maxretries, int delay, int force, int chaserefs, int idx )
|
||||
{
|
||||
int i = 0, do_retry = maxretries;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char thrstr[BUFSIZ];
|
||||
|
||||
retry:;
|
||||
if ( do_retry == maxretries ) {
|
||||
snprintf( thrstr, BUFSIZ, "Read(%d): entry=\"%s\".\n",
|
||||
maxloop, entry );
|
||||
thread_verbose( thrstr );
|
||||
}
|
||||
|
||||
snprintf(thrstr, BUFSIZ, "tid: %d LD %x cnt: %d (retried %d) (%s)", \
|
||||
whoami(), ld, maxloop, (do_retry - maxretries), entry);
|
||||
thread_verbose( thrstr );
|
||||
|
||||
for ( ; i < maxloop; i++ ) {
|
||||
LDAPMessage *res = NULL;
|
||||
|
||||
rc = ldap_search_ext_s( ld, entry, LDAP_SCOPE_BASE,
|
||||
NULL, attrs, noattrs, NULL, NULL, NULL,
|
||||
LDAP_NO_LIMIT, &res );
|
||||
if ( res != NULL ) {
|
||||
ldap_msgfree( res );
|
||||
}
|
||||
|
||||
if ( rc == 0 ) {
|
||||
rt_pass[idx]++;
|
||||
} else {
|
||||
int first = tester_ignore_err( rc );
|
||||
char buf[ BUFSIZ ];
|
||||
|
||||
rt_fail[idx]++;
|
||||
snprintf( buf, sizeof( buf ), "ldap_search_ext_s(%s)", entry );
|
||||
|
||||
/* if ignore.. */
|
||||
if ( first ) {
|
||||
/* only log if first occurrence */
|
||||
if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) {
|
||||
tester_ldap_error( ld, buf, NULL );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* busy needs special handling */
|
||||
tester_ldap_error( ld, buf, NULL );
|
||||
if ( rc == LDAP_BUSY && do_retry > 0 ) {
|
||||
do_retry--;
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -192,6 +192,7 @@ LDAPCOMPARE="$CLIENTDIR/ldapcompare $TOOLARGS"
|
||||
LDAPEXOP="$CLIENTDIR/ldapexop $TOOLARGS"
|
||||
SLAPDTESTER=$PROGDIR/slapd-tester
|
||||
LDIFFILTER=$PROGDIR/ldif-filter
|
||||
SLAPDMTREAD=$PROGDIR/slapd-mtread
|
||||
LVL=${SLAPD_DEBUG-0x4105}
|
||||
LOCALHOST=localhost
|
||||
BASEPORT=${SLAPD_BASEPORT-9010}
|
||||
@ -311,6 +312,8 @@ SLAVE2OUT=$SERVER3OUT
|
||||
SLAVEFLT=$SERVER2FLT
|
||||
SLAVE2FLT=$SERVER3FLT
|
||||
|
||||
MTREADOUT=$TESTDIR/mtread.out
|
||||
|
||||
# original outputs for cmp
|
||||
PROXYCACHEOUT=$DATADIR/proxycache.out
|
||||
REFERRALOUT=$DATADIR/referrals.out
|
||||
|
289
tests/scripts/test060-mt-hot
Executable file
289
tests/scripts/test060-mt-hot
Executable file
@ -0,0 +1,289 @@
|
||||
#! /bin/sh
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2009 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
|
||||
echo "running defines.sh"
|
||||
. $SRCDIR/scripts/defines.sh
|
||||
|
||||
mkdir -p $TESTDIR $DBDIR1
|
||||
|
||||
#
|
||||
# Populate and start up slapd server with some random data
|
||||
#
|
||||
|
||||
echo "Running slapadd to build slapd database..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $MCONF > $ADDCONF
|
||||
$SLAPADD -f $ADDCONF -l $LDIFORDERED
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapadd failed ($RC)!"
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
echo "Running slapindex to index slapd database..."
|
||||
. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
|
||||
$SLAPINDEX -f $CONF1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "warning: slapindex failed ($RC)"
|
||||
echo " assuming no indexing support"
|
||||
fi
|
||||
|
||||
echo "Starting slapd on TCP/IP port $PORT1..."
|
||||
echo $SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING
|
||||
$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
|
||||
PID=$!
|
||||
if test $WAIT != 0 ; then
|
||||
echo PID $PID
|
||||
read foo
|
||||
fi
|
||||
KILLPIDS="$PID"
|
||||
|
||||
sleep 1
|
||||
|
||||
# Perform a basic search, make sure of a functional setup
|
||||
echo "Testing basic monitor search..."
|
||||
for i in 0 1 2 3 4 5; do
|
||||
$LDAPSEARCH -s base -b "$MONITORDN" -h $LOCALHOST -p $PORT1 \
|
||||
'(objectclass=*)' > /dev/null 2>&1
|
||||
RC=$?
|
||||
if test $RC = 0 ; then
|
||||
break
|
||||
fi
|
||||
echo "Waiting 5 seconds for slapd to start..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
if test $RC != 0 ; then
|
||||
echo "mt-hot read failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
cat /dev/null > $MTREADOUT
|
||||
|
||||
echo "Monitor searches"
|
||||
# Perform a basic single threaded search on a single connection
|
||||
THR=1
|
||||
OUTER=1
|
||||
INNER=50000
|
||||
echo "Testing basic mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" \
|
||||
-m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a basic multi-threaded search on a single connection
|
||||
THR=5
|
||||
OUTER=1
|
||||
INNER=10000
|
||||
echo "Testing basic mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" \
|
||||
-m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a basic multi-threaded search on a single connection
|
||||
THR=100
|
||||
OUTER=5
|
||||
INNER=100
|
||||
echo "Testing basic mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" \
|
||||
-m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a single threaded random DB search on a single connection
|
||||
echo "Random searches"
|
||||
THR=1
|
||||
OUTER=1
|
||||
INNER=50000
|
||||
echo "Testing random mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a multi-threaded random DB search on a single connection
|
||||
THR=5
|
||||
OUTER=1
|
||||
INNER=10000
|
||||
echo "Testing random mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a multi-threaded random DB search on a single connection
|
||||
THR=100
|
||||
OUTER=5
|
||||
INNER=100
|
||||
echo "Testing random mt-hot search: $THR threads ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a basic multi-threaded search using multiple connections
|
||||
echo "Multiple threads and connection searches"
|
||||
CONN=5
|
||||
THR=5
|
||||
OUTER=1
|
||||
INNER=10000
|
||||
echo "Testing basic mt-hot search: $THR threads $CONN conns ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" \
|
||||
-c $CONN -m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||
-c $CONN -m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a basic multi-threaded search using multiple connections
|
||||
CONN=5
|
||||
THR=50
|
||||
OUTER=5
|
||||
INNER=1000
|
||||
echo "Testing basic mt-hot search: $THR threads $CONN conns ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" \
|
||||
-c $CONN -m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$MONITORDN" -f "(objectclass=*)" \
|
||||
-c $CONN -m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a multi-threaded random DB search using multiple connections
|
||||
CONN=5
|
||||
THR=100
|
||||
OUTER=5
|
||||
INNER=100
|
||||
echo "Testing random mt-hot search: $THR threads $CONN conns ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-c $CONN -m $THR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(objectclass=*)" \
|
||||
-c $CONN -m $THR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a multi-threaded random reads and writes using single connection
|
||||
CONN=1
|
||||
THR=10
|
||||
WTHR=10
|
||||
OUTER=5
|
||||
INNER=100
|
||||
echo "Testing random mt-hot r/w search: $THR read threads $WTHR write threads $CONN conns ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
# Perform a multi-threaded random reads and writes using multiple connections
|
||||
CONN=5
|
||||
THR=10
|
||||
WTHR=10
|
||||
OUTER=5
|
||||
INNER=100
|
||||
echo "Testing random mt-hot r/w search: $THR read threads $WTHR write threads $CONN conns ($OUTER x $INNER) loops..."
|
||||
echo $SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER
|
||||
$SLAPDMTREAD -h $LOCALHOST -p $PORT1 -D "$MANAGERDN" -w $PASSWD \
|
||||
-e "$BASEDN" -f "(&(!(cn=rwtest*))(objectclass=*))" \
|
||||
-c $CONN -m $THR -M $WTHR -L $OUTER -l $INNER >> $MTREADOUT 2>&1
|
||||
RC=$?
|
||||
if test $RC != 0 ; then
|
||||
echo "slapd-mtread failed ($RC)!"
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
exit $RC
|
||||
fi
|
||||
|
||||
|
||||
test $KILLSERVERS != no && kill -HUP $KILLPIDS
|
||||
|
||||
echo ">>>>> Test succeeded"
|
||||
|
||||
exit 0
|
Loading…
Reference in New Issue
Block a user