Blame SOURCES/0014-Ticket-47509-CLEANALLRUV-doesnt-run-across-all-repli.patch

ba46c7
From fedc973133652f22888e7ae26d2d9c34a24fe0a6 Mon Sep 17 00:00:00 2001
ba46c7
From: Mark Reynolds <mreynolds@redhat.com>
ba46c7
Date: Tue, 17 Sep 2013 10:53:12 -0400
ba46c7
Subject: [PATCH 14/28] Ticket 47509 - CLEANALLRUV doesnt run across all replicas
ba46c7
ba46c7
Bug Description:  If one of the replicas in the environment is older and does not support
ba46c7
                  cleanallruv, then this would cause the cleanallruv task to never complete.
ba46c7
ba46c7
Fix Description:  Several issues are addressed with this fix:
ba46c7
ba46c7
	- Corrected error handling of replicas that do not support cleanallruv(prevent task hanging)
ba46c7
ba46c7
	- Created helper function to get local maxcsn:  replica_cleanallruv_get_local_maxcsn().
ba46c7
          This code was taken from the extended op "multimaster_extop_cleanruv_get_maxcsn".
ba46c7
ba46c7
	- Improved replica_cleanallruv_find_maxcsn() to also include the local maxcsn, and not just the remote replicas.
ba46c7
ba46c7
	- Improved abort task processing.  Abort task now waits for the cleanallruv task to be aborted before continuing.
ba46c7
ba46c7
	- Improved task configuration cleanup.  Removed places where the config attribute value was manually created.
ba46c7
          Now we search for the exact value to delete.
ba46c7
ba46c7
https://fedorahosted.org/389/ticket/47509
ba46c7
ba46c7
Reviewed by: richm(Thanks!!)
ba46c7
(cherry picked from commit 26253234c7b1c69286d8cde8f5e000bae946b6a5)
ba46c7
(cherry picked from commit b80706245e0a04e34d2c532ea4acf758886e3037)
ba46c7
---
ba46c7
 ldap/servers/plugins/replication/repl5.h           |    1 +
ba46c7
 .../plugins/replication/repl5_replica_config.c     |  314 ++++++++++++--------
ba46c7
 ldap/servers/plugins/replication/repl_extop.c      |   53 +----
ba46c7
 3 files changed, 188 insertions(+), 180 deletions(-)
ba46c7
ba46c7
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
ba46c7
index 6752ac8..5bec1c7 100644
ba46c7
--- a/ldap/servers/plugins/replication/repl5.h
ba46c7
+++ b/ldap/servers/plugins/replication/repl5.h
ba46c7
@@ -656,6 +656,7 @@ void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root, int sk
ba46c7
 int is_pre_cleaned_rid(ReplicaId rid);
ba46c7
 void set_cleaned_rid(ReplicaId rid);
ba46c7
 void cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...);
ba46c7
+char * replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn);
ba46c7
 
ba46c7
 #define CLEANRIDSIZ 4 /* maximum number for concurrent CLEANALLRUV tasks */
ba46c7
 
ba46c7
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
ba46c7
index 79ac5b0..fb0b746 100644
ba46c7
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
ba46c7
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
ba46c7
@@ -1834,7 +1834,7 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
ba46c7
     int rc = -1;
ba46c7
 
ba46c7
     if((conn = conn_new(agmt)) == NULL){
ba46c7
-        return -1;
ba46c7
+        return rc;
ba46c7
     }
ba46c7
     if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
ba46c7
         payload = create_cleanruv_payload(filter);
ba46c7
@@ -1848,7 +1848,10 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
ba46c7
                 char *response = NULL;
ba46c7
 
ba46c7
                 decode_cleanruv_payload(retsdata, &response);
ba46c7
-                if(response && strcmp(response,CLEANRUV_FINISHED) == 0){
ba46c7
+                if(response == NULL){
ba46c7
+                    /* this replica does not support cleanallruv */
ba46c7
+                    rc = 0;
ba46c7
+                } else if(strcmp(response,CLEANRUV_FINISHED) == 0){
ba46c7
                     /* finished cleaning */
ba46c7
                     rc = 0;
ba46c7
                 }
ba46c7
@@ -1858,8 +1861,6 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
ba46c7
                 slapi_ch_free_string(&retoid);
ba46c7
             }
ba46c7
         }
ba46c7
-    } else {
ba46c7
-        rc = -1;
ba46c7
     }
ba46c7
     conn_delete_internal_ext(conn);
ba46c7
     if(payload)
ba46c7
@@ -2114,16 +2115,16 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data)
ba46c7
     val.bv_val = data;
ba46c7
     mods[0] = &mod;
ba46c7
     mods[1] = NULL;
ba46c7
-    repl_dn = slapi_create_dn_string("cn=replica,cn=%s,cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn));
ba46c7
+    repl_dn = slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn));
ba46c7
     /*
ba46c7
      *  Add task to remote replica
ba46c7
      */
ba46c7
     rc = ldap_modify_ext_s( ld, repl_dn, mods, NULL, NULL);
ba46c7
 
ba46c7
     if(rc != LDAP_SUCCESS){
ba46c7
-    	cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task replica "
ba46c7
+        cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task (%s) to replica "
ba46c7
             "(%s).  You will need to manually run the CLEANRUV task on this replica (%s) error (%d)",
ba46c7
-            agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc);
ba46c7
+            repl_dn, agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc);
ba46c7
     }
ba46c7
     slapi_ch_free_string(&repl_dn);
ba46c7
     slapi_sdn_free(&sdn);
ba46c7
@@ -2349,7 +2350,6 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
ba46c7
     } else {
ba46c7
         /* only remove the config, leave the in-memory rid */
ba46c7
         dn = replica_get_dn(r);
ba46c7
-        pb = slapi_pblock_new();
ba46c7
         data = PR_smprintf("%d:%s", (int)rid, repl_root);
ba46c7
 
ba46c7
         mod.mod_op  = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
ba46c7
@@ -2362,6 +2362,7 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
ba46c7
         mods[0] = &mod;
ba46c7
         mods[1] = NULL;
ba46c7
 
ba46c7
+        pb = slapi_pblock_new();
ba46c7
         slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
ba46c7
         slapi_modify_internal_pb (pb);
ba46c7
         slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
ba46c7
@@ -2381,40 +2382,29 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
ba46c7
 static void
ba46c7
 delete_cleaned_rid_config(cleanruv_data *clean_data)
ba46c7
 {
ba46c7
-    Slapi_PBlock *pb;
ba46c7
+    Slapi_PBlock *pb, *modpb;
ba46c7
     Slapi_Entry **entries = NULL;
ba46c7
     LDAPMod *mods[2];
ba46c7
     LDAPMod mod;
ba46c7
-    struct berval *vals[2];
ba46c7
-    struct berval val;
ba46c7
-    char data[CSN_STRSIZE + 15];
ba46c7
-    char *csnstr = NULL;
ba46c7
+    struct berval *vals[5]= {0, 0, 0, 0, 0}; /* maximum of 4 tasks */
ba46c7
+    struct berval val[5];
ba46c7
     char *iter = NULL;
ba46c7
-    char *dn;
ba46c7
-    int found = 0, i;
ba46c7
-    int rc, ret, rid;
ba46c7
+    char *dn = NULL;
ba46c7
+    int i, ii;
ba46c7
+    int rc = -1, ret, rid;
ba46c7
 
ba46c7
     if(clean_data == NULL){
ba46c7
-        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "delete_cleaned_rid_config: cleanruv data is NULL, "
ba46c7
-                "failed to clean the config.\n");
ba46c7
+        cleanruv_log(NULL, CLEANALLRUV_ID, "delete_cleaned_rid_config: cleanruv data is NULL, "
ba46c7
+                "failed to clean the config.");
ba46c7
         return;
ba46c7
     }
ba46c7
     /*
ba46c7
-     *  If there is no maxcsn, set the proper csnstr
ba46c7
-     */
ba46c7
-    csnstr = csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr);
ba46c7
-    if ((csnstr == NULL) || (csn_get_replicaid(clean_data->maxcsn) == 0)) {
ba46c7
-        slapi_ch_free_string(&csnstr); /* no problem to pass NULL */
ba46c7
-        csnstr = slapi_ch_strdup("00000000000000000000");
ba46c7
-    }
ba46c7
-    /*
ba46c7
      *  Search the config for the exact attribute value to delete
ba46c7
      */
ba46c7
     pb = slapi_pblock_new();
ba46c7
     if(clean_data->replica){
ba46c7
         dn = replica_get_dn(clean_data->replica);
ba46c7
     } else {
ba46c7
-        rc = -1;
ba46c7
         goto bail;
ba46c7
     }
ba46c7
 
ba46c7
@@ -2424,72 +2414,81 @@ delete_cleaned_rid_config(cleanruv_data *clean_data)
ba46c7
     slapi_search_internal_pb(pb);
ba46c7
     slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
ba46c7
     if (ret != LDAP_SUCCESS){
ba46c7
-        /*
ba46c7
-         * Search failed, manually build the attr value
ba46c7
-         */
ba46c7
-        val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
ba46c7
-            (int)clean_data->rid, csnstr, clean_data->force);
ba46c7
-        slapi_pblock_destroy(pb);
ba46c7
+        cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: internal search failed(%d).",ret);
ba46c7
+        goto bail;
ba46c7
     } else {
ba46c7
         slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
ba46c7
         if (entries == NULL || entries[0] == NULL){
ba46c7
             /*
ba46c7
-             *  Entry not found, manually build the attr value
ba46c7
+             *  No matching entries!
ba46c7
              */
ba46c7
-            val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
ba46c7
-                (int)clean_data->rid, csnstr, clean_data->force);
ba46c7
+            cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: failed to find any "
ba46c7
+                    "entries with nsds5ReplicaCleanRUV under (%s)", dn);
ba46c7
+            goto bail;
ba46c7
         } else {
ba46c7
-            char **attr_val = slapi_entry_attr_get_charray(entries[0], "nsds5ReplicaCleanRUV");
ba46c7
-
ba46c7
-            for (i = 0; attr_val && attr_val[i] && !found; i++){
ba46c7
-                /* make a copy to retain the full value after toking */
ba46c7
-                char *aval = slapi_ch_strdup(attr_val[i]);
ba46c7
-
ba46c7
-                rid = atoi(ldap_utf8strtok_r(attr_val[i], ":", &iter));
ba46c7
-                if(rid == clean_data->rid){
ba46c7
-                    /* found it */
ba46c7
-                    found = 1;
ba46c7
-                    val.bv_len = PR_snprintf(data, sizeof(data), "%s", aval);
ba46c7
+            /*
ba46c7
+             *  Clean all the matching entries
ba46c7
+             */
ba46c7
+            for(i = 0; entries[i] != NULL;i++){
ba46c7
+                char **attr_val = slapi_entry_attr_get_charray(entries[i], type_replicaCleanRUV);
ba46c7
+                char *edn = slapi_entry_get_dn(entries[i]);
ba46c7
+                int count = 0;
ba46c7
+
ba46c7
+                for (ii = 0; attr_val && attr_val[ii] && i < 5; ii++){
ba46c7
+                    /* make a copy to retain the full value after toking */
ba46c7
+                    char *aval = slapi_ch_strdup(attr_val[ii]);
ba46c7
+
ba46c7
+                    rid = atoi(ldap_utf8strtok_r(attr_val[ii], ":", &iter));
ba46c7
+                    if(rid == clean_data->rid){
ba46c7
+                        val[count].bv_len = strlen(aval);
ba46c7
+                        val[count].bv_val = aval;
ba46c7
+                        vals[count] = &val[count];
ba46c7
+                        count++;
ba46c7
+                    } else {
ba46c7
+                        slapi_ch_free_string(&aval);
ba46c7
+                    }
ba46c7
                 }
ba46c7
-                slapi_ch_free_string(&aval);
ba46c7
-            }
ba46c7
-            if(!found){
ba46c7
+                slapi_ch_array_free(attr_val);
ba46c7
+
ba46c7
                 /*
ba46c7
-                 *  No match, manually build the attr value
ba46c7
+                 *  Now delete the attribute
ba46c7
                  */
ba46c7
-                val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
ba46c7
-                    (int)clean_data->rid, csnstr, clean_data->force);
ba46c7
+                vals[5] = NULL;
ba46c7
+                mod.mod_op  = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
ba46c7
+                mod.mod_type = (char *)type_replicaCleanRUV;
ba46c7
+                mod.mod_bvalues = vals;
ba46c7
+                mods[0] = &mod;
ba46c7
+                mods[1] = NULL;
ba46c7
+
ba46c7
+                modpb = slapi_pblock_new();
ba46c7
+                slapi_modify_internal_set_pb(modpb, edn, mods, NULL, NULL,
ba46c7
+                        repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
ba46c7
+                slapi_modify_internal_pb (modpb);
ba46c7
+                slapi_pblock_get(modpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
ba46c7
+                slapi_pblock_destroy(modpb);
ba46c7
+
ba46c7
+                /* free the attr vals */
ba46c7
+                for (ii = 0; ii < count; ii++){
ba46c7
+                    slapi_ch_free_string(&val[ii].bv_val);
ba46c7
+                }
ba46c7
+
ba46c7
+                if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
ba46c7
+                    cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove task data "
ba46c7
+                            "from (%s) error (%d), rid (%d)", edn, rc, clean_data->rid);
ba46c7
+                    goto bail;
ba46c7
+                }
ba46c7
             }
ba46c7
-            slapi_ch_array_free(attr_val);
ba46c7
         }
ba46c7
-        slapi_free_search_results_internal(pb);
ba46c7
-        slapi_pblock_destroy(pb);
ba46c7
     }
ba46c7
 
ba46c7
-    /*
ba46c7
-     *  Now delete the attribute
ba46c7
-     */
ba46c7
-    mod.mod_op  = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
ba46c7
-    mod.mod_type = (char *)type_replicaCleanRUV;
ba46c7
-    mod.mod_bvalues = vals;
ba46c7
-    vals [0] = &val;
ba46c7
-    vals [1] = NULL;
ba46c7
-    val.bv_val = data;
ba46c7
-    mods[0] = &mod;
ba46c7
-    mods[1] = NULL;
ba46c7
-    pb = slapi_pblock_new();
ba46c7
-    slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
ba46c7
-    slapi_modify_internal_pb (pb);
ba46c7
-    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
ba46c7
-
ba46c7
 bail:
ba46c7
     if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
ba46c7
-        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config "
ba46c7
-            "(%d), rid (%d)\n", rc, clean_data->rid);
ba46c7
+        cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove replica config "
ba46c7
+            "(%d), rid (%d)", rc, clean_data->rid);
ba46c7
     }
ba46c7
+    slapi_free_search_results_internal(pb);
ba46c7
     slapi_pblock_destroy(pb);
ba46c7
     slapi_ch_free_string(&dn);
ba46c7
-    slapi_ch_free_string(&csnstr);
ba46c7
 }
ba46c7
 
ba46c7
 /*
ba46c7
@@ -2694,6 +2693,7 @@ replica_abort_task_thread(void *arg)
ba46c7
     int agmt_not_notified = 1;
ba46c7
     int interval = 10;
ba46c7
     int release_it = 0;
ba46c7
+    int count = 0, rc = 0;
ba46c7
 
ba46c7
     cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid);
ba46c7
 
ba46c7
@@ -2772,6 +2772,20 @@ done:
ba46c7
         cleanruv_log(data->task, ABORT_CLEANALLRUV_ID,"Abort task failed, will resume the task at the next server startup.");
ba46c7
     } else {
ba46c7
         /*
ba46c7
+         *  Wait for this server to stop its cleanallruv task(which removes the rid from the cleaned list)
ba46c7
+         */
ba46c7
+        cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Waiting for CleanAllRUV task to abort...");
ba46c7
+        while(is_cleaned_rid(data->rid)){
ba46c7
+            DS_Sleep(PR_SecondsToInterval(1));
ba46c7
+            count++;
ba46c7
+            if(count == 60){ /* it should not take this long */
ba46c7
+                cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "CleanAllRUV task failed to abort.  You might need to "
ba46c7
+                        "rerun the task.");
ba46c7
+                rc = -1;
ba46c7
+                break;
ba46c7
+            }
ba46c7
+        }
ba46c7
+        /*
ba46c7
          *  Clean up the config
ba46c7
          */
ba46c7
         delete_aborted_rid(data->replica, data->rid, data->repl_root, 1); /* delete just the config, leave rid in memory */
ba46c7
@@ -2779,8 +2793,13 @@ done:
ba46c7
             check_replicas_are_done_aborting(data);
ba46c7
         }
ba46c7
         delete_aborted_rid(data->replica, data->rid, data->repl_root, 0); /* remove the in-memory aborted rid */
ba46c7
-        cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid);
ba46c7
+        if(rc == 0){
ba46c7
+            cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid);
ba46c7
+        } else {
ba46c7
+            cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Failed to abort task for rid(%d)",data->rid);
ba46c7
+        }
ba46c7
     }
ba46c7
+
ba46c7
     if(data->task){
ba46c7
         slapi_task_finish(data->task, agmt_not_notified);
ba46c7
     }
ba46c7
@@ -2858,6 +2877,7 @@ replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int che
ba46c7
                      *  add the CLEANRUV task to the replica.
ba46c7
                      */
ba46c7
                     replica_send_cleanruv_task(ra, clean_data);
ba46c7
+                    rc = 0;
ba46c7
                 }
ba46c7
                 if (NULL != retsdata)
ba46c7
                     ber_bvfree(retsdata);
ba46c7
@@ -2881,72 +2901,49 @@ replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn)
ba46c7
 {
ba46c7
     Object *agmt_obj;
ba46c7
     Repl_Agmt *agmt;
ba46c7
-    char *rid_text;
ba46c7
     CSN *maxcsn = NULL, *topcsn = NULL;
ba46c7
-    int done = 1, found = 0;
ba46c7
-    int interval = 10;
ba46c7
+    char *rid_text = slapi_ch_smprintf("%d", rid);
ba46c7
+    char *csnstr = NULL;
ba46c7
 
ba46c7
-    rid_text = slapi_ch_smprintf("%d", rid);
ba46c7
+    /* start with the local maxcsn */
ba46c7
+    csnstr = replica_cleanallruv_get_local_maxcsn(rid, basedn);
ba46c7
+    if(csnstr){
ba46c7
+        topcsn = csn_new();
ba46c7
+        csn_init_by_string(topcsn, csnstr);
ba46c7
+        slapi_ch_free_string(&csnstr);
ba46c7
+    }
ba46c7
 
ba46c7
-    while(done && !is_task_aborted(rid) && !slapi_is_shutting_down()){
ba46c7
-        agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
ba46c7
-        if(agmt_obj == NULL){
ba46c7
-            break;
ba46c7
+    agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
ba46c7
+    if(agmt_obj == NULL){ /* no agreements */
ba46c7
+        goto done;
ba46c7
+    }
ba46c7
+    while (agmt_obj && !slapi_is_shutting_down()){
ba46c7
+        agmt = (Repl_Agmt*)object_get_data (agmt_obj);
ba46c7
+        if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
ba46c7
+            agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
ba46c7
+            continue;
ba46c7
         }
ba46c7
-        while (agmt_obj && !slapi_is_shutting_down()){
ba46c7
-            agmt = (Repl_Agmt*)object_get_data (agmt_obj);
ba46c7
-            if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
ba46c7
+        if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){
ba46c7
+            if(maxcsn == NULL){
ba46c7
                 agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
ba46c7
-                done = 0;
ba46c7
                 continue;
ba46c7
             }
ba46c7
-            if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){
ba46c7
-                if(maxcsn == NULL){
ba46c7
-                    agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
ba46c7
-                    continue;
ba46c7
-                }
ba46c7
-                found = 1;
ba46c7
-                if(topcsn == NULL){
ba46c7
+            if(topcsn == NULL){
ba46c7
+                topcsn = maxcsn;
ba46c7
+            } else {
ba46c7
+                if(csn_compare(topcsn, maxcsn) < 0){
ba46c7
+                    csn_free(&topcsn);
ba46c7
                     topcsn = maxcsn;
ba46c7
                 } else {
ba46c7
-                    if(csn_compare(topcsn, maxcsn) < 0){
ba46c7
-                        csn_free(&topcsn);
ba46c7
-                        topcsn = maxcsn;
ba46c7
-                    } else {
ba46c7
-                        csn_free(&maxcsn);
ba46c7
-                    }
ba46c7
+                    csn_free(&maxcsn);
ba46c7
                 }
ba46c7
-                done = 0;
ba46c7
-            } else {
ba46c7
-                done = 1;
ba46c7
-                break;
ba46c7
             }
ba46c7
-            agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
ba46c7
-        } /* agmt while */
ba46c7
-        if(done == 0 || is_task_aborted(rid) ){
ba46c7
-            break;
ba46c7
-        }
ba46c7
-        if(!found){
ba46c7
-            /* we could not find any maxcsn's - already cleaned? */
ba46c7
-            return NULL;
ba46c7
-        }
ba46c7
-        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: "
ba46c7
-            "Not all replicas online, retrying in %d seconds\n", interval);
ba46c7
-        PR_Lock( notify_lock );
ba46c7
-        PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) );
ba46c7
-        PR_Unlock( notify_lock );
ba46c7
-
ba46c7
-        if(interval < 14400){ /* 4 hour max */
ba46c7
-            interval = interval * 2;
ba46c7
-        } else {
ba46c7
-            interval = 14400;
ba46c7
         }
ba46c7
+        agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
ba46c7
     }
ba46c7
-    slapi_ch_free_string(&rid_text);
ba46c7
 
ba46c7
-    if(is_task_aborted(rid)){
ba46c7
-        return NULL;
ba46c7
-    }
ba46c7
+done:
ba46c7
+    slapi_ch_free_string(&rid_text);
ba46c7
 
ba46c7
     return topcsn;
ba46c7
 }
ba46c7
@@ -3229,3 +3226,64 @@ cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...)
ba46c7
     va_end(ap4);
ba46c7
 }
ba46c7
 
ba46c7
+char *
ba46c7
+replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn)
ba46c7
+{
ba46c7
+    Slapi_PBlock *search_pb = NULL;
ba46c7
+    Slapi_Entry **entries = NULL;
ba46c7
+    char **ruv_elements = NULL;
ba46c7
+    char *maxcsn = NULL;
ba46c7
+    char *filter = NULL;
ba46c7
+    char *ridstr = NULL;
ba46c7
+    char *iter = NULL;
ba46c7
+    char *attrs[2];
ba46c7
+    char *ruv_part = NULL;
ba46c7
+    int part_count = 0;
ba46c7
+    int res, i;
ba46c7
+
ba46c7
+    /*
ba46c7
+     *  Get the maxruv from the database tombstone entry
ba46c7
+     */
ba46c7
+    filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))";
ba46c7
+    attrs[0] = "nsds50ruv";
ba46c7
+    attrs[1] = NULL;
ba46c7
+    ridstr = slapi_ch_smprintf("{replica %d ldap", rid);
ba46c7
+
ba46c7
+    search_pb = slapi_pblock_new();
ba46c7
+    slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
ba46c7
+    slapi_search_internal_pb (search_pb);
ba46c7
+    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
ba46c7
+
ba46c7
+    if ( LDAP_SUCCESS == res ) {
ba46c7
+        slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
ba46c7
+        if (NULL == entries || entries[0] == NULL) {
ba46c7
+            /* Hmmm, no tombstone!  Error out */
ba46c7
+        } else {
ba46c7
+            /* find the right ruv element, and find the maxcsn */
ba46c7
+            ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]);
ba46c7
+            for(i = 0; ruv_elements && ruv_elements[i] ; i++){
ba46c7
+                if(strstr(ruv_elements[i], ridstr)){
ba46c7
+                    /* get the max csn */
ba46c7
+                    ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter);
ba46c7
+                    for(part_count = 1; ruv_part && part_count < 5; part_count++){
ba46c7
+                        ruv_part = ldap_utf8strtok_r(iter, " ", &iter);
ba46c7
+                    }
ba46c7
+                    if(part_count == 5 && ruv_part){/* we have the maxcsn */
ba46c7
+                        maxcsn = slapi_ch_strdup(ruv_part);
ba46c7
+                        break;
ba46c7
+                    }
ba46c7
+                }
ba46c7
+            }
ba46c7
+            slapi_ch_array_free(ruv_elements);
ba46c7
+        }
ba46c7
+    } else {
ba46c7
+        /* internal search failed */
ba46c7
+        cleanruv_log(NULL, CLEANALLRUV_ID, "replica_cleanallruv_get_local_maxcsn: internal search failed (%d)\n", res);
ba46c7
+    }
ba46c7
+
ba46c7
+	slapi_free_search_results_internal(search_pb);
ba46c7
+	slapi_pblock_destroy(search_pb);
ba46c7
+	slapi_ch_free_string(&ridstr);
ba46c7
+
ba46c7
+    return maxcsn;
ba46c7
+}
ba46c7
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
ba46c7
index f41cc7d..57249a6 100644
ba46c7
--- a/ldap/servers/plugins/replication/repl_extop.c
ba46c7
+++ b/ldap/servers/plugins/replication/repl_extop.c
ba46c7
@@ -1784,26 +1784,16 @@ free_and_return:
ba46c7
 int
ba46c7
 multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
ba46c7
 {
ba46c7
-	Slapi_PBlock *search_pb = NULL;
ba46c7
-	Slapi_Entry **entries = NULL;
ba46c7
 	struct berval *resp_bval = NULL;
ba46c7
 	struct berval *extop_payload;
ba46c7
 	BerElement *resp_bere = NULL;
ba46c7
-	char **ruv_elements = NULL;
ba46c7
 	char *extop_oid = NULL;
ba46c7
-	char *ruv_part = NULL;
ba46c7
 	char *base_dn = NULL;
ba46c7
 	char *payload = NULL;
ba46c7
 	char *maxcsn = NULL;
ba46c7
-	char *filter = NULL;
ba46c7
-	char *ridstr = NULL;
ba46c7
 	char *iter = NULL;
ba46c7
-	char *attrs[2];
ba46c7
-	int part_count = 0;
ba46c7
 	int rid = 0;
ba46c7
-	int res = 0;
ba46c7
 	int rc = LDAP_OPERATIONS_ERROR;
ba46c7
-	int i = 0;
ba46c7
 
ba46c7
 	slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
ba46c7
 	slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload);
ba46c7
@@ -1822,45 +1812,7 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
ba46c7
 	}
ba46c7
 	rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
ba46c7
 	base_dn = ldap_utf8strtok_r(iter, ":", &iter);
ba46c7
-	/*
ba46c7
-	 *  Get the maxruv from the database tombstone entry
ba46c7
-	 */
ba46c7
-	filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))";
ba46c7
-	attrs[0] = "nsds50ruv";
ba46c7
-	attrs[1] = NULL;
ba46c7
-	ridstr = slapi_ch_smprintf("{replica %d ldap", rid);
ba46c7
-
ba46c7
-	search_pb = slapi_pblock_new();
ba46c7
-	slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
ba46c7
-	slapi_search_internal_pb (search_pb);
ba46c7
-	slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
ba46c7
-
ba46c7
-	if ( LDAP_SUCCESS == res ) {
ba46c7
-		slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
ba46c7
-		if (NULL == entries || entries[0] == NULL) {
ba46c7
-			/* Hmmm, no tombstpne!  Error out */
ba46c7
-		} else {
ba46c7
-			/* find the right ruv element, and find the maxcsn */
ba46c7
-			ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]);
ba46c7
-			for(i = 0; ruv_elements && ruv_elements[i] ; i++){
ba46c7
-				if(strstr(ruv_elements[i], ridstr)){
ba46c7
-					/* get the max csn */
ba46c7
-					ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter);
ba46c7
-					for(part_count = 1; ruv_part && part_count < 5; part_count++){
ba46c7
-						ruv_part = ldap_utf8strtok_r(iter, " ", &iter);
ba46c7
-					}
ba46c7
-					if(part_count == 5 && ruv_part){/* we have the maxcsn */
ba46c7
-						maxcsn = slapi_ch_strdup(ruv_part);
ba46c7
-						break;
ba46c7
-					}
ba46c7
-				}
ba46c7
-			}
ba46c7
-			slapi_ch_array_free(ruv_elements);
ba46c7
-		}
ba46c7
-	} else {
ba46c7
-		/* internal search failed */
ba46c7
-		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Get MaxCSN Task: internal search failed (%d)\n", res);
ba46c7
-	}
ba46c7
+	maxcsn = replica_cleanallruv_get_local_maxcsn(rid, base_dn);
ba46c7
 	if(maxcsn == NULL){
ba46c7
 		maxcsn = slapi_ch_strdup(CLEANRUV_NO_MAXCSN);
ba46c7
 	}
ba46c7
@@ -1889,11 +1841,8 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
ba46c7
 	}
ba46c7
 
ba46c7
 free_and_return:
ba46c7
-	slapi_free_search_results_internal(search_pb);
ba46c7
-	slapi_pblock_destroy(search_pb);
ba46c7
 	slapi_ch_free_string(&payload);
ba46c7
 	slapi_ch_free_string(&maxcsn);
ba46c7
-	slapi_ch_free_string(&ridstr);
ba46c7
 
ba46c7
 	return rc;
ba46c7
 }
ba46c7
-- 
ba46c7
1.7.1
ba46c7