andykimpe / rpms / 389-ds-base

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