zrhoffman / rpms / 389-ds-base

Forked from rpms/389-ds-base 3 years ago
Clone

Blame SOURCES/0074-Ticket-48192-Individual-abandoned-simple-paged-resul.patch

df9752
From 22b0f8f0de1ee208a8c06c171bc2069da0adcc87 Mon Sep 17 00:00:00 2001
df9752
From: Noriko Hosoi <nhosoi@redhat.com>
df9752
Date: Mon, 6 Jul 2015 14:06:11 -0700
df9752
Subject: [PATCH] Ticket #48192 - Individual abandoned simple paged results
df9752
 request has no chance to be cleaned up
df9752
df9752
Description: There was a small window that the search on the next page
df9752
after the previous page abandoned referred the cleaned up simple paged
df9752
object.
df9752
df9752
This patch introduces a pagedresults_is_abandoned helper function to
df9752
check the simple paged results was abandoned or not with some improvements
df9752
based upon the comments by rmeggins@redhat.com (Thank you!!):
df9752
1) adding locking when getting a simplepaged object in pagedresults_is_
df9752
   abandoned_or_notavailable as well as in pagedresults_{un}lock.
df9752
2) sending "Simple Paged Results Search abandoned" if the previous page
df9752
   with the same cookie in the same connection was abandoned.
df9752
df9752
https://fedorahosted.org/389/ticket/48192
df9752
df9752
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
df9752
df9752
(cherry picked from commit e4d83c91fc88fcf9e6c823c608c629ac10e362f8)
df9752
(cherry picked from commit b513a502250f93cfb43df000c2140b27c4ef0d39)
df9752
(cherry picked from commit 7b17c488de280f29264920b4e53dce862ed5b7e4)
df9752
---
df9752
 ldap/servers/slapd/opshared.c     | 22 ++++++++++++++++------
df9752
 ldap/servers/slapd/pagedresults.c | 24 +++++++++++++++++++++++-
df9752
 ldap/servers/slapd/proto-slap.h   |  1 +
df9752
 3 files changed, 40 insertions(+), 7 deletions(-)
df9752
df9752
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
df9752
index 4be5366..1bad7ef 100644
df9752
--- a/ldap/servers/slapd/opshared.c
df9752
+++ b/ldap/servers/slapd/opshared.c
df9752
@@ -709,12 +709,20 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
df9752
        */
df9752
       pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx);
df9752
       if (pr_search_result) {
df9752
-        slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
df9752
-        rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
df9752
+        if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) {
df9752
+          pagedresults_unlock(pb->pb_conn, pr_idx);
df9752
+          /* Previous operation was abandoned and the simplepaged object is not in use. */
df9752
+          send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
df9752
+          rc = LDAP_SUCCESS;
df9752
+          goto free_and_return;
df9752
+        } else {
df9752
+          slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
df9752
+          rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
df9752
 
df9752
-        /* search result could be reset in the backend/dse */
df9752
-        slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
df9752
-        pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx);
df9752
+          /* search result could be reset in the backend/dse */
df9752
+          slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
df9752
+          pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx);
df9752
+        }
df9752
       } else {
df9752
         pr_stat = PAGEDRESULTS_SEARCH_END;
df9752
       }
df9752
@@ -744,7 +752,9 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
df9752
       if (PAGEDRESULTS_SEARCH_END == pr_stat) {
df9752
         pagedresults_lock(pb->pb_conn, pr_idx);
df9752
         slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
df9752
-        pagedresults_free_one(pb->pb_conn, operation, pr_idx);
df9752
+        if (!pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) {
df9752
+          pagedresults_free_one(pb->pb_conn, operation, pr_idx);
df9752
+        }
df9752
         pagedresults_unlock(pb->pb_conn, pr_idx);
df9752
         if (next_be) {
df9752
           /* no more entries, but at least another backend */
df9752
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
df9752
index a7fe2cd..010e5c1 100644
df9752
--- a/ldap/servers/slapd/pagedresults.c
df9752
+++ b/ldap/servers/slapd/pagedresults.c
df9752
@@ -890,6 +890,8 @@ pagedresults_reset_processing(Connection *conn, int index)
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
+ * must be called within conn->c_mutex 
df9752
  */
df9752
 int
df9752
 pagedresults_is_timedout_nolock(Connection *conn)
df9752
@@ -918,7 +920,10 @@ pagedresults_is_timedout_nolock(Connection *conn)
df9752
     return 0;
df9752
 }
df9752
 
df9752
-/* reset all timeout */
df9752
+/* 
df9752
+ * reset all timeout
df9752
+ * must be called within conn->c_mutex 
df9752
+ */
df9752
 int
df9752
 pagedresults_reset_timedout_nolock(Connection *conn)
df9752
 {
df9752
@@ -981,7 +986,9 @@ pagedresults_lock( Connection *conn, int index )
df9752
     if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
df9752
         return;
df9752
     }
df9752
+    PR_Lock(conn->c_mutex);
df9752
     prp = conn->c_pagedresults.prl_list + index;
df9752
+    PR_Unlock(conn->c_mutex);
df9752
     if (prp->pr_mutex) {
df9752
         PR_Lock(prp->pr_mutex);
df9752
     }
df9752
@@ -995,9 +1002,24 @@ pagedresults_unlock( Connection *conn, int index )
df9752
     if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
df9752
         return;
df9752
     }
df9752
+    PR_Lock(conn->c_mutex);
df9752
     prp = conn->c_pagedresults.prl_list + index;
df9752
+    PR_Unlock(conn->c_mutex);
df9752
     if (prp->pr_mutex) {
df9752
         PR_Unlock(prp->pr_mutex);
df9752
     }
df9752
     return;
df9752
 }
df9752
+
df9752
+int
df9752
+pagedresults_is_abandoned_or_notavailable( Connection *conn, int index )
df9752
+{
df9752
+    PagedResults *prp;
df9752
+    if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
df9752
+        return 1; /* not abandoned, but do not want to proceed paged results op. */
df9752
+    }
df9752
+    PR_Lock(conn->c_mutex);
df9752
+    prp = conn->c_pagedresults.prl_list + index;
df9752
+    PR_Unlock(conn->c_mutex);
df9752
+    return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
df9752
+}
df9752
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
df9752
index c5c412d..4c0d1ce 100644
df9752
--- a/ldap/servers/slapd/proto-slap.h
df9752
+++ b/ldap/servers/slapd/proto-slap.h
df9752
@@ -1515,6 +1515,7 @@ int pagedresults_cleanup_all(Connection *conn, int needlock);
df9752
 void op_set_pagedresults(Operation *op);
df9752
 void pagedresults_lock(Connection *conn, int index);
df9752
 void pagedresults_unlock(Connection *conn, int index);
df9752
+int pagedresults_is_abandoned_or_notavailable(Connection *conn, int index);
df9752
 
df9752
 /*
df9752
  * sort.c
df9752
-- 
df9752
1.9.3
df9752