From 3efa97aae09f5228bff773809c35db30fa602dfd Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Fri, 26 Apr 2013 15:24:22 -0700
Subject: [PATCH 58/99] Ticket #47347 - Simple paged results should support
async search
Bug description: Simple paged results serialized the request
even for a series of asynchronous search requests, and it
returned error 53 (unwilling to perform) if the second request
comes in while the first one is being processed.
Fix description: This patch implements the asynchronous support
for the Simple paged results search.
- Removed pagedresults_check_or_set_processing which was
used to Simple paged results requests exclusive. Instead,
pagedresults_lock is introduced to protect the PagedResults
object from the other threads sharing the same cookie.
- If any error including hitting the sizelimit or timelimit,
search result set was released immediately in ldbm_back_
next_search_entry_ext, which could cause the race condition
among multiple asynchronous search requests. To prevent it,
the search result set is untouched if the operation is a
Simple paged result search, and let its clean up function
to handle it.
- Sizelimit was evaluated in the accumulative way instead of
on the each page size. For instance, if the sizelimit was
101 AND the page size is 100, as soon as getting the 2nd page,
it hit the sizelimit and the search failed. This patch fixes
it so that as long as the requested page size is less than 101,
the requests successfully continue without getting an error 4
(LDAP_SIZELIMIT_EXCEEDED). To fulfill the requirement, the
current size needs to be managed per operation instead of the
search result set or PagedResults object. For the purpose,
introduced o_pagedresults_sizelimit to Slapi_Operation.
- When shutting down, connection_table_free could use backend
callback (e.g., be_search_results_release). Therefore, moved
be_cleanupall after connection_table_free.
- Each Simple paged results helper functions checks if the
operation is really a Simple paged result request control is
associated with to prevent any unexpected behaviour.
https://fedorahosted.org/389/ticket/47347
Reviewed by Rich (Thank you!!)
(cherry picked from commit d53e8221f77ac325123e3bb4f61cf6de67dce646)
(cherry picked from commit 96535a6756b8a556897fb643a31421c7f5068166)
---
ldap/servers/slapd/back-ldbm/filterindex.c | 11 +-
ldap/servers/slapd/back-ldbm/ldbm_search.c | 117 ++++++++++----------
ldap/servers/slapd/back-ldbm/vlv.c | 2 +-
ldap/servers/slapd/daemon.c | 13 ++-
ldap/servers/slapd/operation.c | 9 +-
ldap/servers/slapd/opshared.c | 85 +++++++++------
ldap/servers/slapd/pagedresults.c | 165 ++++++++++++++++++++++++++---
ldap/servers/slapd/proto-slap.h | 46 +++++---
ldap/servers/slapd/slap.h | 2 +
ldap/servers/slapd/sort.c | 6 +-
10 files changed, 320 insertions(+), 136 deletions(-)
diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c
index 27b20ec..995a62e 100644
--- a/ldap/servers/slapd/back-ldbm/filterindex.c
+++ b/ldap/servers/slapd/back-ldbm/filterindex.c
@@ -317,7 +317,7 @@ ava_candidates(
if ( unindexed ) {
unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED;
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
/* We don't use valuearray_free here since the valueset, berval
@@ -349,7 +349,7 @@ ava_candidates(
if ( unindexed ) {
unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED;
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
valuearray_free( &ivals );
LDAPDebug( LDAP_DEBUG_TRACE, "<= ava_candidates %lu\n",
@@ -390,7 +390,7 @@ presence_candidates(
unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED;
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed(pb->pb_conn, pb->pb_op, pr_idx);
}
if (idl != NULL && ALLIDS(idl) && strcasecmp(type, "nscpentrydn") == 0) {
@@ -504,6 +504,7 @@ extensible_candidates(
SLAPI_PAGED_RESULTS_INDEX,
&pr_idx );
pagedresults_set_unindexed( glob_pb->pb_conn,
+ glob_pb->pb_op,
pr_idx );
}
if (idl2 == NULL)
@@ -916,7 +917,7 @@ substring_candidates(
slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
if ( ivals == NULL || *ivals == NULL ) {
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
LDAPDebug( LDAP_DEBUG_TRACE,
"<= sub_candidates ALLIDS (no keys)\n", 0, 0, 0 );
return( idl_allids( be ) );
@@ -930,7 +931,7 @@ substring_candidates(
idl = keys2idl( be, type, indextype_SUB, ivals, err, &unindexed, &txn, allidslimit );
if ( unindexed ) {
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
valuearray_free( &ivals );
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
index f86f27c..670f627 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
@@ -53,7 +53,7 @@ static int build_candidate_list( Slapi_PBlock *pb, backend *be,
static IDList *base_candidates( Slapi_PBlock *pb, struct backentry *e );
static IDList *onelevel_candidates( Slapi_PBlock *pb, backend *be, const char *base, struct backentry *e, Slapi_Filter *filter, int managedsait, int *lookup_returned_allidsp, int *err );
static back_search_result_set* new_search_result_set(IDList* idl,int vlv, int lookthroughlimit);
-static void delete_search_result_set( back_search_result_set **sr );
+static void delete_search_result_set(Slapi_PBlock *pb, back_search_result_set **sr);
static int can_skip_filter_test( Slapi_PBlock *pb, struct slapi_filter *f,
int scope, IDList *idl );
@@ -165,6 +165,7 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb,
int estimate = 0; /* estimated search result count */
backend *be;
ldbm_instance *inst;
+ back_search_result_set *sr = NULL;
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
inst = (ldbm_instance *) be->be_instance_info;
@@ -178,19 +179,14 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb,
{
slapi_send_ldap_result( pb, ldap_result, NULL, ldap_result_description, 0, NULL );
}
- {
- /* hack hack --- code to free the result set if we don't need it */
- /* We get it and check to see if the structure was ever used */
- back_search_result_set *sr = NULL;
- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
- if ( (NULL != sr) && (function_result != 0) ) {
- int pr_idx = -1;
- slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
- delete_search_result_set(&sr);
+ /* code to free the result set if we don't need it */
+ /* We get it and check to see if the structure was ever used */
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
+ if (sr) {
+ if (function_result) {
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
+ delete_search_result_set(pb, &sr);
}
}
if (vlv_request_control)
@@ -853,7 +849,7 @@ ldbm_back_search( Slapi_PBlock *pb )
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
}
sr->sr_candidates = candidates;
@@ -1341,13 +1337,24 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
int estimate = 0; /* estimated search result count */
back_txn txn = {NULL};
int pr_idx = -1;
+ Slapi_Connection *conn;
+ Slapi_Operation *op;
+ slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &basesdn );
+ if (NULL == basesdn) {
+ slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL,
+ "Null target DN", 0, NULL );
+ return( -1 );
+ }
+ slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
+ if (NULL == sr) {
+ goto bail;
+ }
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
slapi_pblock_get( pb, SLAPI_MANAGEDSAIT, &managedsait );
slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
- slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &basesdn );
slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &slimit );
slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
@@ -1355,32 +1362,30 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
slapi_pblock_get( pb, SLAPI_SEARCH_REFERRALS, &urls );
slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID, &target_uniqueid );
- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
slapi_pblock_get( pb, SLAPI_TXN, &txn.back_txn_txn );
- slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
+ slapi_pblock_get( pb, SLAPI_CONNECTION, &conn );
+ slapi_pblock_get( pb, SLAPI_OPERATION, &op );
if ( !txn.back_txn_txn ) {
dblayer_txn_init( li, &txn );
slapi_pblock_set( pb, SLAPI_TXN, txn.back_txn_txn );
}
- if (NULL == sr) {
- goto bail;
- }
-
if (sr->sr_norm_filter) {
int val = 1;
slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &val );
filter = sr->sr_norm_filter;
}
- if (NULL == basesdn) {
- slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL,
- "Null target DN", 0, NULL );
- return( -1 );
- }
-
- if (sr->sr_current_sizelimit >= 0) {
+ if (op_is_pagedresults(op)) {
+ int myslimit;
+ /* On Simple Paged Results search, sizelimit is appied for each page. */
+ slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
+ myslimit = pagedresults_get_sizelimit(conn, op, pr_idx);
+ if (myslimit >= 0) {
+ slimit = myslimit;
+ }
+ } else if (sr->sr_current_sizelimit >= 0) {
/*
* sr_current_sizelimit contains the current sizelimit.
* In case of paged results, getting one page is one operation,
@@ -1397,8 +1402,7 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
/* Return to the cache the entry we handed out last time */
/* If we are using the extension, the front end will tell
* us when to do this so we don't do it now */
- if ( !use_extension )
- {
+ if (sr->sr_entry && !use_extension) {
CACHE_RETURN( &inst->inst_cache, &(sr->sr_entry) );
sr->sr_entry = NULL;
}
@@ -1422,15 +1426,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
/* check for abandon */
if ( slapi_op_abandoned( pb ) || (NULL == sr) )
{
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = SLAPI_FAIL_GENERAL;
goto bail;
}
@@ -1439,15 +1440,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
curtime = current_time();
if ( tlimit != -1 && curtime > stoptime )
{
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = SLAPI_FAIL_GENERAL;
slapi_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, urls );
goto bail;
@@ -1456,15 +1454,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
/* check lookthrough limit */
if ( llimit != -1 && sr->sr_lookthroughcount >= llimit )
{
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = SLAPI_FAIL_GENERAL;
slapi_send_ldap_result( pb, LDAP_ADMINLIMIT_EXCEEDED, NULL, NULL, nentries, urls );
goto bail;
@@ -1476,15 +1471,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
{
/* No more entries */
/* destroy back_search_result_set */
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
if ( use_extension ) {
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
}
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
rc = 0;
goto bail;
}
@@ -1617,17 +1609,20 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
{
if ( --slimit < 0 ) {
CACHE_RETURN( &inst->inst_cache, &e );
- /* in case paged results, clean up the conn */
- pagedresults_set_search_result( pb->pb_conn, NULL,
- 0, pr_idx);
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate );
- delete_search_result_set( &sr );
+ delete_search_result_set(pb, &sr);
slapi_send_ldap_result( pb, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, nentries, urls );
rc = SLAPI_FAIL_GENERAL;
goto bail;
}
slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, &slimit );
+ if (op_is_pagedresults(op)) {
+ /*
+ * On Simple Paged Results search,
+ * sizelimit is appied to each page.
+ */
+ pagedresults_set_sizelimit(conn, op, slimit, pr_idx);
+ }
sr->sr_current_sizelimit = slimit;
}
if ( (filter_test != 0) && sr->sr_virtuallistview)
@@ -1734,13 +1729,20 @@ new_search_result_set(IDList *idl, int vlv, int lookthroughlimit)
}
static void
-delete_search_result_set( back_search_result_set **sr )
+delete_search_result_set( Slapi_PBlock *pb, back_search_result_set **sr )
{
int rc = 0, filt_errs = 0;
- if ( NULL == sr || NULL == *sr)
+ if ( NULL == sr || NULL == *sr )
{
return;
}
+ if (pb) {
+ if (op_is_pagedresults(pb->pb_op)) {
+ /* If the op is pagedresults, let the module clean up sr. */
+ return;
+ }
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
+ }
if ( NULL != (*sr)->sr_candidates )
{
idl_free( (*sr)->sr_candidates );
@@ -1755,12 +1757,17 @@ delete_search_result_set( back_search_result_set **sr )
slapi_filter_free((*sr)->sr_norm_filter, 1);
memset( *sr, 0, sizeof( back_search_result_set ) );
slapi_ch_free( (void**)sr );
+ return;
}
+/*
+ * This function is called from pagedresults free/cleanup functions.
+ */
void
ldbm_back_search_results_release( void **sr )
{
- delete_search_result_set( (back_search_result_set **)sr );
+ /* passing NULL pb forces to delete the search result set */
+ delete_search_result_set( NULL, (back_search_result_set **)sr );
}
int
diff --git a/ldap/servers/slapd/back-ldbm/vlv.c b/ldap/servers/slapd/back-ldbm/vlv.c
index 2c09531..dcc42fa 100644
--- a/ldap/servers/slapd/back-ldbm/vlv.c
+++ b/ldap/servers/slapd/back-ldbm/vlv.c
@@ -1156,7 +1156,7 @@ vlv_search_build_candidate_list(Slapi_PBlock *pb, const Slapi_DN *base, int *vlv
slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx );
slapi_rwlock_unlock(be->vlvSearchList_lock);
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
- pagedresults_set_unindexed( pb->pb_conn, pr_idx );
+ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx );
rc = VLV_FIND_SEARCH_FAILED;
} else if((*vlv_rc=vlvIndex_accessallowed(pi, pb)) != LDAP_SUCCESS) {
slapi_rwlock_unlock(be->vlvSearchList_lock);
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 0a87293..75a83c0 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1363,14 +1363,19 @@ void slapd_daemon( daemon_ports_t *ports )
mapping_tree_free ();
}
+ /*
+ * connection_table_free could use callbacks in the backend.
+ * (e.g., be_search_results_release)
+ * Thus, it needs to be called before be_cleanupall.
+ */
+ connection_table_free(the_connection_table);
+ the_connection_table= NULL;
+
be_cleanupall ();
- LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n",
+ LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n",
0, 0, 0 );
referrals_free();
- connection_table_free(the_connection_table);
- the_connection_table= NULL;
-
/* tell the time thread to shutdown and then wait for it */
time_shutdown = 1;
PR_JoinThread( time_thread_p );
diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c
index 13e05c1..01ebfef 100644
--- a/ldap/servers/slapd/operation.c
+++ b/ldap/servers/slapd/operation.c
@@ -201,10 +201,11 @@ operation_new(int flags)
o->o_next = NULL;
o->o_flags= flags;
if ( config_get_accesslog_level() & LDAP_DEBUG_TIMING ) {
- o->o_interval = PR_IntervalNow();
- } else {
- o->o_interval = (PRIntervalTime)0;
- }
+ o->o_interval = PR_IntervalNow();
+ } else {
+ o->o_interval = (PRIntervalTime)0;
+ }
+ o->o_pagedresults_sizelimit = -1;
}
return o;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index fabe8a4..a96b950 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -245,7 +245,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
int internal_op;
Slapi_DN *basesdn = NULL;
Slapi_DN *sdn = NULL;
- Slapi_Operation *operation;
+ Slapi_Operation *operation = NULL;
Slapi_Entry *referral = NULL;
char *proxydn = NULL;
char *proxystr = NULL;
@@ -271,7 +271,6 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
int curr_search_count = 0;
Slapi_Backend *pr_be = NULL;
void *pr_search_result = NULL;
- int pr_reset_processing = 0;
int pr_idx = -1;
Slapi_DN *orig_sdn = NULL;
int free_sdn = 0;
@@ -469,23 +468,16 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
if ((LDAP_SUCCESS == rc) ||
(LDAP_CANCELLED == rc) || (0 == pagesize)) {
unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED;
- if (pagedresults_check_or_set_processing(pb->pb_conn, pr_idx)) {
- send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM,
- NULL, "Simple Paged Results Search "
- "already in progress on this connection",
- 0, NULL);
- goto free_and_return_nolock;
- }
- /* need to reset after we are done with this op */
- pr_reset_processing = 1;
op_set_pagedresults(operation);
pr_be = pagedresults_get_current_be(pb->pb_conn, pr_idx);
pr_search_result = pagedresults_get_search_result(pb->pb_conn,
+ operation,
pr_idx);
estimate =
pagedresults_get_search_result_set_size_estimate(pb->pb_conn,
+ operation,
pr_idx);
- if (pagedresults_get_unindexed(pb->pb_conn, pr_idx)) {
+ if (pagedresults_get_unindexed(pb->pb_conn, operation, pr_idx)) {
opnote |= SLAPI_OP_NOTE_UNINDEXED;
}
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
@@ -640,7 +632,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
time_up = (tlimit==-1 ? -1 : optime + tlimit); /* -1: no time limit */
- pagedresults_set_timelimit(pb->pb_conn, time_up, pr_idx);
+ pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, time_up, pr_idx);
}
/* PAR: now filters have been rewritten, we can assign plugins to work on them */
@@ -694,12 +686,25 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
if (op_is_pagedresults(operation) && pr_search_result) {
void *sr = NULL;
/* PAGED RESULTS and already have the search results from the prev op */
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
- rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
+ pagedresults_lock(pb->pb_conn, pr_idx);
+ /*
+ * In async paged result case, the search result might be released
+ * by other theads. We need to double check it in the locked region.
+ */
+ pr_search_result = pagedresults_get_search_result(pb->pb_conn,
+ operation,
+ pr_idx);
+ if (pr_search_result) {
+ slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
+ rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
- /* search result could be reset in the backend/dse */
- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
- pagedresults_set_search_result(pb->pb_conn, sr, 0, pr_idx);
+ /* search result could be reset in the backend/dse */
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
+ pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx);
+ } else {
+ pr_stat = PAGEDRESULTS_SEARCH_END;
+ }
+ pagedresults_unlock(pb->pb_conn, pr_idx);
if (PAGEDRESULTS_SEARCH_END == pr_stat) {
/* no more entries to send in the backend */
@@ -720,14 +725,18 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
}
pagedresults_set_response_control(pb, 0, estimate,
curr_search_count, pr_idx);
- if (pagedresults_get_with_sort(pb->pb_conn, pr_idx)) {
+ if (pagedresults_get_with_sort(pb->pb_conn, operation, pr_idx)) {
sort_make_sort_response_control(pb, CONN_GET_SORT_RESULT_CODE, NULL);
}
pagedresults_set_search_result_set_size_estimate(pb->pb_conn,
+ operation,
estimate, pr_idx);
next_be = NULL; /* to break the loop */
if (curr_search_count == -1) {
- pagedresults_free_one(pb->pb_conn, pr_idx);
+ pagedresults_lock(pb->pb_conn, pr_idx);
+ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
+ pagedresults_free_one(pb->pb_conn, operation, pr_idx);
+ pagedresults_unlock(pb->pb_conn, pr_idx);
}
} else {
/* be_suffix null means that we are searching the default backend
@@ -849,7 +858,11 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
int with_sort = operation->o_flags & OP_FLAG_SERVER_SIDE_SORTING;
curr_search_count = pnentries;
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
if (PAGEDRESULTS_SEARCH_END == pr_stat) {
+ if (sr) { /* in case a left over sr is found, clean it up */
+ be->be_search_results_release(&sr);
+ }
if (NULL == next_be) {
/* no more entries && no more backends */
curr_search_count = -1;
@@ -861,24 +874,31 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
}
} else {
curr_search_count = pnentries;
- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
- if (pagedresults_set_current_be(pb->pb_conn, be, pr_idx) < 0 ||
- pagedresults_set_search_result(pb->pb_conn, sr, 0, pr_idx) < 0 ||
- pagedresults_set_search_result_count(pb->pb_conn,
- curr_search_count, pr_idx) < 0 ||
- pagedresults_set_search_result_set_size_estimate(pb->pb_conn,
- estimate, pr_idx) < 0 ||
- pagedresults_set_with_sort(pb->pb_conn, with_sort, pr_idx) < 0) {
+ pagedresults_lock(pb->pb_conn, pr_idx);
+ if ((pagedresults_set_current_be(pb->pb_conn, be, pr_idx) < 0) ||
+ (pagedresults_set_search_result(pb->pb_conn, operation,
+ sr, 0, pr_idx) < 0) ||
+ (pagedresults_set_search_result_count(pb->pb_conn, operation,
+ curr_search_count,
+ pr_idx) < 0) ||
+ (pagedresults_set_search_result_set_size_estimate(pb->pb_conn,
+ operation,
+ estimate,
+ pr_idx) < 0) ||
+ (pagedresults_set_with_sort(pb->pb_conn, operation,
+ with_sort, pr_idx) < 0)) {
+ pagedresults_unlock(pb->pb_conn, pr_idx);
goto free_and_return;
}
+ pagedresults_unlock(pb->pb_conn, pr_idx);
}
pagedresults_set_response_control(pb, 0, estimate,
curr_search_count, pr_idx);
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
next_be = NULL; /* to break the loop */
if (curr_search_count == -1) {
- pagedresults_free_one(pb->pb_conn, pr_idx);
+ pagedresults_free_one(pb->pb_conn, operation, pr_idx);
}
}
@@ -1007,9 +1027,6 @@ free_and_return_nolock:
slapi_ch_free_string(&proxydn);
slapi_ch_free_string(&proxystr);
- if (pr_reset_processing) {
- pagedresults_reset_processing(pb->pb_conn, pr_idx);
- }
}
/* Returns 1 if this processing on this entry is finished
@@ -1257,7 +1274,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
*pnentries = 0;
- while (!done)
+ while (!done)
{
Slapi_Entry *gerentry = NULL;
Slapi_Operation *operation;
@@ -1275,7 +1292,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
operation_out_of_disk_space();
}
pr_stat = PAGEDRESULTS_SEARCH_END;
- pagedresults_set_timelimit(pb->pb_conn, 0, pr_idx);
+ pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, 0, pr_idx);
rval = -1;
done = 1;
continue;
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
index 9b294eb..78bd6b0 100644
--- a/ldap/servers/slapd/pagedresults.c
+++ b/ldap/servers/slapd/pagedresults.c
@@ -131,6 +131,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
}
}
conn->c_pagedresults.prl_count++;
+ conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock();
} else {
/* Repeated paged results request.
* PagedResults is already allocated. */
@@ -140,6 +141,8 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
*index = strtol(ptr, NULL, 10);
slapi_ch_free_string(&ptr);
}
+ /* reset sizelimit */
+ op->o_pagedresults_sizelimit = -1;
slapi_ch_free((void **)&cookie.bv_val);
if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) {
@@ -243,10 +246,13 @@ bailout:
}
int
-pagedresults_free_one( Connection *conn, int index )
+pagedresults_free_one( Connection *conn, Operation *op, int index )
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return 0; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_free_one: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -256,13 +262,19 @@ pagedresults_free_one( Connection *conn, int index )
"conn=%d paged requests list count is %d\n",
conn->c_connid, conn->c_pagedresults.prl_count);
} else if (index < conn->c_pagedresults.prl_maxlen) {
+ PRLock *prmutex = NULL;
PagedResults *prp = conn->c_pagedresults.prl_list + index;
if (prp && prp->pr_current_be &&
prp->pr_current_be->be_search_results_release &&
prp->pr_search_result_set) {
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
}
+ if (prp->pr_mutex) {
+ /* pr_mutex is reused; back it up and reset it. */
+ prmutex = prp->pr_mutex;
+ }
memset(prp, '\0', sizeof(PagedResults));
+ prp->pr_mutex = prmutex;
conn->c_pagedresults.prl_count--;
rc = 0;
}
@@ -348,9 +360,12 @@ pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index)
}
void *
-pagedresults_get_search_result(Connection *conn, int index)
+pagedresults_get_search_result(Connection *conn, Operation *op, int index)
{
void *sr = NULL;
+ if (!op_is_pagedresults(op)) {
+ return sr; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_search_result: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -366,20 +381,31 @@ pagedresults_get_search_result(Connection *conn, int index)
}
int
-pagedresults_set_search_result(Connection *conn, void *sr,
+pagedresults_set_search_result(Connection *conn, Operation *op, void *sr,
int locked, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return 0; /* noop */
+ }
LDAPDebug2Args(LDAP_DEBUG_TRACE,
"--> pagedresults_set_search_result: idx=%d, sr=%p\n",
index, sr);
if (conn && (index > -1)) {
if (!locked) PR_Lock(conn->c_mutex);
if (index < conn->c_pagedresults.prl_maxlen) {
- conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
+ if (sr) { /* set */
+ if (NULL ==
+ conn->c_pagedresults.prl_list[index].pr_search_result_set) {
+ conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
+ rc = 0;
+ }
+ } else { /* reset */
+ conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
+ rc = 0;
+ }
}
if (!locked) PR_Unlock(conn->c_mutex);
- rc = 0;
}
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"<-- pagedresults_set_search_result: %d\n", rc);
@@ -387,9 +413,12 @@ pagedresults_set_search_result(Connection *conn, void *sr,
}
int
-pagedresults_get_search_result_count(Connection *conn, int index)
+pagedresults_get_search_result_count(Connection *conn, Operation *op, int index)
{
int count = 0;
+ if (!op_is_pagedresults(op)) {
+ return count; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_search_result_count: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -405,9 +434,13 @@ pagedresults_get_search_result_count(Connection *conn, int index)
}
int
-pagedresults_set_search_result_count(Connection *conn, int count, int index)
+pagedresults_set_search_result_count(Connection *conn, Operation *op,
+ int count, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_search_result_count: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -424,9 +457,14 @@ pagedresults_set_search_result_count(Connection *conn, int count, int index)
}
int
-pagedresults_get_search_result_set_size_estimate(Connection *conn, int index)
+pagedresults_get_search_result_set_size_estimate(Connection *conn,
+ Operation *op,
+ int index)
{
int count = 0;
+ if (!op_is_pagedresults(op)) {
+ return count; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_search_result_set_size_estimate: "
"idx=%d\n", index);
@@ -445,9 +483,13 @@ pagedresults_get_search_result_set_size_estimate(Connection *conn, int index)
int
pagedresults_set_search_result_set_size_estimate(Connection *conn,
+ Operation *op,
int count, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_search_result_set_size_estimate: "
"idx=%d\n", index);
@@ -466,9 +508,12 @@ pagedresults_set_search_result_set_size_estimate(Connection *conn,
}
int
-pagedresults_get_with_sort(Connection *conn, int index)
+pagedresults_get_with_sort(Connection *conn, Operation *op, int index)
{
int flags = 0;
+ if (!op_is_pagedresults(op)) {
+ return flags; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_with_sort: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -484,9 +529,13 @@ pagedresults_get_with_sort(Connection *conn, int index)
}
int
-pagedresults_set_with_sort(Connection *conn, int flags, int index)
+pagedresults_set_with_sort(Connection *conn, Operation *op,
+ int flags, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_with_sort: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -505,9 +554,12 @@ pagedresults_set_with_sort(Connection *conn, int flags, int index)
}
int
-pagedresults_get_unindexed(Connection *conn, int index)
+pagedresults_get_unindexed(Connection *conn, Operation *op, int index)
{
int flags = 0;
+ if (!op_is_pagedresults(op)) {
+ return flags; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_unindexed: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -523,9 +575,12 @@ pagedresults_get_unindexed(Connection *conn, int index)
}
int
-pagedresults_set_unindexed(Connection *conn, int index)
+pagedresults_set_unindexed(Connection *conn, Operation *op, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_unindexed: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -543,9 +598,12 @@ pagedresults_set_unindexed(Connection *conn, int index)
}
int
-pagedresults_get_sort_result_code(Connection *conn, int index)
+pagedresults_get_sort_result_code(Connection *conn, Operation *op, int index)
{
int code = LDAP_OPERATIONS_ERROR;
+ if (!op_is_pagedresults(op)) {
+ return code; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_get_sort_result_code: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -561,9 +619,13 @@ pagedresults_get_sort_result_code(Connection *conn, int index)
}
int
-pagedresults_set_sort_result_code(Connection *conn, int code, int index)
+pagedresults_set_sort_result_code(Connection *conn, Operation *op,
+ int code, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_sort_result_code: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -580,9 +642,13 @@ pagedresults_set_sort_result_code(Connection *conn, int code, int index)
}
int
-pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index)
+pagedresults_set_timelimit(Connection *conn, Operation *op,
+ time_t timelimit, int index)
{
int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
"--> pagedresults_set_timelimit: idx=%d\n", index);
if (conn && (index > -1)) {
@@ -597,6 +663,35 @@ pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index)
return rc;
}
+int
+pagedresults_set_sizelimit(Connection *conn, Operation *op,
+ int sizelimit, int index)
+{
+ int rc = -1;
+ if (!op_is_pagedresults(op)) {
+ return rc; /* noop */
+ }
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+ "--> pagedresults_set_sizelimit: idx=%d\n", index);
+ op->o_pagedresults_sizelimit = sizelimit;
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_set_sizelimit: %d\n", rc);
+ return rc;
+}
+
+int
+pagedresults_get_sizelimit(Connection *conn, Operation *op, int index)
+{
+ int sizelimit = -1;
+ if (!op_is_pagedresults(op)) {
+ return sizelimit; /* noop */
+ }
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+ "--> pagedresults_get_sizelimit: idx=%d\n", index);
+ sizelimit = op->o_pagedresults_sizelimit;
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_get_sizelimit\n");
+ return sizelimit;
+}
+
/*
* pagedresults_cleanup cleans up the pagedresults list;
* it does not free the list.
@@ -629,6 +724,9 @@ pagedresults_cleanup(Connection *conn, int needlock)
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
rc = 1;
}
+ if (prp->pr_mutex) {
+ PR_DestroyLock(prp->pr_mutex);
+ }
memset(prp, '\0', sizeof(PagedResults));
}
conn->c_pagedresults.prl_count = 0;
@@ -665,6 +763,9 @@ pagedresults_cleanup_all(Connection *conn, int needlock)
for (i = 0; conn->c_pagedresults.prl_list &&
i < conn->c_pagedresults.prl_maxlen; i++) {
prp = conn->c_pagedresults.prl_list + i;
+ if (prp->pr_mutex) {
+ PR_DestroyLock(prp->pr_mutex);
+ }
if (prp->pr_current_be && prp->pr_search_result_set &&
prp->pr_current_be->be_search_results_release) {
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
@@ -681,6 +782,7 @@ pagedresults_cleanup_all(Connection *conn, int needlock)
return rc;
}
+#if 0 /* Stopped using it (#47347) */
/*
* check to see if this connection is currently processing
* a pagedresults search - if it is, return True - if not,
@@ -734,6 +836,7 @@ pagedresults_reset_processing(Connection *conn, int index)
"<-- pagedresults_reset_processing: %d\n", ret);
return ret;
}
+#endif
/* Are all the paged results requests timed out? */
int
@@ -819,3 +922,35 @@ op_set_pagedresults(Operation *op)
}
op->o_flags |= OP_FLAG_PAGED_RESULTS;
}
+
+/*
+ * pagedresults_lock/unlock -- introduced to protect search results for the
+ * asynchronous searches.
+ */
+void
+pagedresults_lock( Connection *conn, int index )
+{
+ PagedResults *prp;
+ if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
+ return;
+ }
+ prp = conn->c_pagedresults.prl_list + index;
+ if (prp->pr_mutex) {
+ PR_Lock(prp->pr_mutex);
+ }
+ return;
+}
+
+void
+pagedresults_unlock( Connection *conn, int index )
+{
+ PagedResults *prp;
+ if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
+ return;
+ }
+ prp = conn->c_pagedresults.prl_list + index;
+ if (prp->pr_mutex) {
+ PR_Unlock(prp->pr_mutex);
+ }
+ return;
+}
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index a68c2d9..911dadd 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1405,34 +1405,48 @@ void pagedresults_set_response_control(Slapi_PBlock *pb, int iscritical,
int curr_search_count, int index);
Slapi_Backend *pagedresults_get_current_be(Connection *conn, int index);
int pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index);
-void *pagedresults_get_search_result(Connection *conn, int index);
-int pagedresults_set_search_result(Connection *conn, void *sr,
+void *pagedresults_get_search_result(Connection *conn, Operation *op,
+ int index);
+int pagedresults_set_search_result(Connection *conn, Operation *op, void *sr,
int locked, int index);
-int pagedresults_get_search_result_count(Connection *conn, int index);
-int pagedresults_set_search_result_count(Connection *conn, int cnt, int index);
-int pagedresults_get_search_result_set_size_estimate(Connection *conn,
+int pagedresults_get_search_result_count(Connection *conn, Operation *op,
+ int index);
+int pagedresults_set_search_result_count(Connection *conn, Operation *op, int cnt, int index);
+int pagedresults_get_search_result_set_size_estimate(Connection *conn,
+ Operation *op,
int index);
-int pagedresults_set_search_result_set_size_estimate(Connection *conn, int cnt,
+int pagedresults_set_search_result_set_size_estimate(Connection *conn,
+ Operation *op, int cnt,
int index);
-int pagedresults_get_with_sort(Connection *conn, int index);
-int pagedresults_set_with_sort(Connection *conn, int flags, int index);
-int pagedresults_get_unindexed(Connection *conn, int index);
-int pagedresults_set_unindexed(Connection *conn, int index);
-int pagedresults_get_sort_result_code(Connection *conn, int index);
-int pagedresults_set_sort_result_code(Connection *conn, int code, int index);
-int pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index);
+int pagedresults_get_with_sort(Connection *conn, Operation *op, int index);
+int pagedresults_set_with_sort(Connection *conn, Operation *op,
+ int flags, int index);
+int pagedresults_get_unindexed(Connection *conn, Operation *op, int index);
+int pagedresults_set_unindexed(Connection *conn, Operation *op, int index);
+int pagedresults_get_sort_result_code(Connection *conn, Operation *op,
+ int index);
+int pagedresults_set_sort_result_code(Connection *conn, Operation *op,
+ int code, int index);
+int pagedresults_set_timelimit(Connection *conn, Operation *op,
+ time_t timelimit, int index);
+int pagedresults_get_sizelimit(Connection *conn, Operation *op, int index);
+int pagedresults_set_sizelimit(Connection *conn, Operation *op,
+ int sizelimit, int index);
int pagedresults_cleanup(Connection *conn, int needlock);
+#if 0 /* Stopped using it (#47347) */
int pagedresults_check_or_set_processing(Connection *conn, int index);
int pagedresults_reset_processing(Connection *conn, int index);
+#endif
int pagedresults_is_timedout_nolock(Connection *conn);
int pagedresults_reset_timedout_nolock(Connection *conn);
int pagedresults_in_use_nolock(Connection *conn);
-int pagedresults_free_one(Connection *conn, int index);
-int pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid );
+int pagedresults_free_one(Connection *conn, Operation *op, int index);
+int pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid);
int op_is_pagedresults(Operation *op);
int pagedresults_cleanup_all(Connection *conn, int needlock);
void op_set_pagedresults(Operation *op);
-
+void pagedresults_lock(Connection *conn, int index);
+void pagedresults_unlock(Connection *conn, int index);
/*
* sort.c
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index d290c92..ef986e2 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1339,6 +1339,7 @@ typedef struct op {
unsigned long o_abandoned_op; /* operation abandoned by this operation - used to decide which plugins to invoke */
struct slapi_operation_parameters o_params;
struct slapi_operation_results o_results;
+ int o_pagedresults_sizelimit;
} Operation;
/*
@@ -1367,6 +1368,7 @@ typedef struct _paged_results {
time_t pr_timelimit; /* time limit for this request */
int pr_flags;
ber_int_t pr_msgid; /* msgid of the request; to abandon */
+ PRLock *pr_mutex; /* protect each conn structure */
} PagedResults;
/* array of simple paged structure stashed in connection */
diff --git a/ldap/servers/slapd/sort.c b/ldap/servers/slapd/sort.c
index 903fa6f..72c9ec9 100644
--- a/ldap/servers/slapd/sort.c
+++ b/ldap/servers/slapd/sort.c
@@ -58,12 +58,14 @@ sort_make_sort_response_control ( Slapi_PBlock *pb, int code, char *error_type)
slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
if (code == CONN_GET_SORT_RESULT_CODE) {
- code = pagedresults_get_sort_result_code(pb->pb_conn, pr_idx);
+ code = pagedresults_get_sort_result_code(pb->pb_conn,
+ pb->pb_op, pr_idx);
} else {
Slapi_Operation *operation;
slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
if (op_is_pagedresults(operation)) {
- pagedresults_set_sort_result_code(pb->pb_conn, code, pr_idx);
+ pagedresults_set_sort_result_code(pb->pb_conn,
+ pb->pb_op, code, pr_idx);
}
}
--
1.8.1.4