Table of Contents
- Introduction
- Establishing a Connection
- Searching Hierarchical Data
- Browsing Attributes
- Timeouts (this page)
- Modifying Data
Timeouts
LDAP servers are designed to be fast; but it is still possible for an action to take a long time. A deep sub-tree search with an open search criteria could require from seconds to even minutes to return data if the directory was large and no other criteria limited the results.
Thus clients are able to put timeout limits on their requests to abort if they take too long. The public servers I’ve been using are relatively small in scope and/or have result limits on them so they tend to be fast but we’ll create an intentionally expensive search and time it. I’ll use the approximate equality operator to do an expensive search into a deep and wide subtree.
DECLARE v_result PLS_INTEGER; v_session DBMS_LDAP.session; v_search_attrs DBMS_LDAP.string_collection; v_search_results DBMS_LDAP.MESSAGE; v_start TIMESTAMP WITH TIME ZONE; v_end TIMESTAMP WITH TIME ZONE; BEGIN DBMS_LDAP.use_exception := TRUE; v_session := DBMS_LDAP.init(hostname => 'ldap.andrew.cmu.edu', portnum => DBMS_LDAP.port); v_search_attrs(1) := '*'; v_start := SYSTIMESTAMP; v_result := DBMS_LDAP.search_s(ld => v_session, base => 'dc=cmu,dc=edu', scope => DBMS_LDAP.scope_subtree, filter => 'maillocaladdress~=ayushb', attrs => v_search_attrs, attronly => 0, res => v_search_results); v_end := SYSTIMESTAMP; DBMS_OUTPUT.put_line(v_end - v_start); v_result := DBMS_LDAP.unbind_s(v_session); END; / +000000000 00:00:20.977627000
So, just over 20 seconds to do that search. If that is too long, a time out can be created using the DBMS_LDAP.TIMEVAL type. Then instead of using SEARCH_S, we use SEARCH_ST – “T” for timed. If the timeout is exceeded an exception will be raised. In order to more clearly capture the time, I’ll disable exceptions and examine the result code of the SEARCH_ST function instead. We’ll put a 2 second time limit on the search and check the timing when we’re done.
DECLARE v_result PLS_INTEGER; v_session DBMS_LDAP.session; v_search_attrs DBMS_LDAP.string_collection; v_search_results DBMS_LDAP.MESSAGE; v_start TIMESTAMP WITH TIME ZONE; v_end TIMESTAMP WITH TIME ZONE; v_timeout DBMS_LDAP.timeval; BEGIN DBMS_LDAP.use_exception := FALSE; v_session := DBMS_LDAP.init(hostname => 'ldap.andrew.cmu.edu', portnum => DBMS_LDAP.port); v_search_attrs(1) := '*'; v_timeout.seconds := 2; v_start := SYSTIMESTAMP; v_result := DBMS_LDAP.search_st(ld => v_session, base => 'dc=cmu,dc=edu', scope => DBMS_LDAP.scope_subtree, filter => 'maillocaladdress~=ayushb', attrs => v_search_attrs, attronly => 0, tv => v_timeout, res => v_search_results); v_end := SYSTIMESTAMP; DBMS_OUTPUT.put_line('Error code: ' || v_result || ' ' || DBMS_LDAP.err2string(v_result)); DBMS_OUTPUT.put_line(v_end - v_start); v_result := DBMS_LDAP.unbind_s(v_session); END; / Error code: 85 Timed out +000000000 00:00:02.000382000
As expected, the search quit after 2 seconds and exited.
The TIMEVAL type is actually a record of two fields: seconds and microseconds.
TYPE TIMEVAL IS RECORD ( seconds PLS_INTEGER, useconds PLS_INTEGER );
Either or both fields may be populated. If both are populated the timeout value will be the sum of the two times. As in the following example where seconds is populated with 1 and useconds with 1.5 million, for a total timeout of 2.5 seconds.
DECLARE v_result PLS_INTEGER; v_session DBMS_LDAP.session; v_search_attrs DBMS_LDAP.string_collection; v_search_results DBMS_LDAP.MESSAGE; v_start TIMESTAMP WITH TIME ZONE; v_end TIMESTAMP WITH TIME ZONE; v_timeout DBMS_LDAP.timeval; BEGIN DBMS_LDAP.use_exception := FALSE; v_session := DBMS_LDAP.init(hostname => 'ldap.andrew.cmu.edu', portnum => DBMS_LDAP.port); v_search_attrs(1) := '*'; v_timeout.seconds := 1; v_timeout.useconds := 1500000; v_start := SYSTIMESTAMP; v_result := DBMS_LDAP.search_st(ld => v_session, base => 'dc=cmu,dc=edu', scope => DBMS_LDAP.scope_subtree, filter => 'maillocaladdress~=ayushb', attrs => v_search_attrs, attronly => 0, tv => v_timeout, res => v_search_results); v_end := SYSTIMESTAMP; DBMS_OUTPUT.put_line('Error code: ' || v_result || ' ' || DBMS_LDAP.err2string(v_result)); DBMS_OUTPUT.put_line(v_end - v_start); v_result := DBMS_LDAP.unbind_s(v_session); END; / Error code: 85 Timed out +000000000 00:00:02.500799000
While the datatype of each value is PLS_INTEGER, which accepts negative values, if either value is negative you will receive an error code 1027 (Unknown error.)
Similarly if both values are left unpopulated (both NULL) a 1027 error will be returned.
If exceptions are enabled then the following exception will be raised.
ORA-31207: DBMS_LDAP: PL/SQL - Invalid LDAP search time value.
If both values are set to 0, that is treated as no timelimit. The search will run to completion or the server’s limit.