andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From 42060f20853f9dbffb679a3ff4ec00c2732cab2e Mon Sep 17 00:00:00 2001
dc8c34
From: Mark Reynolds <mreynolds@redhat.com>
dc8c34
Date: Tue, 8 Apr 2014 14:12:32 -0400
dc8c34
Subject: [PATCH 195/225] Ticket 47767 - Nested tombstones become orphaned
dc8c34
 after purge
dc8c34
dc8c34
Bug Description:  If there are nested tombstone entries, the parents will
dc8c34
                  always be purged first, which leaves its child entries orphaned.
dc8c34
dc8c34
Fix Description:  When doing the tombstone purge, process the candidate list in
dc8c34
                  reverse order, which will remove the child entries before the
dc8c34
                  parent entries.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/47767
dc8c34
dc8c34
Reviewed by: nhosoi(Thanks!)
dc8c34
(cherry picked from commit 48e2a96cc3369db2b8d739889be273700ca9c23b)
dc8c34
---
dc8c34
 ldap/servers/plugins/replication/repl5_replica.c |  8 +++-
dc8c34
 ldap/servers/slapd/back-ldbm/idl_common.c        |  6 +++
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_delete.c       |  1 +
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_search.c       | 47 +++++++++++++++++++++++-
dc8c34
 ldap/servers/slapd/back-ldbm/proto-back-ldbm.h   |  1 +
dc8c34
 ldap/servers/slapd/operation.c                   |  1 +
dc8c34
 ldap/servers/slapd/slap.h                        |  1 +
dc8c34
 ldap/servers/slapd/slapi-plugin.h                |  8 ++--
dc8c34
 ldap/servers/slapd/slapi-private.h               | 44 ++++++++++++----------
dc8c34
 9 files changed, 89 insertions(+), 28 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
dc8c34
index 82c30c1..1cec805 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_replica.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_replica.c
dc8c34
@@ -2793,7 +2793,10 @@ process_reap_entry (Slapi_Entry *entry, void *cb_data)
dc8c34
 							"%s\n", slapi_entry_get_dn(entry));
dc8c34
 		}
dc8c34
 	}
dc8c34
-	(*num_entriesp)++;
dc8c34
+	if(!is_ruv_tombstone_entry(entry)){
dc8c34
+		/* Don't update the count for the database tombstone entry */
dc8c34
+		(*num_entriesp)++;
dc8c34
+	}
dc8c34
 
dc8c34
 	return 0;
dc8c34
 }
dc8c34
@@ -2878,7 +2881,8 @@ _replica_reap_tombstones(void *arg)
dc8c34
 		slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(replica->repl_root),
dc8c34
 									 LDAP_SCOPE_SUBTREE, "(&(objectclass=nstombstone)(nscpentrydn=*))",
dc8c34
 									 attrs, 0, ctrls, NULL,
dc8c34
-									 repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
dc8c34
+									 repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
dc8c34
+									 OP_FLAG_REVERSE_CANDIDATE_ORDER);
dc8c34
 
dc8c34
 		cb_data.rc = 0;
dc8c34
 		cb_data.num_entries = 0UL;
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/idl_common.c b/ldap/servers/slapd/back-ldbm/idl_common.c
dc8c34
index 584bba5..ee59ee2 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/idl_common.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/idl_common.c
dc8c34
@@ -494,3 +494,9 @@ ID idl_iterator_dereference_increment(idl_iterator *i, const IDList *idl)
dc8c34
 	return t;
dc8c34
 }
dc8c34
 
dc8c34
+ID idl_iterator_dereference_decrement(idl_iterator *i, const IDList *idl)
dc8c34
+{
dc8c34
+	idl_iterator_decrement(i);
dc8c34
+	return idl_iterator_dereference(*i,idl);
dc8c34
+
dc8c34
+}
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
dc8c34
index d1ad3ef..a4b8d8e 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
dc8c34
@@ -1228,5 +1228,6 @@ diskfull_return:
dc8c34
 	{
dc8c34
 		slapi_log_error (SLAPI_LOG_TRACE, "ldbm_back_delete", "leave conn=%" NSPRIu64 " op=%d\n", pb->pb_conn->c_connid, operation->o_opid);
dc8c34
 	}
dc8c34
+
dc8c34
 	return rc;
dc8c34
 }
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
index 552b65b..a097307 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
@@ -1343,6 +1343,7 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
dc8c34
     int                    pr_idx = -1;
dc8c34
     Slapi_Connection       *conn;
dc8c34
     Slapi_Operation        *op;
dc8c34
+    int                    reverse_list = 0;
dc8c34
 
dc8c34
     slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &basesdn );
dc8c34
     if (NULL == basesdn) {
dc8c34
@@ -1370,6 +1371,18 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
dc8c34
     slapi_pblock_get( pb, SLAPI_CONNECTION, &conn );
dc8c34
     slapi_pblock_get( pb, SLAPI_OPERATION, &op );
dc8c34
 
dc8c34
+    if((reverse_list = operation_is_flag_set(op, OP_FLAG_REVERSE_CANDIDATE_ORDER))){
dc8c34
+        /*
dc8c34
+         * Start at the end of the list and work our way forward.  Since a single
dc8c34
+         * search can enter this function multiple times, we need to keep track
dc8c34
+         * of our state, and only initialize sr_current once.
dc8c34
+         */
dc8c34
+        if(!op->o_reverse_search_state){
dc8c34
+            sr->sr_current = sr->sr_candidates->b_nids;
dc8c34
+            op->o_reverse_search_state = REV_STARTED;
dc8c34
+        }
dc8c34
+    }
dc8c34
+
dc8c34
     if ( !txn.back_txn_txn ) {
dc8c34
         dblayer_txn_init( li, &txn );
dc8c34
         slapi_pblock_set( pb, SLAPI_TXN, txn.back_txn_txn );
dc8c34
@@ -1469,8 +1482,32 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
dc8c34
             goto bail;
dc8c34
         }
dc8c34
             
dc8c34
-        /* get the entry */
dc8c34
-        id = idl_iterator_dereference_increment(&(sr->sr_current), sr->sr_candidates);
dc8c34
+        /*
dc8c34
+         * Get the entry ID
dc8c34
+         */
dc8c34
+        if(reverse_list){
dc8c34
+            /*
dc8c34
+             * This is probably a tombstone reaping, we need to process in the candidate
dc8c34
+             * list in reserve order, or else we can orphan tombstone entries by removing
dc8c34
+             * it's parent tombstone entry first.
dc8c34
+             */
dc8c34
+            id = idl_iterator_dereference_decrement(&(sr->sr_current), sr->sr_candidates);
dc8c34
+            if((sr->sr_current == 0) && op->o_reverse_search_state != LAST_REV_ENTRY){
dc8c34
+                /*
dc8c34
+                 * We hit the last entry and we need to process it, but the decrement
dc8c34
+                 * function will keep returning the last entry.  So we need to mark that
dc8c34
+                 * we have hit the last entry so we know to stop on the next pass.
dc8c34
+                 */
dc8c34
+                op->o_reverse_search_state = LAST_REV_ENTRY;
dc8c34
+            } else if(op->o_reverse_search_state == LAST_REV_ENTRY){
dc8c34
+                /* we're done */
dc8c34
+                id = NOID;
dc8c34
+            }
dc8c34
+        } else {
dc8c34
+            /* Process the candidate list in the normal order. */
dc8c34
+            id = idl_iterator_dereference_increment(&(sr->sr_current), sr->sr_candidates);
dc8c34
+        }
dc8c34
+
dc8c34
         if ( id == NOID )
dc8c34
         {
dc8c34
             /* No more entries */
dc8c34
@@ -1481,6 +1518,7 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
dc8c34
             }
dc8c34
             slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
dc8c34
             delete_search_result_set(pb, &sr);
dc8c34
+            op->o_reverse_search_state = 0;
dc8c34
             rc = 0;
dc8c34
             goto bail;
dc8c34
         }
dc8c34
@@ -1686,7 +1724,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
dc8c34
           }
dc8c34
         }
dc8c34
     }
dc8c34
+
dc8c34
 bail:
dc8c34
+    if(rc){
dc8c34
+        op->o_reverse_search_state = 0;
dc8c34
+    }
dc8c34
+
dc8c34
     return rc;
dc8c34
 }
dc8c34
 
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
index d7b88ed..ee30c45 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
@@ -266,6 +266,7 @@ idl_iterator idl_iterator_increment(idl_iterator *i);
dc8c34
 idl_iterator idl_iterator_decrement(idl_iterator *i);
dc8c34
 ID idl_iterator_dereference(idl_iterator i, const IDList *idl);
dc8c34
 ID idl_iterator_dereference_increment(idl_iterator *i, const IDList *idl);
dc8c34
+ID idl_iterator_dereference_decrement(idl_iterator *i, const IDList *idl);
dc8c34
 size_t idl_sizeof(IDList *idl);
dc8c34
 int idl_store_block(backend *be,DB *db,DBT *key,IDList *idl,DB_TXN *txn,struct attrinfo *a);
dc8c34
 void idl_set_tune(int val);
dc8c34
diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c
dc8c34
index 01ebfef..3a58381 100644
dc8c34
--- a/ldap/servers/slapd/operation.c
dc8c34
+++ b/ldap/servers/slapd/operation.c
dc8c34
@@ -200,6 +200,7 @@ operation_new(int flags)
dc8c34
 		o->o_connid = 0;
dc8c34
 		o->o_next = NULL;
dc8c34
 		o->o_flags= flags;
dc8c34
+		o->o_reverse_search_state = 0;
dc8c34
 		if ( config_get_accesslog_level() & LDAP_DEBUG_TIMING ) {
dc8c34
 			o->o_interval = PR_IntervalNow();
dc8c34
 		} else {
dc8c34
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
dc8c34
index 2465500..047c945 100644
dc8c34
--- a/ldap/servers/slapd/slap.h
dc8c34
+++ b/ldap/servers/slapd/slap.h
dc8c34
@@ -1348,6 +1348,7 @@ typedef struct op {
dc8c34
 	struct slapi_operation_parameters o_params;
dc8c34
 	struct slapi_operation_results o_results;
dc8c34
 	int o_pagedresults_sizelimit;
dc8c34
+	int o_reverse_search_state;
dc8c34
 } Operation;
dc8c34
 
dc8c34
 /*
dc8c34
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
dc8c34
index 304c5a8..80500a5 100644
dc8c34
--- a/ldap/servers/slapd/slapi-plugin.h
dc8c34
+++ b/ldap/servers/slapd/slapi-plugin.h
dc8c34
@@ -196,10 +196,10 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...)
dc8c34
                                                  Used for DN. */
dc8c34
 
dc8c34
 /* operation flags */
dc8c34
-#define SLAPI_OP_FLAG_INTERNAL		0x00020 /* An operation generated by the core server or a plugin. */
dc8c34
-#define SLAPI_OP_FLAG_NEVER_CHAIN	0x00800 /* Do not chain the operation */	
dc8c34
-#define SLAPI_OP_FLAG_NO_ACCESS_CHECK  	0x10000 /* Do not check for access control - bypass them */
dc8c34
-#define SLAPI_OP_FLAG_BYPASS_REFERRALS  0x40000 /* Useful for performing internal operations on read-only replica */
dc8c34
+#define SLAPI_OP_FLAG_INTERNAL		0x000020 /* An operation generated by the core server or a plugin. */
dc8c34
+#define SLAPI_OP_FLAG_NEVER_CHAIN	0x000800 /* Do not chain the operation */
dc8c34
+#define SLAPI_OP_FLAG_NO_ACCESS_CHECK	0x10000 /* Do not check for access control - bypass them */
dc8c34
+#define SLAPI_OP_FLAG_BYPASS_REFERRALS	0x40000 /* Useful for performing internal operations on read-only replica */
dc8c34
 
dc8c34
 #define SLAPI_OC_FLAG_REQUIRED	0x0001
dc8c34
 #define SLAPI_OC_FLAG_ALLOWED	0x0002
dc8c34
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
dc8c34
index 8c5541a..b9131a5 100644
dc8c34
--- a/ldap/servers/slapd/slapi-private.h
dc8c34
+++ b/ldap/servers/slapd/slapi-private.h
dc8c34
@@ -395,43 +395,47 @@ slapi_filter_to_string_internal( const struct slapi_filter *f, char *buf, size_t
dc8c34
 
dc8c34
 /* operation.c */
dc8c34
 
dc8c34
-#define OP_FLAG_PS                       0x00001
dc8c34
-#define OP_FLAG_PS_CHANGESONLY           0x00002
dc8c34
-#define OP_FLAG_GET_EFFECTIVE_RIGHTS     0x00004  
dc8c34
-#define OP_FLAG_REPLICATED               0x00008 /* A Replicated Operation */
dc8c34
-#define OP_FLAG_REPL_FIXUP               0x00010 /* A Fixup Operation, 
dc8c34
+#define OP_FLAG_PS                       0x000001
dc8c34
+#define OP_FLAG_PS_CHANGESONLY           0x000002
dc8c34
+#define OP_FLAG_GET_EFFECTIVE_RIGHTS     0x000004
dc8c34
+#define OP_FLAG_REPLICATED               0x000008 /* A Replicated Operation */
dc8c34
+#define OP_FLAG_REPL_FIXUP               0x000010 /* A Fixup Operation,
dc8c34
                                                   * generated as a consequence
dc8c34
                                                   * of a Replicated Operation.
dc8c34
                                                   */
dc8c34
-#define OP_FLAG_INTERNAL                 SLAPI_OP_FLAG_INTERNAL  /* 0x00020 */ 
dc8c34
-#define OP_FLAG_ACTION_LOG_ACCESS        0x00040
dc8c34
-#define OP_FLAG_ACTION_LOG_AUDIT         0x00080
dc8c34
-#define OP_FLAG_ACTION_SCHEMA_CHECK      0x00100
dc8c34
-#define OP_FLAG_ACTION_LOG_CHANGES       0x00200
dc8c34
-#define OP_FLAG_ACTION_INVOKE_FOR_REPLOP 0x00400
dc8c34
-#define OP_FLAG_NEVER_CHAIN              SLAPI_OP_FLAG_NEVER_CHAIN  /* 0x0800 */
dc8c34
-#define OP_FLAG_TOMBSTONE_ENTRY          0x01000
dc8c34
-#define OP_FLAG_RESURECT_ENTRY           0x02000
dc8c34
-#define OP_FLAG_LEGACY_REPLICATION_DN    0x04000 /* Operation done by legacy 
dc8c34
+#define OP_FLAG_INTERNAL                 SLAPI_OP_FLAG_INTERNAL  /* 0x000020 */
dc8c34
+#define OP_FLAG_ACTION_LOG_ACCESS        0x000040
dc8c34
+#define OP_FLAG_ACTION_LOG_AUDIT         0x000080
dc8c34
+#define OP_FLAG_ACTION_SCHEMA_CHECK      0x000100
dc8c34
+#define OP_FLAG_ACTION_LOG_CHANGES       0x000200
dc8c34
+#define OP_FLAG_ACTION_INVOKE_FOR_REPLOP 0x000400
dc8c34
+#define OP_FLAG_NEVER_CHAIN              SLAPI_OP_FLAG_NEVER_CHAIN  /* 0x000800 */
dc8c34
+#define OP_FLAG_TOMBSTONE_ENTRY          0x001000
dc8c34
+#define OP_FLAG_RESURECT_ENTRY           0x002000
dc8c34
+#define OP_FLAG_LEGACY_REPLICATION_DN    0x004000 /* Operation done by legacy
dc8c34
                                                   * replication DN
dc8c34
                                                   */
dc8c34
-#define OP_FLAG_ACTION_NOLOG             0x08000 /* Do not log the entry in 
dc8c34
+#define OP_FLAG_ACTION_NOLOG             0x008000 /* Do not log the entry in
dc8c34
                                                   * audit log or change log
dc8c34
                                                   */
dc8c34
-#define OP_FLAG_SKIP_MODIFIED_ATTRS      0x10000 /* Do not update the 
dc8c34
+#define OP_FLAG_SKIP_MODIFIED_ATTRS      0x010000 /* Do not update the
dc8c34
                                                   * modifiersname,
dc8c34
                                                   * modifiedtimestamp, etc.
dc8c34
                                                   * attributes
dc8c34
                                                   */
dc8c34
-#define OP_FLAG_REPL_RUV                 0x20000 /* Flag to tell to the backend
dc8c34
+#define OP_FLAG_REPL_RUV                 0x020000 /* Flag to tell to the backend
dc8c34
                                                   * that the entry to be added/
dc8c34
                                                   * modified is RUV. This info
dc8c34
                                                   * is used to skip VLV op.
dc8c34
                                                   * (see #329951)
dc8c34
                                                   */
dc8c34
-#define OP_FLAG_PAGED_RESULTS            0x40000 /* simple paged results */
dc8c34
-#define OP_FLAG_SERVER_SIDE_SORTING      0x80000 /* server side sorting  */
dc8c34
+#define OP_FLAG_PAGED_RESULTS            0x040000 /* simple paged results */
dc8c34
+#define OP_FLAG_SERVER_SIDE_SORTING      0x080000 /* server side sorting  */
dc8c34
+#define OP_FLAG_REVERSE_CANDIDATE_ORDER  0x100000 /* reverse the search candidate list */
dc8c34
 
dc8c34
+/* reverse search states */
dc8c34
+#define REV_STARTED 1
dc8c34
+#define LAST_REV_ENTRY 2
dc8c34
 
dc8c34
 CSN *operation_get_csn(Slapi_Operation *op);
dc8c34
 void operation_set_csn(Slapi_Operation *op,CSN *csn);
dc8c34
-- 
dc8c34
1.8.1.4
dc8c34