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