andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 4 months ago
Clone
Blob Blame History Raw
From 6ff0de2cd74424427058cff5a93275c918d32ae8 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 22 Dec 2016 14:38:27 -0500
Subject: [PATCH 422/425] Ticket 48964 - cleanallruv changelog purging removes
 wrong  rid

Bug Description:  A regression from the previous patch uses the local replica
                  object to locate the correct changelog file, but the rid to
                  be clean is not the same rid from the replica object.  So the
                  local replica object's rid is used accidentally to purge the
                  change log.

Fix Description:  Instead if passing the replica object to the changelog purging
                  code, create a new purge_data struct to hold all the neccessary
                  data to purge the correct changelog file and the cleaned rid.

https://fedorahosted.org/389/ticket/48964

Reviewed by: nhosoi(Thanks!)

(cherry picked from commit a38d76d27970b5b6facf2ffbd1bce9d6979e6297)
(cherry picked from commit 4053587d5dfb9c4b4e5cd966cabb1adc624511d6)
(cherry picked from commit 41c0a49148725667fbced82b2c2be5b6ec37a4db)
---
 ldap/servers/plugins/replication/cl5_api.c         | 54 +++++++++++++---------
 ldap/servers/plugins/replication/cl5_api.h         |  2 +-
 ldap/servers/plugins/replication/repl5.h           |  8 ++++
 .../plugins/replication/repl5_replica_config.c     | 12 ++++-
 4 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index d91574f..3c46ed3 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -3491,12 +3491,12 @@ static void _cl5DoTrimming ()
  * changelog for the backend that is being cleaned, and purge all the records
  * with the cleaned rid.
  */
-static void _cl5DoPurging (Replica *replica)
+static void _cl5DoPurging (cleanruv_purge_data *purge_data)
 {
-	ReplicaId rid = replica_get_rid(replica);
-	const Slapi_DN *sdn = replica_get_root(replica);
-	const char *replName = replica_get_name(replica);
-	char *replGen = replica_get_generation(replica);
+	ReplicaId rid = purge_data->cleaned_rid;
+	const Slapi_DN *suffix_sdn = purge_data->suffix_sdn;
+	const char *replName = purge_data->replName;
+	char *replGen = purge_data->replGen;
 	char *fileName;
 	Object *obj;
 
@@ -3508,18 +3508,15 @@ static void _cl5DoPurging (Replica *replica)
 		_cl5PurgeRID (obj, rid);
 		object_release (obj);
 		slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl,
-			"Purged rid (%d) from suffix (%s)\n",
-			rid, slapi_sdn_get_dn(sdn));
+			"_cl5DoPurging - Purged rid (%d) from suffix (%s)\n",
+			rid, slapi_sdn_get_dn(suffix_sdn));
 	} else {
 		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
-			"Purge rid (%d) failed to find changelog file (%s) for suffix (%s)\n",
-			rid, fileName, slapi_sdn_get_dn(sdn));
+			"_cl5DoPurging - Purge rid (%d) failed to find changelog file (%s) for suffix (%s)\n",
+			rid, fileName, slapi_sdn_get_dn(suffix_sdn));
 	}
 	PR_Unlock (s_cl5Desc.dbTrim.lock);
 
-	slapi_ch_free_string(&replGen);
-	slapi_ch_free_string(&fileName);
-
 	return;
 }
 
@@ -6888,19 +6885,27 @@ cl5CleanRUV(ReplicaId rid){
     slapi_rwlock_unlock (s_cl5Desc.stLock);
 }
 
+static void free_purge_data(cleanruv_purge_data *purge_data)
+{
+    slapi_ch_free_string(&purge_data->replGen);
+    slapi_ch_free_string(&purge_data->replName);
+    slapi_ch_free((void **)&purge_data);
+}
+
 /*
  * Create a thread to purge a changelog of cleaned RIDs
  */
-void trigger_cl_purging(Replica *replica){
+void trigger_cl_purging(cleanruv_purge_data *purge_data){
     PRThread *trim_tid = NULL;
 
     trim_tid = PR_CreateThread(PR_USER_THREAD, (VFP)(void*)trigger_cl_purging_thread,
-                   (void *)replica, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+                   (void *)purge_data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
                    PR_UNJOINABLE_THREAD, DEFAULT_THREAD_STACKSIZE);
     if (NULL == trim_tid){
         slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
-            "trigger_cl_purging: failed to create trimming "
+            "trigger_cl_purging: failed to create cl trimming "
             "thread; NSPR error - %d\n", PR_GetError ());
+        free_purge_data(purge_data);
     } else {
         /* need a little time for the thread to get started */
         DS_Sleep(PR_SecondsToInterval(1));
@@ -6912,13 +6917,12 @@ void trigger_cl_purging(Replica *replica){
  */
 void
 trigger_cl_purging_thread(void *arg){
-    Replica *replica = (Replica *)arg;
+    cleanruv_purge_data *purge_data = (cleanruv_purge_data *)arg;
 
     /* Make sure we have a change log, and we aren't closing it */
-    if (replica == NULL ||
-        s_cl5Desc.dbState == CL5_STATE_CLOSED ||
+    if (s_cl5Desc.dbState == CL5_STATE_CLOSED ||
         s_cl5Desc.dbState == CL5_STATE_CLOSING) {
-        return;
+        goto free_and_return;
     }
 
     /* Bump the changelog thread count */
@@ -6926,13 +6930,17 @@ trigger_cl_purging_thread(void *arg){
         slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
             "trigger_cl_purging: Abort - failed to increment thread count "
             "NSPR error - %d\n", PR_GetError ());
-        return;
+        goto free_and_return;
     }
 
     /* Purge the changelog */
-    _cl5DoPurging(replica);
+    _cl5DoPurging(purge_data);
     _cl5RemoveThread();
+
     slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl,
-        "trigger_cl_purging: purged changelog for (%s) rid (%d)\n",
-        slapi_sdn_get_dn(replica_get_root(replica)), replica_get_rid(replica));
+        "trigger_cl_purging_thread - purged changelog for (%s) rid (%d)\n",
+        slapi_sdn_get_dn(purge_data->suffix_sdn), purge_data->cleaned_rid);
+
+free_and_return:
+    free_purge_data(purge_data);
 }
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index 83683f5..c690d89 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -493,6 +493,6 @@ int cl5WriteRUV();
 int cl5DeleteRUV();
 void cl5CleanRUV(ReplicaId rid);
 void cl5NotifyCleanup(int rid);
-void trigger_cl_purging(Replica *replica);
+void trigger_cl_purging(cleanruv_purge_data *purge_data);
 
 #endif
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index a521389..0db632e 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -676,6 +676,14 @@ typedef struct _cleanruv_data
 	char *force;
 } cleanruv_data;
 
+typedef struct _cleanruv_purge_data
+{
+	int cleaned_rid;
+	const Slapi_DN *suffix_sdn;
+	char *replName;
+	char *replGen;
+} cleanruv_purge_data;
+
 /* replutil.c */
 LDAPControl* create_managedsait_control ();
 LDAPControl* create_backend_control(Slapi_DN *sdn);
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 010e517..c6a9ffa 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1211,6 +1211,7 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
 	Object *RUVObj;
 	RUV *local_ruv = NULL;
 	Replica *replica = (Replica*)object_get_data (r);
+	cleanruv_purge_data *purge_data;
 	int rc = 0;
 	PR_ASSERT (replica);
 
@@ -1242,9 +1243,16 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not
 	cl5CleanRUV(rid);
 
 	/*
-	 * Now purge the changelog
+	 * Now purge the changelog.  The purging thread will free the purge_data
 	 */
-	trigger_cl_purging(replica);
+	if (replica){
+		purge_data = (cleanruv_purge_data*)slapi_ch_calloc(1, sizeof(cleanruv_purge_data));
+		purge_data->cleaned_rid = rid;
+		purge_data->suffix_sdn = replica_get_root(replica);
+		purge_data->replName = (char *)replica_get_name(replica);
+		purge_data->replGen = replica_get_generation(replica);
+		trigger_cl_purging(purge_data);
+	}
 
 	if (rc != RUV_SUCCESS){
 		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_task: task failed(%d)\n",rc);
-- 
2.9.3