|
|
df9752 |
From 810e825adebf9f1669bab9f61831f158e0c2f941 Mon Sep 17 00:00:00 2001
|
|
|
df9752 |
From: Noriko Hosoi <nhosoi@redhat.com>
|
|
|
df9752 |
Date: Thu, 4 Jun 2015 16:27:05 -0700
|
|
|
df9752 |
Subject: [PATCH 70/72] Ticket #48192 - Individual abandoned simple paged
|
|
|
df9752 |
results request has no chance to be cleaned up
|
|
|
df9752 |
|
|
|
df9752 |
Description: When allocating a slot in simple paged results array stashed
|
|
|
df9752 |
in a connection in pagedresults_parse_control_value, a new code is added
|
|
|
df9752 |
to scan the array if the existing slot is timed out or not. If it is, the
|
|
|
df9752 |
slot is released and a search results is released if it is attached.
|
|
|
df9752 |
|
|
|
df9752 |
Also, if a request is abandoned, instead of returning a valid cookie, it
|
|
|
df9752 |
changed to return an empty cookie to inform the client the request was not
|
|
|
df9752 |
successfully completed.
|
|
|
df9752 |
|
|
|
df9752 |
https://fedorahosted.org/389/ticket/48192
|
|
|
df9752 |
|
|
|
df9752 |
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
|
|
|
df9752 |
|
|
|
df9752 |
(cherry picked from commit f3c3125fc9fd4dc1cbd41027d6442cb525efd014)
|
|
|
df9752 |
(cherry picked from commit 97c707df4e11936202310e99bcf5f45d15b49f0f)
|
|
|
df9752 |
---
|
|
|
df9752 |
ldap/servers/slapd/opshared.c | 41 +++++++-------
|
|
|
df9752 |
ldap/servers/slapd/pagedresults.c | 110 ++++++++++++++++++++++++--------------
|
|
|
df9752 |
2 files changed, 89 insertions(+), 62 deletions(-)
|
|
|
df9752 |
|
|
|
df9752 |
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
|
|
|
df9752 |
index 5dff42f..9cf431c 100644
|
|
|
df9752 |
--- a/ldap/servers/slapd/opshared.c
|
|
|
df9752 |
+++ b/ldap/servers/slapd/opshared.c
|
|
|
df9752 |
@@ -517,8 +517,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
|
|
|
df9752 |
rc = pagedresults_parse_control_value(pb, ctl_value, &pagesize, &pr_idx, be);
|
|
|
df9752 |
/* Let's set pr_idx even if it fails; in case, pr_idx == -1. */
|
|
|
df9752 |
slapi_pblock_set(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
|
|
|
df9752 |
- if ((LDAP_SUCCESS == rc) ||
|
|
|
df9752 |
- (LDAP_CANCELLED == rc) || (0 == pagesize)) {
|
|
|
df9752 |
+ if ((LDAP_SUCCESS == rc) || (LDAP_CANCELLED == rc) || (0 == pagesize)) {
|
|
|
df9752 |
unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED;
|
|
|
df9752 |
op_set_pagedresults(operation);
|
|
|
df9752 |
pr_be = pagedresults_get_current_be(pb->pb_conn, pr_idx);
|
|
|
df9752 |
@@ -545,9 +544,8 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
|
|
|
df9752 |
}
|
|
|
df9752 |
slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
|
|
|
df9752 |
if ((LDAP_CANCELLED == rc) || (0 == pagesize)) {
|
|
|
df9752 |
- /* paged-results-request was abandoned */
|
|
|
df9752 |
- pagedresults_set_response_control(pb, 0, estimate,
|
|
|
df9752 |
- curr_search_count, pr_idx);
|
|
|
df9752 |
+ /* paged-results-request was abandoned; making an empty cookie. */
|
|
|
df9752 |
+ pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx);
|
|
|
df9752 |
send_ldap_result(pb, 0, NULL,
|
|
|
df9752 |
"Simple Paged Results Search abandoned",
|
|
|
df9752 |
0, NULL);
|
|
|
df9752 |
@@ -574,10 +572,21 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
|
|
|
df9752 |
|
|
|
df9752 |
/* adjust time and size limits */
|
|
|
df9752 |
compute_limits (pb);
|
|
|
df9752 |
-
|
|
|
df9752 |
- /* call the pre-search plugins. if they succeed, call the backend
|
|
|
df9752 |
- search function. then call the post-search plugins. */
|
|
|
df9752 |
|
|
|
df9752 |
+ /* set the timelimit to clean up the too-long-lived-paged results requests */
|
|
|
df9752 |
+ if (op_is_pagedresults(operation)) {
|
|
|
df9752 |
+ time_t optime, time_up;
|
|
|
df9752 |
+ int tlimit;
|
|
|
df9752 |
+ slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
|
|
|
df9752 |
+ slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
|
|
|
df9752 |
+ time_up = (tlimit==-1 ? -1 : optime + tlimit); /* -1: no time limit */
|
|
|
df9752 |
+ pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, time_up, pr_idx);
|
|
|
df9752 |
+ }
|
|
|
df9752 |
+
|
|
|
df9752 |
+ /*
|
|
|
df9752 |
+ * call the pre-search plugins. if they succeed, call the backend
|
|
|
df9752 |
+ * search function. then call the post-search plugins.
|
|
|
df9752 |
+ */
|
|
|
df9752 |
/* ONREPL - should regular plugin be called for internal searches ? */
|
|
|
df9752 |
if (plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_SEARCH_FN) == 0)
|
|
|
df9752 |
{
|
|
|
df9752 |
@@ -642,16 +651,6 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
|
|
|
df9752 |
}
|
|
|
df9752 |
}
|
|
|
df9752 |
|
|
|
df9752 |
- /* set the timelimit to clean up the too-long-lived-paged results requests */
|
|
|
df9752 |
- if (op_is_pagedresults(operation)) {
|
|
|
df9752 |
- time_t optime, time_up;
|
|
|
df9752 |
- int tlimit;
|
|
|
df9752 |
- slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
|
|
|
df9752 |
- slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
|
|
|
df9752 |
- time_up = (tlimit==-1 ? -1 : optime + tlimit); /* -1: no time limit */
|
|
|
df9752 |
- pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, time_up, pr_idx);
|
|
|
df9752 |
- }
|
|
|
df9752 |
-
|
|
|
df9752 |
/* PAR: now filters have been rewritten, we can assign plugins to work on them */
|
|
|
df9752 |
index_subsys_assign_filter_decoders(pb);
|
|
|
df9752 |
|
|
|
df9752 |
@@ -880,10 +879,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
|
|
|
df9752 |
slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
|
|
|
df9752 |
if (PAGEDRESULTS_SEARCH_END == pr_stat) {
|
|
|
df9752 |
if (sr) { /* in case a left over sr is found, clean it up */
|
|
|
df9752 |
- PR_Lock(pb->pb_conn->c_mutex);
|
|
|
df9752 |
- pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx);
|
|
|
df9752 |
- be->be_search_results_release(&sr);
|
|
|
df9752 |
- PR_Unlock(pb->pb_conn->c_mutex);
|
|
|
df9752 |
+ pagedresults_free_one(pb->pb_conn, operation, pr_idx);
|
|
|
df9752 |
}
|
|
|
df9752 |
if (NULL == next_be) {
|
|
|
df9752 |
/* no more entries && no more backends */
|
|
|
df9752 |
@@ -1306,7 +1302,6 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
|
|
|
df9752 |
operation_out_of_disk_space();
|
|
|
df9752 |
}
|
|
|
df9752 |
pr_stat = PAGEDRESULTS_SEARCH_END;
|
|
|
df9752 |
- pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, 0, pr_idx);
|
|
|
df9752 |
rval = -1;
|
|
|
df9752 |
done = 1;
|
|
|
df9752 |
continue;
|
|
|
df9752 |
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
|
|
|
df9752 |
index 327da54..402dd10 100644
|
|
|
df9752 |
--- a/ldap/servers/slapd/pagedresults.c
|
|
|
df9752 |
+++ b/ldap/servers/slapd/pagedresults.c
|
|
|
df9752 |
@@ -41,6 +41,27 @@
|
|
|
df9752 |
|
|
|
df9752 |
#include "slap.h"
|
|
|
df9752 |
|
|
|
df9752 |
+/* helper function to clean up one prp slot */
|
|
|
df9752 |
+static void
|
|
|
df9752 |
+_pr_cleanup_one_slot(PagedResults *prp)
|
|
|
df9752 |
+{
|
|
|
df9752 |
+ PRLock *prmutex = NULL;
|
|
|
df9752 |
+ if (!prp) {
|
|
|
df9752 |
+ return;
|
|
|
df9752 |
+ }
|
|
|
df9752 |
+ if (prp->pr_current_be && prp->pr_current_be->be_search_results_release) {
|
|
|
df9752 |
+ /* sr is left; release it. */
|
|
|
df9752 |
+ prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
|
|
|
df9752 |
+ }
|
|
|
df9752 |
+ /* clean up the slot */
|
|
|
df9752 |
+ if (prp->pr_mutex) {
|
|
|
df9752 |
+ /* pr_mutex is reused; back it up and reset it. */
|
|
|
df9752 |
+ prmutex = prp->pr_mutex;
|
|
|
df9752 |
+ }
|
|
|
df9752 |
+ memset(prp, '\0', sizeof(PagedResults));
|
|
|
df9752 |
+ prp->pr_mutex = prmutex;
|
|
|
df9752 |
+}
|
|
|
df9752 |
+
|
|
|
df9752 |
/*
|
|
|
df9752 |
* Parse the value from an LDAPv3 "Simple Paged Results" control. They look
|
|
|
df9752 |
* like this:
|
|
|
df9752 |
@@ -65,6 +86,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
|
|
|
df9752 |
Connection *conn = pb->pb_conn;
|
|
|
df9752 |
Operation *op = pb->pb_op;
|
|
|
df9752 |
BerElement *ber = NULL;
|
|
|
df9752 |
+ PagedResults *prp = NULL;
|
|
|
df9752 |
|
|
|
df9752 |
LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_parse_control_value\n");
|
|
|
df9752 |
if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) {
|
|
|
df9752 |
@@ -117,13 +139,31 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
|
|
|
df9752 |
}
|
|
|
df9752 |
*index = maxlen; /* the first position in the new area */
|
|
|
df9752 |
} else {
|
|
|
df9752 |
- for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) {
|
|
|
df9752 |
- if (!conn->c_pagedresults.prl_list[i].pr_current_be) {
|
|
|
df9752 |
- conn->c_pagedresults.prl_list[i].pr_current_be = be;
|
|
|
df9752 |
+ time_t ctime = current_time();
|
|
|
df9752 |
+ prp = conn->c_pagedresults.prl_list;
|
|
|
df9752 |
+ for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) {
|
|
|
df9752 |
+ if (!prp->pr_current_be) { /* unused slot; take it */
|
|
|
df9752 |
+ prp->pr_current_be = be;
|
|
|
df9752 |
+ *index = i;
|
|
|
df9752 |
+ break;
|
|
|
df9752 |
+ } else if (((prp->pr_timelimit > 0) && (ctime < prp->pr_timelimit)) || /* timelimit exceeded */
|
|
|
df9752 |
+ (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) /* abandoned */) {
|
|
|
df9752 |
+ _pr_cleanup_one_slot(prp);
|
|
|
df9752 |
+ conn->c_pagedresults.prl_count--;
|
|
|
df9752 |
+ prp->pr_current_be = be;
|
|
|
df9752 |
*index = i;
|
|
|
df9752 |
break;
|
|
|
df9752 |
}
|
|
|
df9752 |
}
|
|
|
df9752 |
+ /* cleaning up the rest of the timedout if any */
|
|
|
df9752 |
+ for (++i; i < conn->c_pagedresults.prl_maxlen; i++, prp++) {
|
|
|
df9752 |
+ if (prp->pr_current_be &&
|
|
|
df9752 |
+ (((prp->pr_timelimit > 0) && (ctime < prp->pr_timelimit)) || /* timelimit exceeded */
|
|
|
df9752 |
+ (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED)) /* abandoned */) {
|
|
|
df9752 |
+ _pr_cleanup_one_slot(prp);
|
|
|
df9752 |
+ conn->c_pagedresults.prl_count--;
|
|
|
df9752 |
+ }
|
|
|
df9752 |
+ }
|
|
|
df9752 |
}
|
|
|
df9752 |
if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen) &&
|
|
|
df9752 |
!conn->c_pagedresults.prl_list[*index].pr_mutex) {
|
|
|
df9752 |
@@ -131,7 +171,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
|
|
|
df9752 |
}
|
|
|
df9752 |
conn->c_pagedresults.prl_count++;
|
|
|
df9752 |
} else {
|
|
|
df9752 |
- PagedResults *prp = NULL;
|
|
|
df9752 |
/* Repeated paged results request.
|
|
|
df9752 |
* PagedResults is already allocated. */
|
|
|
df9752 |
char *ptr = slapi_ch_malloc(cookie.bv_len + 1);
|
|
|
df9752 |
@@ -156,8 +195,10 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
|
|
|
df9752 |
slapi_ch_free((void **)&cookie.bv_val);
|
|
|
df9752 |
|
|
|
df9752 |
if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) {
|
|
|
df9752 |
- if (conn->c_pagedresults.prl_list[*index].pr_flags &
|
|
|
df9752 |
- CONN_FLAG_PAGEDRESULTS_ABANDONED) {
|
|
|
df9752 |
+ if (conn->c_pagedresults.prl_list[*index].pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) {
|
|
|
df9752 |
+ /* repeated case? */
|
|
|
df9752 |
+ prp = conn->c_pagedresults.prl_list + *index;
|
|
|
df9752 |
+ _pr_cleanup_one_slot(prp);
|
|
|
df9752 |
rc = LDAP_CANCELLED;
|
|
|
df9752 |
} else {
|
|
|
df9752 |
/* Need to keep the latest msgid to prepare for the abandon. */
|
|
|
df9752 |
@@ -273,20 +314,8 @@ pagedresults_free_one( Connection *conn, Operation *op, int index )
|
|
|
df9752 |
"conn=%d paged requests list count is %d\n",
|
|
|
df9752 |
conn->c_connid, conn->c_pagedresults.prl_count);
|
|
|
df9752 |
} else if (index < conn->c_pagedresults.prl_maxlen) {
|
|
|
df9752 |
- PRLock *prmutex = NULL;
|
|
|
df9752 |
PagedResults *prp = conn->c_pagedresults.prl_list + index;
|
|
|
df9752 |
- if (prp && prp->pr_current_be &&
|
|
|
df9752 |
- prp->pr_current_be->be_search_results_release &&
|
|
|
df9752 |
- prp->pr_search_result_set) {
|
|
|
df9752 |
- prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
|
|
|
df9752 |
- }
|
|
|
df9752 |
- prp->pr_current_be = NULL;
|
|
|
df9752 |
- if (prp->pr_mutex) {
|
|
|
df9752 |
- /* pr_mutex is reused; back it up and reset it. */
|
|
|
df9752 |
- prmutex = prp->pr_mutex;
|
|
|
df9752 |
- }
|
|
|
df9752 |
- memset(prp, '\0', sizeof(PagedResults));
|
|
|
df9752 |
- prp->pr_mutex = prmutex;
|
|
|
df9752 |
+ _pr_cleanup_one_slot(prp);
|
|
|
df9752 |
conn->c_pagedresults.prl_count--;
|
|
|
df9752 |
rc = 0;
|
|
|
df9752 |
}
|
|
|
df9752 |
@@ -309,7 +338,7 @@ pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid )
|
|
|
df9752 |
; /* Not a paged result. */
|
|
|
df9752 |
} else {
|
|
|
df9752 |
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
|
|
|
df9752 |
- "--> pagedresults_free_one: msgid=%d\n", msgid);
|
|
|
df9752 |
+ "--> pagedresults_free_one_msgid_nolock: msgid=%d\n", msgid);
|
|
|
df9752 |
for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) {
|
|
|
df9752 |
if (conn->c_pagedresults.prl_list[i].pr_msgid == msgid) {
|
|
|
df9752 |
PagedResults *prp = conn->c_pagedresults.prl_list + i;
|
|
|
df9752 |
@@ -318,16 +347,14 @@ pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid )
|
|
|
df9752 |
prp->pr_search_result_set) {
|
|
|
df9752 |
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
|
|
|
df9752 |
}
|
|
|
df9752 |
- prp->pr_current_be = NULL;
|
|
|
df9752 |
prp->pr_flags |= CONN_FLAG_PAGEDRESULTS_ABANDONED;
|
|
|
df9752 |
prp->pr_flags &= ~CONN_FLAG_PAGEDRESULTS_PROCESSING;
|
|
|
df9752 |
- conn->c_pagedresults.prl_count--;
|
|
|
df9752 |
rc = 0;
|
|
|
df9752 |
break;
|
|
|
df9752 |
}
|
|
|
df9752 |
}
|
|
|
df9752 |
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
|
|
|
df9752 |
- "<-- pagedresults_free_one: %d\n", rc);
|
|
|
df9752 |
+ "<-- pagedresults_free_one_msgid_nolock: %d\n", rc);
|
|
|
df9752 |
}
|
|
|
df9752 |
}
|
|
|
df9752 |
|
|
|
df9752 |
@@ -845,37 +872,42 @@ pagedresults_reset_processing(Connection *conn, int index)
|
|
|
df9752 |
}
|
|
|
df9752 |
#endif
|
|
|
df9752 |
|
|
|
df9752 |
-/* Are all the paged results requests timed out? */
|
|
|
df9752 |
+/*
|
|
|
df9752 |
+ * This timedout is mainly for an end user leaves a commandline untouched
|
|
|
df9752 |
+ * for a long time. This should not affect a permanent connection which
|
|
|
df9752 |
+ * manages multiple simple paged results requests over the connection.
|
|
|
df9752 |
+ *
|
|
|
df9752 |
+ * [rule]
|
|
|
df9752 |
+ * If there is just one slot and it's timed out, we return it is timedout.
|
|
|
df9752 |
+ * If there are multiple slots, the connection may be a permanent one.
|
|
|
df9752 |
+ * Do not return timed out here. But let the next request take care the
|
|
|
df9752 |
+ * timedout slot(s).
|
|
|
df9752 |
+ */
|
|
|
df9752 |
int
|
|
|
df9752 |
pagedresults_is_timedout_nolock(Connection *conn)
|
|
|
df9752 |
{
|
|
|
df9752 |
- int i;
|
|
|
df9752 |
PagedResults *prp = NULL;
|
|
|
df9752 |
time_t ctime;
|
|
|
df9752 |
- int rc = 0;
|
|
|
df9752 |
|
|
|
df9752 |
LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_is_timedout\n");
|
|
|
df9752 |
|
|
|
df9752 |
- if (NULL == conn || 0 == conn->c_pagedresults.prl_count) {
|
|
|
df9752 |
- LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: -\n");
|
|
|
df9752 |
- return rc;
|
|
|
df9752 |
+ if (!conn || (0 == conn->c_pagedresults.prl_maxlen)) {
|
|
|
df9752 |
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: false\n");
|
|
|
df9752 |
+ return 0;
|
|
|
df9752 |
}
|
|
|
df9752 |
|
|
|
df9752 |
ctime = current_time();
|
|
|
df9752 |
- for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) {
|
|
|
df9752 |
- prp = conn->c_pagedresults.prl_list + i;
|
|
|
df9752 |
+ prp = conn->c_pagedresults.prl_list;
|
|
|
df9752 |
+ if (prp && (1 == conn->c_pagedresults.prl_maxlen)) {
|
|
|
df9752 |
if (prp->pr_current_be && (prp->pr_timelimit > 0)) {
|
|
|
df9752 |
- if (ctime < prp->pr_timelimit) {
|
|
|
df9752 |
- LDAPDebug0Args(LDAP_DEBUG_TRACE,
|
|
|
df9752 |
- "<-- pagedresults_is_timedout: 0\n");
|
|
|
df9752 |
- return 0; /* at least, one request is not timed out. */
|
|
|
df9752 |
- } else {
|
|
|
df9752 |
- rc = 1; /* possibly timed out */
|
|
|
df9752 |
+ if (ctime > prp->pr_timelimit) {
|
|
|
df9752 |
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: true\n");
|
|
|
df9752 |
+ return 1;
|
|
|
df9752 |
}
|
|
|
df9752 |
}
|
|
|
df9752 |
}
|
|
|
df9752 |
- LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: 1\n");
|
|
|
df9752 |
- return rc; /* all requests are timed out. */
|
|
|
df9752 |
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: false\n");
|
|
|
df9752 |
+ return 0;
|
|
|
df9752 |
}
|
|
|
df9752 |
|
|
|
df9752 |
/* reset all timeout */
|
|
|
df9752 |
--
|
|
|
df9752 |
1.9.3
|
|
|
df9752 |
|