andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 4 months ago
Clone

Blame 0037-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch

dc8c34
From caa4c40e88032c97d8c928debd5d1b34078d60a3 Mon Sep 17 00:00:00 2001
dc8c34
From: Mark Reynolds <mreynolds@redhat.com>
dc8c34
Date: Tue, 19 Mar 2013 15:17:51 -0400
dc8c34
Subject: [PATCH 37/42] Ticket 623 - cleanAllRUV task fails to cleanup config
dc8c34
 upon completion
dc8c34
dc8c34
Bug Description:  Since multiple tasks can  be run at once.  When a task
dc8c34
                  completes we need to remove a attribute from the replication
dc8c34
                  configuration.  We were manually building the attribute
dc8c34
                  value, and under certain circumstances this would not work
dc8c34
                  correctly.  This would leave the attribute in the replication
dc8c34
                  config, and after a restart the task would fire off again.
dc8c34
dc8c34
Fix Description:  Do not manually build the attribute value, but instead search
dc8c34
                  cn=config and grab the exact value we need to delete.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/623
dc8c34
dc8c34
Reviewed by: nhosoi(Thanks!)
dc8c34
(cherry picked from commit fa7972a5f01be7cedcd65c4c19af9602d2f7848f)
dc8c34
---
dc8c34
 .../plugins/replication/repl5_replica_config.c     | 106 +++++++++++++++------
dc8c34
 1 file changed, 75 insertions(+), 31 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
dc8c34
index e234c15..8710c04 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
dc8c34
@@ -2351,57 +2351,100 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
dc8c34
 static void
dc8c34
 delete_cleaned_rid_config(cleanruv_data *clean_data)
dc8c34
 {
dc8c34
-    Slapi_PBlock *pb;
dc8c34
+    Slapi_PBlock *pb = slapi_pblock_new();
dc8c34
+    Slapi_Entry **entries = NULL;
dc8c34
     LDAPMod *mods[2];
dc8c34
     LDAPMod mod;
dc8c34
     struct berval *vals[2];
dc8c34
     struct berval val;
dc8c34
     char data[CSN_STRSIZE + 15];
dc8c34
     char *csnstr = NULL;
dc8c34
+    char *iter = NULL;
dc8c34
     char *dn;
dc8c34
-    int rc;
dc8c34
+    int found = 0, i;
dc8c34
+    int rc, ret, rid;
dc8c34
 
dc8c34
     /*
dc8c34
-     *  Prepare the mods for the config entry
dc8c34
+     *  If there is no maxcsn, set the proper csnstr
dc8c34
      */
dc8c34
     csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr);
dc8c34
-    val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", (int)clean_data->rid, csnstr, clean_data->force);
dc8c34
+    if(csnstr == NULL || csn_get_replicaid(clean_data->maxcsn) == 0){
dc8c34
+        csnstr = slapi_ch_strdup("00000000000000000000");
dc8c34
+    }
dc8c34
+    /*
dc8c34
+     *  Search the config for the exact attribute value to delete
dc8c34
+     */
dc8c34
     dn = replica_get_dn(clean_data->replica);
dc8c34
-    pb = slapi_pblock_new();
dc8c34
+    slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_SUBTREE, "nsds5ReplicaCleanRUV=*", NULL, 0, NULL, NULL,
dc8c34
+        (void *)plugin_get_default_component_id(), 0);
dc8c34
+    slapi_search_internal_pb(pb);
dc8c34
+    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret;;
dc8c34
+    if (ret != LDAP_SUCCESS){
dc8c34
+        /*
dc8c34
+         * Search failed, manually build the attr value
dc8c34
+         */
dc8c34
+        val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
dc8c34
+            (int)clean_data->rid, csnstr, clean_data->force);
dc8c34
+        slapi_pblock_destroy(pb);
dc8c34
+    } else {
dc8c34
+        slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
dc8c34
+        if (entries == NULL || entries[0] == NULL){
dc8c34
+            /*
dc8c34
+             *  Entry not found, manually build the attr value
dc8c34
+             */
dc8c34
+            val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
dc8c34
+                (int)clean_data->rid, csnstr, clean_data->force);
dc8c34
+        } else {
dc8c34
+            char **attr_val = slapi_entry_attr_get_charray(entries[0], "nsds5ReplicaCleanRUV");
dc8c34
+
dc8c34
+            for (i = 0; attr_val && attr_val[i] && !found; i++){
dc8c34
+                /* make a copy to retain the full value after toking */
dc8c34
+                char *aval = slapi_ch_strdup(attr_val[i]);
dc8c34
+
dc8c34
+                rid = atoi(ldap_utf8strtok_r(attr_val[i], ":", &iter));
dc8c34
+                if(rid == clean_data->rid){
dc8c34
+                    /* found it */
dc8c34
+                    found = 1;
dc8c34
+                    val.bv_len = PR_snprintf(data, sizeof(data), "%s", aval);
dc8c34
+                }
dc8c34
+                slapi_ch_free_string(&aval);
dc8c34
+            }
dc8c34
+            if(!found){
dc8c34
+                /*
dc8c34
+                 *  No match, manually build the attr value
dc8c34
+                 */
dc8c34
+                val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
dc8c34
+                    (int)clean_data->rid, csnstr, clean_data->force);
dc8c34
+            }
dc8c34
+            slapi_ch_array_free(attr_val);
dc8c34
+        }
dc8c34
+        slapi_free_search_results_internal(pb);
dc8c34
+        slapi_pblock_destroy(pb);
dc8c34
+    }
dc8c34
+
dc8c34
+    /*
dc8c34
+     *  Now delete the attribute
dc8c34
+     */
dc8c34
     mod.mod_op  = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
dc8c34
-    mod.mod_type = (char *)type_replicaAbortCleanRUV;
dc8c34
     mod.mod_type = (char *)type_replicaCleanRUV;
dc8c34
     mod.mod_bvalues = vals;
dc8c34
     vals [0] = &val;
dc8c34
     vals [1] = NULL;
dc8c34
     val.bv_val = data;
dc8c34
-
dc8c34
     mods[0] = &mod;
dc8c34
     mods[1] = NULL;
dc8c34
+    pb = slapi_pblock_new();
dc8c34
     slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
dc8c34
     slapi_modify_internal_pb (pb);
dc8c34
     slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
dc8c34
-    if (rc != LDAP_SUCCESS){
dc8c34
-        /*
dc8c34
-         *  When aborting a task, we don't know if the "force" option was used.
dc8c34
-         *  So we assume it is set to "no", but if this op fails, we'll try "yes"
dc8c34
-         */
dc8c34
-        slapi_pblock_destroy (pb);
dc8c34
-        pb = slapi_pblock_new();
dc8c34
-        memset(data,'0',sizeof(data));
dc8c34
-        val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:yes", (int)clean_data->rid, csnstr);
dc8c34
-        slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
dc8c34
-        slapi_modify_internal_pb (pb);
dc8c34
-        slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
dc8c34
-        if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
dc8c34
-            slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config "
dc8c34
-                "(%d), rid (%d)\n", rc, clean_data->rid);
dc8c34
-        }
dc8c34
-     }
dc8c34
-     slapi_pblock_destroy (pb);
dc8c34
-     slapi_ch_free_string(&dn;;
dc8c34
-     slapi_ch_free_string(&csnstr);
dc8c34
- }
dc8c34
+    if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
dc8c34
+        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config "
dc8c34
+            "(%d), rid (%d)\n", rc, clean_data->rid);
dc8c34
+    }
dc8c34
+    slapi_pblock_destroy(pb);
dc8c34
+    slapi_ch_free_string(&dn;;
dc8c34
+    slapi_ch_free_string(&csnstr);
dc8c34
+}
dc8c34
 
dc8c34
 /*
dc8c34
  *  Remove the rid from our list, and the config
dc8c34
@@ -2762,8 +2805,8 @@ replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int che
dc8c34
                     /* extop was accepted */
dc8c34
                     rc = 0;
dc8c34
                 } else {
dc8c34
-                    cleanruv_log(clean_data->task, CLEANALLRUV_ID,"Replica %s does not support the CLEANALLRUV task.  Sending replica CLEANRUV task...",
dc8c34
-                        slapi_sdn_get_dn(agmt_get_dn_byref(ra)));
dc8c34
+                    cleanruv_log(clean_data->task, CLEANALLRUV_ID,"Replica %s does not support the CLEANALLRUV task.  "
dc8c34
+                        "Sending replica CLEANRUV task...", slapi_sdn_get_dn(agmt_get_dn_byref(ra)));
dc8c34
                     /*
dc8c34
                      *  Ok, this replica doesn't know about CLEANALLRUV, so just manually
dc8c34
                      *  add the CLEANRUV task to the replica.
dc8c34
@@ -2841,7 +2884,8 @@ replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn)
dc8c34
             /* we could not find any maxcsn's - already cleaned? */
dc8c34
             return NULL;
dc8c34
         }
dc8c34
-        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: Not all replicas online, retrying in %d seconds\n",interval);
dc8c34
+        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: "
dc8c34
+            "Not all replicas online, retrying in %d seconds\n", interval);
dc8c34
         PR_Lock( notify_lock );
dc8c34
         PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) );
dc8c34
         PR_Unlock( notify_lock );
dc8c34
-- 
dc8c34
1.8.1.4
dc8c34