andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From 0ae7a17ae868530ae461ea70ffcead0a8a8d1880 Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@totoro.usersys.redhat.com>
dc8c34
Date: Mon, 29 Oct 2012 10:55:05 -0700
dc8c34
Subject: [PATCH 10/10] Trac Ticket #498 - Cannot abaondon simple paged result search
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/498
dc8c34
dc8c34
Bug Description: The enhancement "Ticket #260 - 389 DS does not
dc8c34
support multiple paging controls on a single connection (commit
dc8c34
add880accaa28de8304da1c2c2f58fe8af002ebb)" broke the ability to
dc8c34
abandon the on-going simple paged result search.
dc8c34
dc8c34
1) The abandon request expects the operation exist. When sending
dc8c34
an abort request, the search operation could have already finished
dc8c34
and the operation object has been released.
dc8c34
dc8c34
2) Plus, request page size is 0, it should be interpreted as abandoned.
dc8c34
dc8c34
Fix Description:
dc8c34
1) In do_abandon, this patch eliminates to check if the operation
dc8c34
is a simplepaged results oriented or not, since the operation object
dc8c34
is often already released.  Instead, it directly checks the internal
dc8c34
paged results info in the connection object.
dc8c34
dc8c34
To make sure the abandoned search won't go further, a flag value
dc8c34
CONN_FLAG_PAGEDRESULTS_ABANDONED is introduced.  If it is set in
dc8c34
the pagedresults structure in the connection object, it skips any
dc8c34
further process of the search.
dc8c34
dc8c34
2) This patch is adding a check if the given page size is 0 in the
dc8c34
simple-paged-results control or not.  If it is 0, treat is as an
dc8c34
abandoned operation.
dc8c34
(cherry picked from commit 47c0d96ac28c0b1cc15e7bbb77648551c309ccf5)
dc8c34
(cherry picked from commit 973886082b1c695a55d503f96b2e74188cbfded6)
dc8c34
---
dc8c34
 ldap/servers/slapd/abandon.c      |   10 +++-----
dc8c34
 ldap/servers/slapd/opshared.c     |   17 ++++++++++++--
dc8c34
 ldap/servers/slapd/pagedresults.c |   41 +++++++++++++++++++++++++-----------
dc8c34
 ldap/servers/slapd/slap.h         |   15 +++++++------
dc8c34
 4 files changed, 54 insertions(+), 29 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c
dc8c34
index 094ae95..9639701 100644
dc8c34
--- a/ldap/servers/slapd/abandon.c
dc8c34
+++ b/ldap/servers/slapd/abandon.c
dc8c34
@@ -152,12 +152,10 @@ do_abandon( Slapi_PBlock *pb )
dc8c34
 		    0 );
dc8c34
 	}
dc8c34
 
dc8c34
-	if ( op_is_pagedresults(o) ) {
dc8c34
-		if ( 0 == pagedresults_free_one_msgid_nolock(pb->pb_conn, id) ) {
dc8c34
-			slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 
dc8c34
-			                  " op=%d ABANDON targetop=Simple Paged Results\n",
dc8c34
-			                  pb->pb_conn->c_connid, pb->pb_op->o_opid );
dc8c34
-		}
dc8c34
+	if ( 0 == pagedresults_free_one_msgid_nolock(pb->pb_conn, id) ) {
dc8c34
+		slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 
dc8c34
+		                  " op=%d ABANDON targetop=Simple Paged Results\n",
dc8c34
+		                  pb->pb_conn->c_connid, pb->pb_op->o_opid );
dc8c34
 	} else if ( NULL == o ) {
dc8c34
 		slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ABANDON"
dc8c34
 			" targetop=NOTFOUND msgid=%d\n",
dc8c34
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
dc8c34
index 22a3822..2701250 100644
dc8c34
--- a/ldap/servers/slapd/opshared.c
dc8c34
+++ b/ldap/servers/slapd/opshared.c
dc8c34
@@ -197,8 +197,8 @@ void modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
dc8c34
         }
dc8c34
     }
dc8c34
 
dc8c34
-   	slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
dc8c34
-   						   "modifiersname", bvals);
dc8c34
+    slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
dc8c34
+                           "modifiersname", bvals);
dc8c34
 
dc8c34
     /* fill in modifytimestamp */
dc8c34
     curtime = current_time();
dc8c34
@@ -461,7 +461,8 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
dc8c34
                                                 &pagesize, &pr_idx);
dc8c34
           /* Let's set pr_idx even if it fails; in case, pr_idx == -1. */
dc8c34
           slapi_pblock_set(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
dc8c34
-          if (LDAP_SUCCESS == rc) {
dc8c34
+          if ((LDAP_SUCCESS == rc) ||
dc8c34
+              (LDAP_CANCELLED == rc) || (0 == pagesize)) {
dc8c34
               unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED;
dc8c34
               if (pagedresults_check_or_set_processing(pb->pb_conn, pr_idx)) {
dc8c34
                   send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM,
dc8c34
@@ -483,6 +484,16 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
dc8c34
                   opnote |= SLAPI_OP_NOTE_UNINDEXED;
dc8c34
               }
dc8c34
               slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
dc8c34
+              if ((LDAP_CANCELLED == rc) || (0 == pagesize)) {
dc8c34
+                  /* paged-results-request was abandoned */
dc8c34
+                  pagedresults_set_response_control(pb, 0, estimate, 
dc8c34
+                                                    curr_search_count, pr_idx);
dc8c34
+                  send_ldap_result(pb, 0, NULL,
dc8c34
+                                   "Simple Paged Results Search abandoned",
dc8c34
+                                   0, NULL);
dc8c34
+                  rc = LDAP_SUCCESS;
dc8c34
+                  goto free_and_return;
dc8c34
+              }
dc8c34
           } else {
dc8c34
               /* parse paged-results-control failed */
dc8c34
               if (iscritical) { /* return an error since it's critical */
dc8c34
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
dc8c34
index d445c06..9b294eb 100644
dc8c34
--- a/ldap/servers/slapd/pagedresults.c
dc8c34
+++ b/ldap/servers/slapd/pagedresults.c
dc8c34
@@ -143,8 +143,13 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
dc8c34
     slapi_ch_free((void **)&cookie.bv_val);
dc8c34
 
dc8c34
     if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) {
dc8c34
-        /* Need to keep the latest msgid to prepare for the abandon. */
dc8c34
-        conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid;
dc8c34
+        if (conn->c_pagedresults.prl_list[*index].pr_flags &
dc8c34
+            CONN_FLAG_PAGEDRESULTS_ABANDONED) {
dc8c34
+            rc = LDAP_CANCELLED;
dc8c34
+        } else {
dc8c34
+            /* Need to keep the latest msgid to prepare for the abandon. */
dc8c34
+            conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid;
dc8c34
+        }
dc8c34
     } else {
dc8c34
         rc = LDAP_PROTOCOL_ERROR;
dc8c34
         LDAPDebug1Arg(LDAP_DEBUG_ANY,
dc8c34
@@ -251,8 +256,13 @@ pagedresults_free_one( Connection *conn, int index )
dc8c34
                            "conn=%d paged requests list count is %d\n",
dc8c34
                            conn->c_connid, conn->c_pagedresults.prl_count);
dc8c34
         } else if (index < conn->c_pagedresults.prl_maxlen) {
dc8c34
-            memset(&conn->c_pagedresults.prl_list[index],
dc8c34
-                   '\0', sizeof(PagedResults));
dc8c34
+            PagedResults *prp = conn->c_pagedresults.prl_list + index;
dc8c34
+            if (prp && prp->pr_current_be &&
dc8c34
+                prp->pr_current_be->be_search_results_release &&
dc8c34
+                prp->pr_search_result_set) {
dc8c34
+                prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
dc8c34
+            }
dc8c34
+            memset(prp, '\0', sizeof(PagedResults));
dc8c34
             conn->c_pagedresults.prl_count--;
dc8c34
             rc = 0;
dc8c34
         }
dc8c34
@@ -263,34 +273,39 @@ pagedresults_free_one( Connection *conn, int index )
dc8c34
     return rc;
dc8c34
 }
dc8c34
 
dc8c34
+/* Used for abandoning */
dc8c34
 int 
dc8c34
 pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid )
dc8c34
 {
dc8c34
     int rc = -1;
dc8c34
     int i;
dc8c34
 
dc8c34
-    LDAPDebug1Arg(LDAP_DEBUG_TRACE,
dc8c34
-                  "--> pagedresults_free_one: msgid=%d\n", msgid);
dc8c34
     if (conn && (msgid > -1)) {
dc8c34
         if (conn->c_pagedresults.prl_count <= 0) {
dc8c34
-            LDAPDebug2Args(LDAP_DEBUG_TRACE,
dc8c34
-                           "pagedresults_free_one_msgid_nolock: "
dc8c34
-                           "conn=%d paged requests list count is %d\n",
dc8c34
-                           conn->c_connid, conn->c_pagedresults.prl_count);
dc8c34
+            ; /* Not a paged result. */
dc8c34
         } else {
dc8c34
+            LDAPDebug1Arg(LDAP_DEBUG_TRACE,
dc8c34
+                          "--> pagedresults_free_one: msgid=%d\n", msgid);
dc8c34
             for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) {
dc8c34
                 if (conn->c_pagedresults.prl_list[i].pr_msgid == msgid) {
dc8c34
-                    memset(&conn->c_pagedresults.prl_list[i],
dc8c34
-                           '\0', sizeof(PagedResults));
dc8c34
+                    PagedResults *prp = conn->c_pagedresults.prl_list + i;
dc8c34
+                    if (prp && prp->pr_current_be &&
dc8c34
+                        prp->pr_current_be->be_search_results_release &&
dc8c34
+                        prp->pr_search_result_set) {
dc8c34
+                        prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
dc8c34
+                    }
dc8c34
+                    prp->pr_flags |= CONN_FLAG_PAGEDRESULTS_ABANDONED;
dc8c34
+                    prp->pr_flags &= ~CONN_FLAG_PAGEDRESULTS_PROCESSING;
dc8c34
                     conn->c_pagedresults.prl_count--;
dc8c34
                     rc = 0;
dc8c34
                     break;
dc8c34
                 }
dc8c34
             }
dc8c34
+            LDAPDebug1Arg(LDAP_DEBUG_TRACE,
dc8c34
+                          "<-- pagedresults_free_one: %d\n", rc);
dc8c34
         }
dc8c34
     }
dc8c34
 
dc8c34
-    LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_free_one: %d\n", rc);
dc8c34
     return rc;
dc8c34
 }
dc8c34
 
dc8c34
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
dc8c34
index d0f2b33..e3cbc72 100644
dc8c34
--- a/ldap/servers/slapd/slap.h
dc8c34
+++ b/ldap/servers/slapd/slap.h
dc8c34
@@ -1461,16 +1461,17 @@ typedef struct conn {
dc8c34
                                      * successfully completed.
dc8c34
                                      */
dc8c34
 
dc8c34
-#define CONN_FLAG_PAGEDRESULTS_WITH_SORT 64 /* paged results control is
dc8c34
-                                             * sent with server side sorting
dc8c34
-                                             */
dc8c34
+#define CONN_FLAG_PAGEDRESULTS_WITH_SORT   64/* paged results control is
dc8c34
+                                              * sent with server side sorting
dc8c34
+                                              */
dc8c34
 
dc8c34
-#define CONN_FLAG_PAGEDRESULTS_UNINDEXED 128 /* If the search is unindexed,
dc8c34
+#define CONN_FLAG_PAGEDRESULTS_UNINDEXED  128/* If the search is unindexed,
dc8c34
                                               * store the info in c_flags
dc8c34
                                               */
dc8c34
-#define CONN_FLAG_PAGEDRESULTS_PROCESSING 256 /* there is an operation
dc8c34
-					       * processing a pagedresults search
dc8c34
-					       */
dc8c34
+#define CONN_FLAG_PAGEDRESULTS_PROCESSING 256/* there is an operation
dc8c34
+                                              * processing a pagedresults search
dc8c34
+                                              */
dc8c34
+#define CONN_FLAG_PAGEDRESULTS_ABANDONED  512/* pagedresults abandoned */
dc8c34
 #define CONN_GET_SORT_RESULT_CODE (-1)
dc8c34
 
dc8c34
 #define START_TLS_OID    "1.3.6.1.4.1.1466.20037"
dc8c34
-- 
dc8c34
1.7.1
dc8c34