|
|
dc8c34 |
From b04b2271f48f427330344ca9c61d76e312e9eb8c Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
dc8c34 |
Date: Tue, 20 Nov 2012 16:14:42 -0500
|
|
|
dc8c34 |
Subject: [PATCH 17/22] Ticket 337 - improve CLEANRUV functionality
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Bug Description: Without anonymous access allowed, then task could not
|
|
|
dc8c34 |
contact other servers and retrieve data(ruv, maxcsns, etc).
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Fix Description: Changed all communication to use extended operations, and improved
|
|
|
dc8c34 |
sychronization between the replicas.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/337
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Reviewed by: richm(Thanks Rich!)
|
|
|
dc8c34 |
(cherry picked from commit ecbd8b7513d05dab5876a88ca56b102c08a7a67c)
|
|
|
dc8c34 |
(cherry picked from commit 7a3014c0746134403f1fe9a25eac9581750aef0b)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
ldap/servers/plugins/replication/cl5_api.c | 21 +-
|
|
|
dc8c34 |
ldap/servers/plugins/replication/repl5.h | 29 +-
|
|
|
dc8c34 |
ldap/servers/plugins/replication/repl5_agmt.c | 99 --
|
|
|
dc8c34 |
ldap/servers/plugins/replication/repl5_agmtlist.c | 11 +-
|
|
|
dc8c34 |
.../servers/plugins/replication/repl5_connection.c | 6 +
|
|
|
dc8c34 |
ldap/servers/plugins/replication/repl5_init.c | 69 +-
|
|
|
dc8c34 |
ldap/servers/plugins/replication/repl5_replica.c | 132 +--
|
|
|
dc8c34 |
.../plugins/replication/repl5_replica_config.c | 1055 +++++++++++++-------
|
|
|
dc8c34 |
ldap/servers/plugins/replication/repl_extop.c | 266 ++++-
|
|
|
dc8c34 |
ldap/servers/plugins/replication/replutil.c | 47 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 7 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/misc.c | 2 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 1 +
|
|
|
dc8c34 |
ldap/servers/slapd/entry.c | 10 +-
|
|
|
dc8c34 |
ldap/servers/slapd/slapi-private.h | 2 +-
|
|
|
dc8c34 |
15 files changed, 1104 insertions(+), 653 deletions(-)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
|
|
|
dc8c34 |
index a347c57..6c94b3d 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/cl5_api.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/cl5_api.c
|
|
|
dc8c34 |
@@ -1474,13 +1474,13 @@ int cl5WriteOperation(const char *replName, const char *replGen,
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Name: cl5CreateReplayIterator
|
|
|
dc8c34 |
- Description: creates an iterator that allows to retireve changes that should
|
|
|
dc8c34 |
- to be sent to the consumer identified by ruv. The iteration is peformed by
|
|
|
dc8c34 |
+ Description: creates an iterator that allows to retrieve changes that should
|
|
|
dc8c34 |
+ to be sent to the consumer identified by ruv. The iteration is performed by
|
|
|
dc8c34 |
repeated calls to cl5GetNextOperationToReplay.
|
|
|
dc8c34 |
Parameters: replica - replica whose data we wish to iterate;
|
|
|
dc8c34 |
ruv - consumer ruv;
|
|
|
dc8c34 |
iterator - iterator to be passed to cl5GetNextOperationToReplay call
|
|
|
dc8c34 |
- Return: CL5_SUCCESS, if function is successfull;
|
|
|
dc8c34 |
+ Return: CL5_SUCCESS, if function is successful;
|
|
|
dc8c34 |
CL5_MISSING_DATA, if data that should be in the changelog is missing
|
|
|
dc8c34 |
CL5_PURGED_DATA, if some data that consumer needs has been purged.
|
|
|
dc8c34 |
Note that the iterator can be non null if the supplier contains
|
|
|
dc8c34 |
@@ -1488,14 +1488,14 @@ int cl5WriteOperation(const char *replName, const char *replGen,
|
|
|
dc8c34 |
CL5_NOTFOUND if the consumer is up to data with respect to the supplier
|
|
|
dc8c34 |
CL5_BAD_DATA if invalid parameter is passed;
|
|
|
dc8c34 |
CL5_BAD_STATE if db has not been open;
|
|
|
dc8c34 |
- CL5_DB_ERROR if any other db error occured;
|
|
|
dc8c34 |
+ CL5_DB_ERROR if any other db error occurred;
|
|
|
dc8c34 |
CL5_MEMORY_ERROR if memory allocation fails.
|
|
|
dc8c34 |
Algorithm: Build a list of csns from consumer's and supplier's ruv. For each element
|
|
|
dc8c34 |
of the consumer's ruv put max csn into the csn list. For each element
|
|
|
dc8c34 |
of the supplier's ruv not in the consumer's ruv put min csn from the
|
|
|
dc8c34 |
supplier's ruv into the list. The list contains, for each known replica,
|
|
|
dc8c34 |
the starting point for changes to be sent to the consumer.
|
|
|
dc8c34 |
- Sort the list in accending order.
|
|
|
dc8c34 |
+ Sort the list in ascending order.
|
|
|
dc8c34 |
Build a hash which contains, for each known replica, whether the
|
|
|
dc8c34 |
supplier can bring the consumer up to data with respect to that replica.
|
|
|
dc8c34 |
The hash is used to decide whether a change can be sent to the consumer
|
|
|
dc8c34 |
@@ -1503,7 +1503,7 @@ int cl5WriteOperation(const char *replName, const char *replGen,
|
|
|
dc8c34 |
we can bring the consumer up to date.
|
|
|
dc8c34 |
Position the db cursor on the change entry that corresponds to this csn.
|
|
|
dc8c34 |
Hash entries are created for each replica traversed so far. sendChanges
|
|
|
dc8c34 |
- flag is set to FALSE for all repolicas except the last traversed.
|
|
|
dc8c34 |
+ flag is set to FALSE for all replicas except the last traversed.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
int cl5CreateReplayIteratorEx (Private_Repl_Protocol *prp, const RUV *consumerRuv,
|
|
|
dc8c34 |
@@ -6543,7 +6543,9 @@ bail:
|
|
|
dc8c34 |
void
|
|
|
dc8c34 |
cl5CleanRUV(ReplicaId rid){
|
|
|
dc8c34 |
CL5DBFile *file;
|
|
|
dc8c34 |
- Object *obj;
|
|
|
dc8c34 |
+ Object *obj = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ slapi_rwlock_wrlock (s_cl5Desc.stLock);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
obj = objset_first_obj(s_cl5Desc.dbFiles);
|
|
|
dc8c34 |
while (obj){
|
|
|
dc8c34 |
@@ -6552,6 +6554,11 @@ cl5CleanRUV(ReplicaId rid){
|
|
|
dc8c34 |
ruv_delete_replica(file->maxRUV, rid);
|
|
|
dc8c34 |
obj = objset_next_obj(s_cl5Desc.dbFiles, obj);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ if(obj){
|
|
|
dc8c34 |
+ object_release (obj);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ slapi_rwlock_unlock (s_cl5Desc.stLock);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
void trigger_cl_trimming(ReplicaId rid){
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
|
|
|
dc8c34 |
index 61b51b0..bd582bc 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5.h
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5.h
|
|
|
dc8c34 |
@@ -97,8 +97,14 @@
|
|
|
dc8c34 |
/* cleanallruv extended ops */
|
|
|
dc8c34 |
#define REPL_CLEANRUV_OID "2.16.840.1.113730.3.6.5"
|
|
|
dc8c34 |
#define REPL_ABORT_CLEANRUV_OID "2.16.840.1.113730.3.6.6"
|
|
|
dc8c34 |
-#define CLEANRUV_NOTIFIED 0
|
|
|
dc8c34 |
-#define CLEANRUV_RELEASED 1
|
|
|
dc8c34 |
+#define REPL_CLEANRUV_GET_MAXCSN_OID "2.16.840.1.113730.3.6.7"
|
|
|
dc8c34 |
+#define REPL_CLEANRUV_CHECK_STATUS_OID "2.16.840.1.113730.3.6.8"
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+#define CLEANRUV_ACCEPTED "accepted"
|
|
|
dc8c34 |
+#define CLEANRUV_REJECTED "rejected"
|
|
|
dc8c34 |
+#define CLEANRUV_FINISHED "finished"
|
|
|
dc8c34 |
+#define CLEANRUV_CLEANING "cleaning"
|
|
|
dc8c34 |
+#define CLEANRUV_NO_MAXCSN "no maxcsn"
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* DS 5.0 replication protocol error codes */
|
|
|
dc8c34 |
#define NSDS50_REPL_REPLICA_READY 0x00 /* Replica ready, go ahead */
|
|
|
dc8c34 |
@@ -230,6 +236,8 @@ int multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb);
|
|
|
dc8c34 |
int multimaster_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb);
|
|
|
dc8c34 |
int multimaster_extop_cleanruv(Slapi_PBlock *pb);
|
|
|
dc8c34 |
int multimaster_extop_abort_cleanruv(Slapi_PBlock *pb);
|
|
|
dc8c34 |
+int multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb);
|
|
|
dc8c34 |
+int multimaster_extop_cleanruv_check_status(Slapi_PBlock *pb);
|
|
|
dc8c34 |
int extop_noop(Slapi_PBlock *pb);
|
|
|
dc8c34 |
struct berval *NSDS50StartReplicationRequest_new(const char *protocol_oid,
|
|
|
dc8c34 |
const char *repl_root, char **extra_referrals, CSN *csn);
|
|
|
dc8c34 |
@@ -365,9 +373,6 @@ PRBool agmt_is_enabled(Repl_Agmt *ra);
|
|
|
dc8c34 |
int agmt_set_enabled_from_entry(Repl_Agmt *ra, Slapi_Entry *e, char *returntext);
|
|
|
dc8c34 |
char **agmt_get_attrs_to_strip(Repl_Agmt *ra);
|
|
|
dc8c34 |
int agmt_set_attrs_to_strip(Repl_Agmt *ra, Slapi_Entry *e);
|
|
|
dc8c34 |
-void agmt_set_cleanruv_notified_from_entry(Repl_Agmt *ra, Slapi_Entry *e);
|
|
|
dc8c34 |
-int agmt_set_cleanruv_data(Repl_Agmt *ra, ReplicaId rid, int op);
|
|
|
dc8c34 |
-int agmt_is_cleanruv_notified(Repl_Agmt *ra, ReplicaId rid);
|
|
|
dc8c34 |
int agmt_set_timeout(Repl_Agmt *ra, long timeout);
|
|
|
dc8c34 |
void agmt_update_done(Repl_Agmt *ra, int is_total);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -454,6 +459,7 @@ LDAP * conn_get_ldap(Repl_Connection *conn);
|
|
|
dc8c34 |
void conn_lock(Repl_Connection *conn);
|
|
|
dc8c34 |
void conn_unlock(Repl_Connection *conn);
|
|
|
dc8c34 |
void conn_delete_internal_ext(Repl_Connection *conn);
|
|
|
dc8c34 |
+const char* conn_get_bindmethod(Repl_Connection *conn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* In repl5_protocol.c */
|
|
|
dc8c34 |
typedef struct repl_protocol Repl_Protocol;
|
|
|
dc8c34 |
@@ -608,7 +614,7 @@ int replica_config_init();
|
|
|
dc8c34 |
void replica_config_destroy ();
|
|
|
dc8c34 |
int get_replica_type(Replica *r);
|
|
|
dc8c34 |
int replica_execute_cleanruv_task_ext(Object *r, ReplicaId rid);
|
|
|
dc8c34 |
-void add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn);
|
|
|
dc8c34 |
+void add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing);
|
|
|
dc8c34 |
int is_cleaned_rid(ReplicaId rid);
|
|
|
dc8c34 |
int replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
|
|
|
dc8c34 |
int *returncode, char *returntext, void *arg);
|
|
|
dc8c34 |
@@ -616,17 +622,15 @@ void replica_cleanallruv_thread_ext(void *arg);
|
|
|
dc8c34 |
void stop_ruv_cleaning();
|
|
|
dc8c34 |
int task_aborted();
|
|
|
dc8c34 |
void replica_abort_task_thread(void *arg);
|
|
|
dc8c34 |
-void delete_cleaned_rid(Replica *r, ReplicaId rid, CSN *maxcsn);
|
|
|
dc8c34 |
+void remove_cleaned_rid(ReplicaId rid);
|
|
|
dc8c34 |
int process_repl_agmts(Replica *replica, int *agmt_info, char *oid, Slapi_Task *task, struct berval *payload, int op);
|
|
|
dc8c34 |
int decode_cleanruv_payload(struct berval *extop_value, char **payload);
|
|
|
dc8c34 |
-struct berval *create_ruv_payload(char *value);
|
|
|
dc8c34 |
-void replica_add_cleanruv_data(Replica *r, char *val);
|
|
|
dc8c34 |
-void replica_remove_cleanruv_data(Replica *r, char *val);
|
|
|
dc8c34 |
-CSN *replica_get_cleanruv_maxcsn(Replica *r, ReplicaId rid);
|
|
|
dc8c34 |
+struct berval *create_cleanruv_payload(char *value);
|
|
|
dc8c34 |
void ruv_get_cleaned_rids(RUV *ruv, ReplicaId *rids);
|
|
|
dc8c34 |
void add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root);
|
|
|
dc8c34 |
int is_task_aborted(ReplicaId rid);
|
|
|
dc8c34 |
-void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root);
|
|
|
dc8c34 |
+void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root, int skip);
|
|
|
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 |
|
|
|
dc8c34 |
@@ -643,6 +647,7 @@ typedef struct _cleanruv_data
|
|
|
dc8c34 |
char *repl_root;
|
|
|
dc8c34 |
Slapi_DN *sdn;
|
|
|
dc8c34 |
char *certify;
|
|
|
dc8c34 |
+ char *force;
|
|
|
dc8c34 |
} cleanruv_data;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* replutil.c */
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
|
|
|
dc8c34 |
index d25f54b..935fb37 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5_agmt.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
|
|
|
dc8c34 |
@@ -141,7 +141,6 @@ typedef struct repl5agmt {
|
|
|
dc8c34 |
char **attrs_to_strip; /* for fractional replication, if a "mod" is empty, strip out these attributes:
|
|
|
dc8c34 |
* modifiersname, modifytimestamp, internalModifiersname, internalModifyTimestamp, etc */
|
|
|
dc8c34 |
int agreement_type;
|
|
|
dc8c34 |
- int cleanruv_notified[CLEANRIDSIZ + 1]; /* specifies if the replica has been notified of a CLEANALLRUV task */
|
|
|
dc8c34 |
} repl5agmt;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Forward declarations */
|
|
|
dc8c34 |
@@ -252,7 +251,6 @@ agmt_new_from_entry(Slapi_Entry *e)
|
|
|
dc8c34 |
Repl_Agmt *ra;
|
|
|
dc8c34 |
Slapi_Attr *sattr;
|
|
|
dc8c34 |
char *tmpstr;
|
|
|
dc8c34 |
- char **clean_vals = NULL;
|
|
|
dc8c34 |
char **denied_attrs = NULL;
|
|
|
dc8c34 |
char *auto_initialize = NULL;
|
|
|
dc8c34 |
char *val_nsds5BeginReplicaRefresh = "start";
|
|
|
dc8c34 |
@@ -431,20 +429,6 @@ agmt_new_from_entry(Slapi_Entry *e)
|
|
|
dc8c34 |
ra->last_init_start_time = 0UL;
|
|
|
dc8c34 |
ra->last_init_status[0] = '\0';
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- /* cleanruv notification */
|
|
|
dc8c34 |
- clean_vals = slapi_entry_attr_get_charray(e, type_nsds5ReplicaCleanRUVnotified);
|
|
|
dc8c34 |
- if(clean_vals){
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
- for (i = 0; i < CLEANRIDSIZ && clean_vals[i]; i++){
|
|
|
dc8c34 |
- ra->cleanruv_notified[i] = atoi(clean_vals[i]);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if(i < CLEANRIDSIZ)
|
|
|
dc8c34 |
- ra->cleanruv_notified[i + 1] = 0;
|
|
|
dc8c34 |
- slapi_ch_array_free(clean_vals);
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- ra->cleanruv_notified[0] = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/* Fractional attributes */
|
|
|
dc8c34 |
slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeList, &sattr);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -2623,89 +2607,6 @@ agmt_set_attrs_to_strip(Repl_Agmt *ra, Slapi_Entry *e)
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
-int
|
|
|
dc8c34 |
-agmt_is_cleanruv_notified(Repl_Agmt *ra, ReplicaId rid){
|
|
|
dc8c34 |
- int notified = 0;
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Lock(ra->lock);
|
|
|
dc8c34 |
- for(i = 0; i < CLEANRIDSIZ && ra->cleanruv_notified[i]; i++){
|
|
|
dc8c34 |
- if(ra->cleanruv_notified[i] == rid){
|
|
|
dc8c34 |
- notified = 1;
|
|
|
dc8c34 |
- break;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- PR_Unlock(ra->lock);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- return notified;
|
|
|
dc8c34 |
-}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
-/*
|
|
|
dc8c34 |
- * This will trigger agmt_set_cleanruv_notified_from_entry() to be called,
|
|
|
dc8c34 |
- * which will update the in memory agmt.
|
|
|
dc8c34 |
- *
|
|
|
dc8c34 |
- * op can be: CLEANRUV_NOTIFIED or CLEANRUV_RELEASED
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
-int
|
|
|
dc8c34 |
-agmt_set_cleanruv_data(Repl_Agmt *ra, ReplicaId rid, int op){
|
|
|
dc8c34 |
- Slapi_PBlock *pb;
|
|
|
dc8c34 |
- LDAPMod *mods[2];
|
|
|
dc8c34 |
- LDAPMod mod;
|
|
|
dc8c34 |
- struct berval *vals[2];
|
|
|
dc8c34 |
- struct berval val;
|
|
|
dc8c34 |
- char data[6];
|
|
|
dc8c34 |
- int rc = 0;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- if(ra == NULL){
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- if(op == CLEANRUV_NOTIFIED){
|
|
|
dc8c34 |
- /* add the cleanruv data */
|
|
|
dc8c34 |
- mod.mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES;
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- /* remove the cleanruv data */
|
|
|
dc8c34 |
- mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- pb = slapi_pblock_new();
|
|
|
dc8c34 |
- val.bv_len = PR_snprintf(data, sizeof(data), "%d", (int)rid);
|
|
|
dc8c34 |
- mod.mod_type = (char *)type_nsds5ReplicaCleanRUVnotified;
|
|
|
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 |
-
|
|
|
dc8c34 |
- slapi_modify_internal_set_pb_ext (pb, ra->dn, mods, NULL, NULL,
|
|
|
dc8c34 |
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
|
|
|
dc8c34 |
- slapi_modify_internal_pb (pb);
|
|
|
dc8c34 |
- slapi_pblock_destroy(pb);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- return rc;
|
|
|
dc8c34 |
-}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
-void
|
|
|
dc8c34 |
-agmt_set_cleanruv_notified_from_entry(Repl_Agmt *ra, Slapi_Entry *e){
|
|
|
dc8c34 |
- char **attr_vals = NULL;
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Lock(ra->lock);
|
|
|
dc8c34 |
- attr_vals = slapi_entry_attr_get_charray(e, type_nsds5ReplicaCleanRUVnotified);
|
|
|
dc8c34 |
- if(attr_vals){
|
|
|
dc8c34 |
- for (i = 0; i < CLEANRIDSIZ && attr_vals[i]; i++){
|
|
|
dc8c34 |
- ra->cleanruv_notified[i] = atoi(attr_vals[i]);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if( i < CLEANRIDSIZ )
|
|
|
dc8c34 |
- ra->cleanruv_notified[i + 1] = 0;
|
|
|
dc8c34 |
- slapi_ch_array_free(attr_vals);
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- ra->cleanruv_notified[0] = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- PR_Unlock(ra->lock);
|
|
|
dc8c34 |
-}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/* this is called whenever an update (total/incremental)
|
|
|
dc8c34 |
is completed */
|
|
|
dc8c34 |
void
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
|
|
|
dc8c34 |
index 537cfd8..70f71a8 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
|
|
|
dc8c34 |
@@ -248,7 +248,12 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
|
|
|
dc8c34 |
/* we don't allow delete attribute operations unless it was issued by
|
|
|
dc8c34 |
the replication plugin - handled above */
|
|
|
dc8c34 |
if (mods[i]->mod_op & LDAP_MOD_DELETE)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ if(strcasecmp (mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified) == 0){
|
|
|
dc8c34 |
+ /* allow the deletion of cleanallruv agmt attr */
|
|
|
dc8c34 |
+ continue;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
|
|
|
dc8c34 |
"deletion of %s attribute is not allowed\n", type_nsds5ReplicaInitialize);
|
|
|
dc8c34 |
*returncode = LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
@@ -508,10 +513,6 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified))
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- agmt_set_cleanruv_notified_from_entry(agmt, e);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c
|
|
|
dc8c34 |
index 51a2bc5..5efd0e6 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5_connection.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5_connection.c
|
|
|
dc8c34 |
@@ -1760,6 +1760,12 @@ bind_method_to_mech(int bindmethod)
|
|
|
dc8c34 |
return LDAP_SASL_SIMPLE;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+const char*
|
|
|
dc8c34 |
+conn_get_bindmethod(Repl_Connection *conn)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ return (bind_method_to_mech(conn->bindmethod));
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Check the result of an ldap BIND operation to see we it
|
|
|
dc8c34 |
* contains the expiration controls
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c
|
|
|
dc8c34 |
index 7a80c6f..a0f02fe 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5_init.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5_init.c
|
|
|
dc8c34 |
@@ -123,7 +123,7 @@ static char *cleanruv_oid_list[] = {
|
|
|
dc8c34 |
NULL
|
|
|
dc8c34 |
};
|
|
|
dc8c34 |
static char *cleanruv_name_list[] = {
|
|
|
dc8c34 |
- NSDS_REPL_NAME_PREFIX " Cleanruv",
|
|
|
dc8c34 |
+ NSDS_REPL_NAME_PREFIX " CleanAllRUV",
|
|
|
dc8c34 |
NULL
|
|
|
dc8c34 |
};
|
|
|
dc8c34 |
static char *cleanruv_abort_oid_list[] = {
|
|
|
dc8c34 |
@@ -131,9 +131,26 @@ static char *cleanruv_abort_oid_list[] = {
|
|
|
dc8c34 |
NULL
|
|
|
dc8c34 |
};
|
|
|
dc8c34 |
static char *cleanruv_abort_name_list[] = {
|
|
|
dc8c34 |
- NSDS_REPL_NAME_PREFIX " Cleanruv Abort",
|
|
|
dc8c34 |
+ NSDS_REPL_NAME_PREFIX " CleanAllRUV Abort",
|
|
|
dc8c34 |
NULL
|
|
|
dc8c34 |
};
|
|
|
dc8c34 |
+static char *cleanruv_maxcsn_oid_list[] = {
|
|
|
dc8c34 |
+ REPL_CLEANRUV_GET_MAXCSN_OID,
|
|
|
dc8c34 |
+ NULL
|
|
|
dc8c34 |
+};
|
|
|
dc8c34 |
+static char *cleanruv_maxcsn_name_list[] = {
|
|
|
dc8c34 |
+ NSDS_REPL_NAME_PREFIX " CleanAllRUV Retrieve MaxCSN",
|
|
|
dc8c34 |
+ NULL
|
|
|
dc8c34 |
+};
|
|
|
dc8c34 |
+static char *cleanruv_status_oid_list[] = {
|
|
|
dc8c34 |
+ REPL_CLEANRUV_CHECK_STATUS_OID,
|
|
|
dc8c34 |
+ NULL
|
|
|
dc8c34 |
+};
|
|
|
dc8c34 |
+static char *cleanruv_status_name_list[] = {
|
|
|
dc8c34 |
+ NSDS_REPL_NAME_PREFIX " CleanAllRUV Check Status",
|
|
|
dc8c34 |
+ NULL
|
|
|
dc8c34 |
+};
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* List of plugin identities for every plugin registered. Plugin identity
|
|
|
dc8c34 |
is passed by the server in the plugin init function and must be supplied
|
|
|
dc8c34 |
@@ -403,6 +420,52 @@ multimaster_end_extop_init( Slapi_PBlock *pb )
|
|
|
dc8c34 |
return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+multimaster_cleanruv_maxcsn_extop_init( Slapi_PBlock *pb )
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ int rc= 0; /* OK */
|
|
|
dc8c34 |
+ void *identity = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* get plugin identity and store it to pass to internal operations */
|
|
|
dc8c34 |
+ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);
|
|
|
dc8c34 |
+ PR_ASSERT (identity);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterextopdesc ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, (void *)cleanruv_maxcsn_oid_list ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, (void *)cleanruv_maxcsn_name_list ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)multimaster_extop_cleanruv_get_maxcsn ))
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_cleanruv_extop_init failed\n" );
|
|
|
dc8c34 |
+ rc= -1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+multimaster_cleanruv_status_extop_init( Slapi_PBlock *pb )
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ int rc= 0; /* OK */
|
|
|
dc8c34 |
+ void *identity = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* get plugin identity and store it to pass to internal operations */
|
|
|
dc8c34 |
+ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);
|
|
|
dc8c34 |
+ PR_ASSERT (identity);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterextopdesc ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, (void *)cleanruv_status_oid_list ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, (void *)cleanruv_status_name_list ) != 0 ||
|
|
|
dc8c34 |
+ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)multimaster_extop_cleanruv_check_status ))
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_cleanruv_extop_init failed\n" );
|
|
|
dc8c34 |
+ rc= -1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
multimaster_total_extop_init( Slapi_PBlock *pb )
|
|
|
dc8c34 |
@@ -679,6 +742,8 @@ int replication_multimaster_plugin_init(Slapi_PBlock *pb)
|
|
|
dc8c34 |
rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_response_extop_init", multimaster_response_extop_init, "Multimaster replication extended response plugin", NULL, identity);
|
|
|
dc8c34 |
rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_extop_init", multimaster_cleanruv_extop_init, "Multimaster replication cleanruv extended operation plugin", NULL, identity);
|
|
|
dc8c34 |
rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_abort_extop_init", multimaster_cleanruv_abort_extop_init, "Multimaster replication cleanruv abort extended operation plugin", NULL, identity);
|
|
|
dc8c34 |
+ rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_maxcsn_extop_init", multimaster_cleanruv_maxcsn_extop_init, "Multimaster replication cleanruv maxcsn extended operation plugin", NULL, identity);
|
|
|
dc8c34 |
+ rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_status_extop_init", multimaster_cleanruv_status_extop_init, "Multimaster replication cleanruv status extended operation plugin", NULL, identity);
|
|
|
dc8c34 |
if (0 == rc)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
multimaster_initialised = 1;
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
|
|
|
dc8c34 |
index 2b1d958..b3df831 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5_replica.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5_replica.c
|
|
|
dc8c34 |
@@ -88,7 +88,6 @@ struct replica {
|
|
|
dc8c34 |
PRBool state_update_inprogress; /* replica state is being updated */
|
|
|
dc8c34 |
PRLock *agmt_lock; /* protects agreement creation, start and stop */
|
|
|
dc8c34 |
char *locking_purl; /* supplier who has exclusive access */
|
|
|
dc8c34 |
- char *repl_cleanruv_data[CLEANRIDSIZ + 1];
|
|
|
dc8c34 |
};
|
|
|
dc8c34 |
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -310,7 +309,6 @@ replica_destroy(void **arg)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Replica *r;
|
|
|
dc8c34 |
void *repl_name;
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (arg == NULL)
|
|
|
dc8c34 |
return;
|
|
|
dc8c34 |
@@ -397,10 +395,6 @@ replica_destroy(void **arg)
|
|
|
dc8c34 |
csnplFree(&r->min_csn_pl);;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- for(i = 0;r->repl_cleanruv_data[i] != NULL; i++){
|
|
|
dc8c34 |
- slapi_ch_free_string(&r->repl_cleanruv_data[i]);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
slapi_ch_free((void **)arg);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1502,7 +1496,7 @@ int replica_check_for_data_reload (Replica *r, void *arg)
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_check_for_data_reload: "
|
|
|
dc8c34 |
"Warning: for replica %s there were some differences between the changelog max RUV and the "
|
|
|
dc8c34 |
"database RUV. If there are obsolete elements in the database RUV, you "
|
|
|
dc8c34 |
- "should remove them using CLEANRUV task. If they are not obsolete, "
|
|
|
dc8c34 |
+ "should remove them using the CLEANALLRUV task. If they are not obsolete, "
|
|
|
dc8c34 |
"you should check their status to see why there are no changes from those "
|
|
|
dc8c34 |
"servers in the changelog.\n",
|
|
|
dc8c34 |
slapi_sdn_get_dn(r->repl_root));
|
|
|
dc8c34 |
@@ -1819,12 +1813,13 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
|
|
|
dc8c34 |
PRThread *thread = NULL;
|
|
|
dc8c34 |
struct berval *payload = NULL;
|
|
|
dc8c34 |
CSN *maxcsn = NULL;
|
|
|
dc8c34 |
- char *csnpart;
|
|
|
dc8c34 |
- char *iter;
|
|
|
dc8c34 |
+ ReplicaId rid;
|
|
|
dc8c34 |
char csnstr[CSN_STRSIZE];
|
|
|
dc8c34 |
- char *ridstr;
|
|
|
dc8c34 |
char *token = NULL;
|
|
|
dc8c34 |
- ReplicaId rid;
|
|
|
dc8c34 |
+ char *forcing;
|
|
|
dc8c34 |
+ char *csnpart;
|
|
|
dc8c34 |
+ char *ridstr;
|
|
|
dc8c34 |
+ char *iter;
|
|
|
dc8c34 |
int i;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
for(i = 0; i < CLEANRIDSIZ && clean_vals[i]; i++){
|
|
|
dc8c34 |
@@ -1833,7 +1828,6 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Set the cleanruv data, and add the cleaned rid
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- r->repl_cleanruv_data[i] = slapi_ch_strdup(clean_vals[i]);
|
|
|
dc8c34 |
token = ldap_utf8strtok_r(clean_vals[i], ":", &iter);
|
|
|
dc8c34 |
if(token){
|
|
|
dc8c34 |
rid = atoi(token);
|
|
|
dc8c34 |
@@ -1851,15 +1845,18 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
|
|
|
dc8c34 |
maxcsn = csn_new();
|
|
|
dc8c34 |
csn_init_by_string(maxcsn, csnpart);
|
|
|
dc8c34 |
csn_as_string(maxcsn, PR_FALSE, csnstr);
|
|
|
dc8c34 |
- add_cleaned_rid(rid, r, csnstr);
|
|
|
dc8c34 |
+ forcing = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
+ if(forcing == NULL){
|
|
|
dc8c34 |
+ forcing = "no";
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: cleanAllRUV task found, "
|
|
|
dc8c34 |
"resuming the cleaning of rid(%d)...\n", rid);
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Create payload
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- ridstr = slapi_ch_smprintf("%d:%s:%s", rid, slapi_sdn_get_dn(replica_get_root(r)), csnstr);
|
|
|
dc8c34 |
- payload = create_ruv_payload(ridstr);
|
|
|
dc8c34 |
+ ridstr = slapi_ch_smprintf("%d:%s:%s:%s", rid, slapi_sdn_get_dn(replica_get_root(r)), csnstr, forcing);
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(ridstr);
|
|
|
dc8c34 |
slapi_ch_free_string(&ridstr);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if(payload == NULL){
|
|
|
dc8c34 |
@@ -1882,8 +1879,10 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
|
|
|
dc8c34 |
data->rid = rid;
|
|
|
dc8c34 |
data->task = NULL;
|
|
|
dc8c34 |
data->maxcsn = maxcsn;
|
|
|
dc8c34 |
- data->sdn = slapi_sdn_dup(r->repl_root);
|
|
|
dc8c34 |
data->payload = payload;
|
|
|
dc8c34 |
+ data->sdn = slapi_sdn_dup(r->repl_root);
|
|
|
dc8c34 |
+ data->force = slapi_ch_strdup(forcing);
|
|
|
dc8c34 |
+ data->repl_root = NULL;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread_ext,
|
|
|
dc8c34 |
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
|
|
dc8c34 |
@@ -1895,11 +1894,11 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
|
|
|
dc8c34 |
csn_free(&maxcsn);
|
|
|
dc8c34 |
slapi_sdn_free(&data->sdn);
|
|
|
dc8c34 |
ber_bvfree(data->payload);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->force);
|
|
|
dc8c34 |
slapi_ch_free((void **)&data);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- r->repl_cleanruv_data[i] = NULL;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
done:
|
|
|
dc8c34 |
slapi_ch_array_free(clean_vals);
|
|
|
dc8c34 |
@@ -1909,13 +1908,12 @@ done:
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
PRThread *thread = NULL;
|
|
|
dc8c34 |
struct berval *payload;
|
|
|
dc8c34 |
- CSN *maxcsn = NULL;
|
|
|
dc8c34 |
- char *iter;
|
|
|
dc8c34 |
+ ReplicaId rid;
|
|
|
dc8c34 |
+ char *certify = NULL;
|
|
|
dc8c34 |
char *ridstr = NULL;
|
|
|
dc8c34 |
- char *repl_root;
|
|
|
dc8c34 |
char *token = NULL;
|
|
|
dc8c34 |
- char *certify = NULL;
|
|
|
dc8c34 |
- ReplicaId rid;
|
|
|
dc8c34 |
+ char *repl_root;
|
|
|
dc8c34 |
+ char *iter;
|
|
|
dc8c34 |
int i;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
for(i = 0; clean_vals[i]; i++){
|
|
|
dc8c34 |
@@ -1926,21 +1924,27 @@ done:
|
|
|
dc8c34 |
rid = atoi(token);
|
|
|
dc8c34 |
if(rid <= 0 || rid >= READ_ONLY_REPLICA_ID){
|
|
|
dc8c34 |
slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: invalid replica id(%d) "
|
|
|
dc8c34 |
- "aborting task.\n", rid);
|
|
|
dc8c34 |
+ "aborting abort task.\n", rid);
|
|
|
dc8c34 |
goto done2;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: unable to parse cleanallruv "
|
|
|
dc8c34 |
- "data (%s), aborting task.\n",clean_vals[i]);
|
|
|
dc8c34 |
+ "data (%s), aborting abort task.\n",clean_vals[i]);
|
|
|
dc8c34 |
goto done2;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
repl_root = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
certify = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if(!is_cleaned_rid(rid)){
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: replica id(%d) is not "
|
|
|
dc8c34 |
+ "being cleaned, nothing to abort. Aborting abort task.\n", rid);
|
|
|
dc8c34 |
+ delete_aborted_rid(r, rid, repl_root, 0);
|
|
|
dc8c34 |
+ goto done2;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ add_aborted_rid(rid, r, repl_root);
|
|
|
dc8c34 |
stop_ruv_cleaning();
|
|
|
dc8c34 |
- maxcsn = replica_get_cleanruv_maxcsn(r, rid);
|
|
|
dc8c34 |
- delete_cleaned_rid(r, rid, maxcsn);
|
|
|
dc8c34 |
- csn_free(&maxcsn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: abort task found, "
|
|
|
dc8c34 |
"resuming abort of rid(%d).\n", rid);
|
|
|
dc8c34 |
@@ -1951,8 +1955,8 @@ done:
|
|
|
dc8c34 |
if (data == NULL) {
|
|
|
dc8c34 |
slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to allocate cleanruv_data.\n");
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
- ridstr = slapi_ch_smprintf("%d:%s", rid, repl_root);
|
|
|
dc8c34 |
- payload = create_ruv_payload(ridstr);
|
|
|
dc8c34 |
+ ridstr = slapi_ch_smprintf("%d:%s:%s", rid, repl_root, certify);
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(ridstr);
|
|
|
dc8c34 |
slapi_ch_free_string(&ridstr);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if(payload == NULL){
|
|
|
dc8c34 |
@@ -2583,7 +2587,7 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods
|
|
|
dc8c34 |
must use the CLEANRUV task instead */
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
|
|
|
dc8c34 |
"replica_ruv_smods_for_op: attempted to directly modify the tombstone RUV "
|
|
|
dc8c34 |
- "entry [%s] - use the CLEANRUV task instead\n",
|
|
|
dc8c34 |
+ "entry [%s] - use the CLEANALLRUV task instead\n",
|
|
|
dc8c34 |
slapi_entry_get_dn_const(target_entry));
|
|
|
dc8c34 |
return (-1);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -3430,7 +3434,7 @@ replica_replace_ruv_tombstone(Replica *r)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (rc != LDAP_SUCCESS)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- if ((rc != LDAP_NO_SUCH_OBJECT) || !replica_is_state_flag_set(r, REPLICA_IN_USE))
|
|
|
dc8c34 |
+ if ((rc != LDAP_NO_SUCH_OBJECT && rc != LDAP_TYPE_OR_VALUE_EXISTS) || !replica_is_state_flag_set(r, REPLICA_IN_USE))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_replace_ruv_tombstone: "
|
|
|
dc8c34 |
"failed to update replication update vector for replica %s: LDAP "
|
|
|
dc8c34 |
@@ -3794,69 +3798,3 @@ replica_get_attr ( Slapi_PBlock *pb, const char* type, void *value )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
-void
|
|
|
dc8c34 |
-replica_add_cleanruv_data(Replica *r, char *val)
|
|
|
dc8c34 |
-{
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Lock(r->repl_lock);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- for (i = 0; i < CLEANRIDSIZ && r->repl_cleanruv_data[i] != NULL; i++); /* goto the end of the list */
|
|
|
dc8c34 |
- if( i < CLEANRIDSIZ){
|
|
|
dc8c34 |
- r->repl_cleanruv_data[i] = slapi_ch_strdup(val); /* append to list */
|
|
|
dc8c34 |
- r->repl_cleanruv_data[i + 1] = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Unlock(r->repl_lock);
|
|
|
dc8c34 |
-}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
-void
|
|
|
dc8c34 |
-replica_remove_cleanruv_data(Replica *r, char *val)
|
|
|
dc8c34 |
-{
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Lock(r->repl_lock);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- for(i = 0; i < CLEANRIDSIZ && r->repl_cleanruv_data[i] && strcmp(r->repl_cleanruv_data[i], val) != 0; i++);
|
|
|
dc8c34 |
- if( i < CLEANRIDSIZ ){
|
|
|
dc8c34 |
- slapi_ch_free_string(&r->repl_cleanruv_data[i]);
|
|
|
dc8c34 |
- for(; i < CLEANRIDSIZ; i++){
|
|
|
dc8c34 |
- /* rewrite entire array */
|
|
|
dc8c34 |
- r->repl_cleanruv_data[i] = r->repl_cleanruv_data[i + 1];
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Unlock(r->repl_lock);
|
|
|
dc8c34 |
-}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
-CSN *
|
|
|
dc8c34 |
-replica_get_cleanruv_maxcsn(Replica *r, ReplicaId rid)
|
|
|
dc8c34 |
-{
|
|
|
dc8c34 |
- CSN *newcsn;
|
|
|
dc8c34 |
- char *csnstr;
|
|
|
dc8c34 |
- char *token;
|
|
|
dc8c34 |
- char *iter;
|
|
|
dc8c34 |
- int repl_rid = 0;
|
|
|
dc8c34 |
- int i;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Lock(r->repl_lock);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- for(i = 0; i < CLEANRIDSIZ && r->repl_cleanruv_data[i]; i++){
|
|
|
dc8c34 |
- token = ldap_utf8strtok_r(r->repl_cleanruv_data[i], ":", &iter);
|
|
|
dc8c34 |
- if(token){
|
|
|
dc8c34 |
- repl_rid = atoi(token);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- csnstr = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
- if(repl_rid == rid){
|
|
|
dc8c34 |
- newcsn = csn_new();
|
|
|
dc8c34 |
- csn_init_by_string(newcsn, csnstr);
|
|
|
dc8c34 |
- PR_Unlock(r->repl_lock);
|
|
|
dc8c34 |
- return newcsn;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- PR_Unlock(r->repl_lock);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- return NULL;
|
|
|
dc8c34 |
-}
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
|
|
|
dc8c34 |
index c5ca965..0fd785b 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
|
|
|
dc8c34 |
@@ -64,6 +64,7 @@
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int slapi_log_urp = SLAPI_LOG_REPL;
|
|
|
dc8c34 |
static ReplicaId cleaned_rids[CLEANRIDSIZ + 1] = {0};
|
|
|
dc8c34 |
+static ReplicaId pre_cleaned_rids[CLEANRIDSIZ + 1] = {0};
|
|
|
dc8c34 |
static ReplicaId aborted_rids[CLEANRIDSIZ + 1] = {0};
|
|
|
dc8c34 |
static Slapi_RWLock *rid_lock = NULL;
|
|
|
dc8c34 |
static Slapi_RWLock *abort_rid_lock = NULL;
|
|
|
dc8c34 |
@@ -84,20 +85,27 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt
|
|
|
dc8c34 |
static int replica_execute_cl2ldif_task (Object *r, char *returntext);
|
|
|
dc8c34 |
static int replica_execute_ldif2cl_task (Object *r, char *returntext);
|
|
|
dc8c34 |
static int replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext);
|
|
|
dc8c34 |
-static int replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, char *returntext);
|
|
|
dc8c34 |
+static int replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, const char *force_cleaning, char *returntext);
|
|
|
dc8c34 |
static void replica_cleanallruv_thread(void *arg);
|
|
|
dc8c34 |
-static void replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task);
|
|
|
dc8c34 |
+static void replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data);
|
|
|
dc8c34 |
static int check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task);
|
|
|
dc8c34 |
-static int check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_Task *task);
|
|
|
dc8c34 |
-static int replica_cleanallruv_send_extop(Repl_Agmt *ra, ReplicaId rid, Slapi_Task *task, struct berval *payload, int check_result);
|
|
|
dc8c34 |
+static int check_agmts_are_caught_up(cleanruv_data *data, char *maxcsn);
|
|
|
dc8c34 |
+static int replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *data, int check_result);
|
|
|
dc8c34 |
static int replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, struct berval *payload);
|
|
|
dc8c34 |
-static int replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *rid_text, char *maxcsn, Slapi_Task *task);
|
|
|
dc8c34 |
+static int replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *basedn, char *rid_text, char *maxcsn, Slapi_Task *task);
|
|
|
dc8c34 |
static int replica_cleanallruv_replica_alive(Repl_Agmt *agmt);
|
|
|
dc8c34 |
-static int replica_cleanallruv_check_ruv(Repl_Agmt *ra, char *rid_text, Slapi_Task *task);
|
|
|
dc8c34 |
+static int replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *ra, char *rid_text, Slapi_Task *task);
|
|
|
dc8c34 |
static int get_cleanruv_task_count();
|
|
|
dc8c34 |
static int get_abort_cleanruv_task_count();
|
|
|
dc8c34 |
static int replica_cleanup_task (Object *r, const char *task_name, char *returntext, int apply_mods);
|
|
|
dc8c34 |
static int replica_task_done(Replica *replica);
|
|
|
dc8c34 |
+static void delete_cleaned_rid_config(cleanruv_data *data);
|
|
|
dc8c34 |
+static int replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task);
|
|
|
dc8c34 |
+static void check_replicas_are_done_cleaning(cleanruv_data *data);
|
|
|
dc8c34 |
+static void check_replicas_are_done_aborting(cleanruv_data *data );
|
|
|
dc8c34 |
+static CSN* replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn);
|
|
|
dc8c34 |
+static int replica_cleanallruv_get_replica_maxcsn(Repl_Agmt *agmt, char *rid_text, char *basedn, CSN **csn);
|
|
|
dc8c34 |
+static void preset_cleaned_rid(ReplicaId rid);
|
|
|
dc8c34 |
static multimaster_mtnode_extension * _replica_config_get_mtnode_ext (const Slapi_Entry *e);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -385,6 +393,12 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
|
|
|
dc8c34 |
if (apply_mods)
|
|
|
dc8c34 |
replica_set_legacy_consumer (r, PR_FALSE);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ else if (strcasecmp (config_attr, type_replicaCleanRUV) == 0 ||
|
|
|
dc8c34 |
+ strcasecmp (config_attr, type_replicaAbortCleanRUV) == 0)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ /* only allow the deletion of the cleanAllRUV config attributes */
|
|
|
dc8c34 |
+ continue;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
*returncode = LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
@@ -891,7 +905,7 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt
|
|
|
dc8c34 |
if (apply_mods)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_Task *empty_task = NULL;
|
|
|
dc8c34 |
- return replica_execute_cleanall_ruv_task(r, (ReplicaId)temprid, empty_task, returntext);
|
|
|
dc8c34 |
+ return replica_execute_cleanall_ruv_task(r, (ReplicaId)temprid, empty_task, returntext, "no");
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
return LDAP_SUCCESS;
|
|
|
dc8c34 |
@@ -1225,35 +1239,52 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
|
|
|
dc8c34 |
Slapi_Task *task = NULL;
|
|
|
dc8c34 |
const Slapi_DN *task_dn;
|
|
|
dc8c34 |
Slapi_DN *dn = NULL;
|
|
|
dc8c34 |
+ ReplicaId rid;
|
|
|
dc8c34 |
Object *r;
|
|
|
dc8c34 |
+ const char *force_cleaning;
|
|
|
dc8c34 |
const char *base_dn;
|
|
|
dc8c34 |
const char *rid_str;
|
|
|
dc8c34 |
- ReplicaId rid;
|
|
|
dc8c34 |
int rc = SLAPI_DSE_CALLBACK_OK;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* allocate new task now */
|
|
|
dc8c34 |
task = slapi_new_task(slapi_entry_get_ndn(e));
|
|
|
dc8c34 |
+ task_dn = slapi_entry_get_sdn(e);
|
|
|
dc8c34 |
if(task == NULL){
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Failed to create new task\n");
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Get our task settings
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if ((base_dn = fetch_attr(e, "replica-base-dn", 0)) == NULL){
|
|
|
dc8c34 |
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing replica-base-dn attribute");
|
|
|
dc8c34 |
+ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if ((rid_str = fetch_attr(e, "replica-id", 0)) == NULL){
|
|
|
dc8c34 |
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing replica-id attribute");
|
|
|
dc8c34 |
+ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- task_dn = slapi_entry_get_sdn(e);
|
|
|
dc8c34 |
+ if ((force_cleaning = fetch_attr(e, "replica-force-cleaning", 0)) != NULL){
|
|
|
dc8c34 |
+ if(strcasecmp(force_cleaning,"yes") != 0 && strcasecmp(force_cleaning,"no") != 0){
|
|
|
dc8c34 |
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid value for replica-force-cleaning "
|
|
|
dc8c34 |
+ "(%s). Value must be \"yes\" or \"no\" for task - (%s)",
|
|
|
dc8c34 |
+ force_cleaning, slapi_sdn_get_dn(task_dn));
|
|
|
dc8c34 |
+ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
+ *returncode = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
+ goto out;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ force_cleaning = "no";
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Check the rid
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -1266,6 +1297,14 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ if(is_cleaned_rid(rid)){
|
|
|
dc8c34 |
+ /* we are already cleaning this rid */
|
|
|
dc8c34 |
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replica id (%d) is already being cleaned", rid);
|
|
|
dc8c34 |
+ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
+ goto out;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Get the replica object
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -1279,7 +1318,7 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* clean the RUV's */
|
|
|
dc8c34 |
- rc = replica_execute_cleanall_ruv_task (r, rid, task, returntext);
|
|
|
dc8c34 |
+ rc = replica_execute_cleanall_ruv_task (r, rid, task, force_cleaning, returntext);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
out:
|
|
|
dc8c34 |
if(rc){
|
|
|
dc8c34 |
@@ -1302,31 +1341,36 @@ out:
|
|
|
dc8c34 |
*
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
-replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, char *returntext)
|
|
|
dc8c34 |
+replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, const char* force_cleaning, char *returntext)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- PRThread *thread = NULL;
|
|
|
dc8c34 |
+ struct berval *payload = NULL;
|
|
|
dc8c34 |
Slapi_Task *pre_task = NULL; /* this is supposed to be null for logging */
|
|
|
dc8c34 |
- Replica *replica;
|
|
|
dc8c34 |
- Object *ruv_obj;
|
|
|
dc8c34 |
cleanruv_data *data = NULL;
|
|
|
dc8c34 |
+ PRThread *thread = NULL;
|
|
|
dc8c34 |
CSN *maxcsn = NULL;
|
|
|
dc8c34 |
- const RUV *ruv;
|
|
|
dc8c34 |
- struct berval *payload = NULL;
|
|
|
dc8c34 |
- char *ridstr = NULL;
|
|
|
dc8c34 |
+ Replica *replica;
|
|
|
dc8c34 |
char csnstr[CSN_STRSIZE];
|
|
|
dc8c34 |
+ char *ridstr = NULL;
|
|
|
dc8c34 |
+ char *basedn = NULL;
|
|
|
dc8c34 |
int rc = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ cleanruv_log(pre_task, CLEANALLRUV_ID,"Initiating CleanAllRUV Task...");
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
if(get_cleanruv_task_count() >= CLEANRIDSIZ){
|
|
|
dc8c34 |
/* we are already running the maximum number of tasks */
|
|
|
dc8c34 |
cleanruv_log(pre_task, CLEANALLRUV_ID,
|
|
|
dc8c34 |
"Exceeded maximum number of active CLEANALLRUV tasks(%d)",CLEANRIDSIZ);
|
|
|
dc8c34 |
return LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Grab the replica
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- replica = (Replica*)object_get_data (r);
|
|
|
dc8c34 |
+ if(r){
|
|
|
dc8c34 |
+ replica = (Replica*)object_get_data (r);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ cleanruv_log(pre_task, CLEANALLRUV_ID, "Replica object is NULL, aborting task");
|
|
|
dc8c34 |
+ return -1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Check if this is a consumer
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -1342,32 +1386,25 @@ replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, c
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Grab the max csn of the deleted replica
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- ruv_obj = replica_get_ruv(replica);
|
|
|
dc8c34 |
- ruv = object_get_data (ruv_obj);
|
|
|
dc8c34 |
- if(ruv_get_rid_max_csn(ruv, &maxcsn, rid) == RUV_BAD_DATA){
|
|
|
dc8c34 |
- /* no maxcsn, can not proceed */
|
|
|
dc8c34 |
- cleanruv_log(pre_task, CLEANALLRUV_ID, "Could not find maxcsn for rid (%d)", rid);
|
|
|
dc8c34 |
- rc = -1;
|
|
|
dc8c34 |
- object_release(ruv_obj);
|
|
|
dc8c34 |
- goto fail;
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- object_release(ruv_obj);
|
|
|
dc8c34 |
- if(maxcsn == NULL || csn_get_replicaid(maxcsn) == 0){
|
|
|
dc8c34 |
- /*
|
|
|
dc8c34 |
- * This is for consistency with extop csn creation, where
|
|
|
dc8c34 |
- * we want the csn string to be "0000000000000000000" not ""
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
- csn_free(&maxcsn);
|
|
|
dc8c34 |
- maxcsn = csn_new();
|
|
|
dc8c34 |
- csn_init_by_string(maxcsn, "");
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- csn_as_string(maxcsn, PR_FALSE, csnstr);
|
|
|
dc8c34 |
+ cleanruv_log(pre_task, CLEANALLRUV_ID, "Retrieving maxcsn...");
|
|
|
dc8c34 |
+ basedn = (char *)slapi_sdn_get_dn(replica_get_root(replica));
|
|
|
dc8c34 |
+ maxcsn = replica_cleanallruv_find_maxcsn(replica, rid, basedn);
|
|
|
dc8c34 |
+ if(maxcsn == NULL || csn_get_replicaid(maxcsn) == 0){
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * This is for consistency with extop csn creation, where
|
|
|
dc8c34 |
+ * we want the csn string to be "0000000000000000000" not ""
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ csn_free(&maxcsn);
|
|
|
dc8c34 |
+ maxcsn = csn_new();
|
|
|
dc8c34 |
+ csn_init_by_string(maxcsn, "");
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ csn_as_string(maxcsn, PR_FALSE, csnstr);
|
|
|
dc8c34 |
+ cleanruv_log(pre_task, CLEANALLRUV_ID, "Found maxcsn (%s)",csnstr);
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Create payload
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- ridstr = slapi_ch_smprintf("%d:%s:%s", rid, slapi_sdn_get_dn(replica_get_root(replica)), csnstr);
|
|
|
dc8c34 |
- payload = create_ruv_payload(ridstr);
|
|
|
dc8c34 |
+ ridstr = slapi_ch_smprintf("%d:%s:%s:%s", rid, basedn, csnstr, force_cleaning);
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(ridstr);
|
|
|
dc8c34 |
slapi_ch_free_string(&ridstr);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if(payload == NULL){
|
|
|
dc8c34 |
@@ -1389,15 +1426,19 @@ replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, c
|
|
|
dc8c34 |
data->replica = replica;
|
|
|
dc8c34 |
data->rid = rid;
|
|
|
dc8c34 |
data->task = task;
|
|
|
dc8c34 |
- data->maxcsn = maxcsn;
|
|
|
dc8c34 |
data->payload = payload;
|
|
|
dc8c34 |
data->sdn = NULL;
|
|
|
dc8c34 |
+ data->maxcsn = maxcsn;
|
|
|
dc8c34 |
+ data->repl_root = slapi_ch_strdup(basedn);
|
|
|
dc8c34 |
+ data->force = slapi_ch_strdup(force_cleaning);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread,
|
|
|
dc8c34 |
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
|
|
dc8c34 |
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
|
|
|
dc8c34 |
if (thread == NULL) {
|
|
|
dc8c34 |
rc = -1;
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->force);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->repl_root);
|
|
|
dc8c34 |
goto fail;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
goto done;
|
|
|
dc8c34 |
@@ -1441,11 +1482,11 @@ replica_cleanallruv_thread_ext(void *arg)
|
|
|
dc8c34 |
static void
|
|
|
dc8c34 |
replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- Object *ruv_obj = NULL;
|
|
|
dc8c34 |
+ cleanruv_data *data = arg;
|
|
|
dc8c34 |
Object *agmt_obj = NULL;
|
|
|
dc8c34 |
+ Object *ruv_obj = NULL;
|
|
|
dc8c34 |
Repl_Agmt *agmt = NULL;
|
|
|
dc8c34 |
RUV *ruv = NULL;
|
|
|
dc8c34 |
- cleanruv_data *data = arg;
|
|
|
dc8c34 |
char csnstr[CSN_STRSIZE];
|
|
|
dc8c34 |
char *returntext = NULL;
|
|
|
dc8c34 |
char *rid_text = NULL;
|
|
|
dc8c34 |
@@ -1466,7 +1507,7 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
* the backends might not be online yet.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
PR_Lock( notify_lock );
|
|
|
dc8c34 |
- PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(5) );
|
|
|
dc8c34 |
+ PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(10) );
|
|
|
dc8c34 |
PR_Unlock( notify_lock );
|
|
|
dc8c34 |
data->repl_obj = replica_get_replica_from_dn(data->sdn);
|
|
|
dc8c34 |
if(data->repl_obj == NULL){
|
|
|
dc8c34 |
@@ -1488,17 +1529,25 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
aborted = 1;
|
|
|
dc8c34 |
goto done;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ if(data->repl_root == NULL){
|
|
|
dc8c34 |
+ /* we must have resumed from start up, fill in the repl root */
|
|
|
dc8c34 |
+ data->repl_root = slapi_ch_strdup(slapi_sdn_get_dn(replica_get_root(data->replica)));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
if(data->task){
|
|
|
dc8c34 |
slapi_task_begin(data->task, 1);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- rid_text = slapi_ch_smprintf("{replica %d ldap", data->rid);
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Presetting the rid prevents duplicate thread creation, but allows the db and changelog to still
|
|
|
dc8c34 |
+ * process updates from the rid. set_cleaned_rid() blocks updates, so we don't want to do that... yet.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ preset_cleaned_rid(data->rid);
|
|
|
dc8c34 |
+ rid_text = slapi_ch_smprintf("%d", data->rid);
|
|
|
dc8c34 |
csn_as_string(data->maxcsn, PR_FALSE, csnstr);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Add the cleanallruv task to the repl config - so we can handle restarts
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
+ add_cleaned_rid(data->rid, data->replica, csnstr, data->force); /* marks config that we started cleaning a rid */
|
|
|
dc8c34 |
cleanruv_log(data->task, CLEANALLRUV_ID, "Cleaning rid (%d)...", data->rid);
|
|
|
dc8c34 |
- add_cleaned_rid(data->rid, data->replica, csnstr); /* marks config that we started cleaning a rid */
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* First, wait for the maxcsn to be covered
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -1506,7 +1555,7 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
ruv_obj = replica_get_ruv(data->replica);
|
|
|
dc8c34 |
ruv = object_get_data (ruv_obj);
|
|
|
dc8c34 |
while(data->maxcsn && !is_task_aborted(data->rid) && !is_cleaned_rid(data->rid) && !slapi_is_shutting_down()){
|
|
|
dc8c34 |
- if(csn_get_replicaid(data->maxcsn) == 0 || ruv_covers_csn_cleanallruv(ruv,data->maxcsn)){
|
|
|
dc8c34 |
+ if(csn_get_replicaid(data->maxcsn) == 0 || ruv_covers_csn_cleanallruv(ruv,data->maxcsn) || strcasecmp(data->force,"yes") == 0){
|
|
|
dc8c34 |
/* We are caught up, now we can clean the ruv's */
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1517,6 +1566,8 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
object_release(ruv_obj);
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Next, make sure all the replicas are up and running before sending off the clean ruv tasks
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * Even if we are forcing the cleaning, the replicas still need to be up
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
cleanruv_log(data->task, CLEANALLRUV_ID,"Waiting for all the replicas to be online...");
|
|
|
dc8c34 |
if(check_agmts_are_alive(data->replica, data->rid, data->task)){
|
|
|
dc8c34 |
@@ -1528,7 +1579,7 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
* Make sure all the replicas have seen the max csn
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
cleanruv_log(data->task, CLEANALLRUV_ID,"Waiting for all the replicas to receive all the deleted replica updates...");
|
|
|
dc8c34 |
- if(check_agmts_are_caught_up(data->replica, data->rid, csnstr, data->task)){
|
|
|
dc8c34 |
+ if(strcasecmp(data->force,"no") == 0 && check_agmts_are_caught_up(data, csnstr)){
|
|
|
dc8c34 |
/* error, aborted or shutdown */
|
|
|
dc8c34 |
aborted = 1;
|
|
|
dc8c34 |
goto done;
|
|
|
dc8c34 |
@@ -1555,10 +1606,11 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
agmt_not_notified = 0;
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if(replica_cleanallruv_send_extop(agmt, data->rid, data->task, data->payload, 1) == 0){
|
|
|
dc8c34 |
+ if(replica_cleanallruv_send_extop(agmt, data, 1) == 0){
|
|
|
dc8c34 |
agmt_not_notified = 0;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
agmt_not_notified = 1;
|
|
|
dc8c34 |
+ cleanruv_log(data->task, CLEANALLRUV_ID, "Failed to send task to replica (%s)",agmt_get_long_name(agmt));
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj);
|
|
|
dc8c34 |
@@ -1609,10 +1661,11 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
found_dirty_rid = 0;
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if(replica_cleanallruv_check_ruv(agmt, rid_text, data->task) == 0){
|
|
|
dc8c34 |
+ if(replica_cleanallruv_check_ruv(data->repl_root, agmt, rid_text, data->task) == 0){
|
|
|
dc8c34 |
found_dirty_rid = 0;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
found_dirty_rid = 1;
|
|
|
dc8c34 |
+ cleanruv_log(data->task, CLEANALLRUV_ID,"Replica is not cleaned yet (%s)",agmt_get_long_name(agmt));
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj);
|
|
|
dc8c34 |
@@ -1623,7 +1676,7 @@ replica_cleanallruv_thread(void *arg)
|
|
|
dc8c34 |
goto done;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(found_dirty_rid == 0){
|
|
|
dc8c34 |
- break;
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* need to sleep between passes
|
|
|
dc8c34 |
@@ -1647,9 +1700,11 @@ done:
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if(!aborted){
|
|
|
dc8c34 |
trigger_cl_trimming(data->rid);
|
|
|
dc8c34 |
- delete_cleaned_rid(data->replica, data->rid, data->maxcsn);
|
|
|
dc8c34 |
+ delete_cleaned_rid_config(data);
|
|
|
dc8c34 |
+ /* make sure all the replicas have been "pre_cleaned" before finishing */
|
|
|
dc8c34 |
+ check_replicas_are_done_cleaning(data);
|
|
|
dc8c34 |
cleanruv_log(data->task, CLEANALLRUV_ID, "Successfully cleaned rid(%d).", data->rid);
|
|
|
dc8c34 |
- slapi_task_finish(data->task, rc);
|
|
|
dc8c34 |
+ remove_cleaned_rid(data->rid);
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Shutdown or abort
|
|
|
dc8c34 |
@@ -1658,29 +1713,189 @@ done:
|
|
|
dc8c34 |
cleanruv_log(data->task, CLEANALLRUV_ID,"Server shutting down. Process will resume at server startup");
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
cleanruv_log(data->task, CLEANALLRUV_ID,"Task aborted for rid(%d).",data->rid);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if(data->task){
|
|
|
dc8c34 |
- slapi_task_finish(data->task, rc);
|
|
|
dc8c34 |
+ delete_cleaned_rid_config(data);
|
|
|
dc8c34 |
+ remove_cleaned_rid(data->rid);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+ if(data->task){
|
|
|
dc8c34 |
+ slapi_task_finish(data->task, rc);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
if(data->payload){
|
|
|
dc8c34 |
ber_bvfree(data->payload);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(data->repl_obj && free_obj){
|
|
|
dc8c34 |
object_release(data->repl_obj);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ csn_free(&data->maxcsn);
|
|
|
dc8c34 |
slapi_sdn_free(&data->sdn);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->repl_root);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->force);
|
|
|
dc8c34 |
slapi_ch_free_string(&rid_text);
|
|
|
dc8c34 |
- csn_free(&data->maxcsn);
|
|
|
dc8c34 |
slapi_ch_free((void **)&data);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
+ * Loop over the agmts, and check if they are in the last phase of cleaning, meaning they have
|
|
|
dc8c34 |
+ * released cleanallruv data from the config
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+static void
|
|
|
dc8c34 |
+check_replicas_are_done_cleaning(cleanruv_data *data )
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ Object *agmt_obj;
|
|
|
dc8c34 |
+ Repl_Agmt *agmt;
|
|
|
dc8c34 |
+ char csnstr[CSN_STRSIZE];
|
|
|
dc8c34 |
+ char *filter = NULL;
|
|
|
dc8c34 |
+ int not_all_cleaned = 1;
|
|
|
dc8c34 |
+ int interval = 10;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ cleanruv_log(data->task, CLEANALLRUV_ID, "Waiting for all the replicas to finish cleaning...");
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ csn_as_string(data->maxcsn, PR_FALSE, csnstr);
|
|
|
dc8c34 |
+ filter = PR_smprintf("(%s=%d:%s:%s)", type_replicaCleanRUV,(int)data->rid, csnstr, data->force);
|
|
|
dc8c34 |
+ while(not_all_cleaned && !is_task_aborted(data->rid) && !slapi_is_shutting_down()){
|
|
|
dc8c34 |
+ agmt_obj = agmtlist_get_first_agreement_for_replica (data->replica);
|
|
|
dc8c34 |
+ if(agmt_obj == NULL){
|
|
|
dc8c34 |
+ not_all_cleaned = 0;
|
|
|
dc8c34 |
+ break;
|
|
|
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 (data->replica, agmt_obj);
|
|
|
dc8c34 |
+ not_all_cleaned = 0;
|
|
|
dc8c34 |
+ continue;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(replica_cleanallruv_is_finished(agmt, filter, data->task) == 0){
|
|
|
dc8c34 |
+ not_all_cleaned = 0;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ not_all_cleaned = 1;
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(not_all_cleaned == 0 || is_task_aborted(data->rid) ){
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ cleanruv_log(data->task, CLEANALLRUV_ID, "Not all replicas finished cleaning, retrying in %d seconds",interval);
|
|
|
dc8c34 |
+ PR_Lock( notify_lock );
|
|
|
dc8c34 |
+ PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) );
|
|
|
dc8c34 |
+ PR_Unlock( notify_lock );
|
|
|
dc8c34 |
+ if(interval < 14400){ /* 4 hour max */
|
|
|
dc8c34 |
+ interval = interval * 2;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ interval = 14400;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_ch_free_string(&filter);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * Search this replica for the nsds5ReplicaCleanruv attribute, we don't return
|
|
|
dc8c34 |
+ * an entry, we know it has finished cleaning.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+static int
|
|
|
dc8c34 |
+replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ Repl_Connection *conn = NULL;
|
|
|
dc8c34 |
+ ConnResult crc = 0;
|
|
|
dc8c34 |
+ struct berval *payload = NULL;
|
|
|
dc8c34 |
+ int msgid = 0;
|
|
|
dc8c34 |
+ int rc = -1;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if((conn = conn_new(agmt)) == NULL){
|
|
|
dc8c34 |
+ return -1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(filter);
|
|
|
dc8c34 |
+ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_CHECK_STATUS_OID, payload, NULL, &msgid);
|
|
|
dc8c34 |
+ if(crc == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
+ struct berval *retsdata = NULL;
|
|
|
dc8c34 |
+ char *retoid = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1);
|
|
|
dc8c34 |
+ if (CONN_OPERATION_SUCCESS == crc ){
|
|
|
dc8c34 |
+ char *response = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ decode_cleanruv_payload(retsdata, &response);
|
|
|
dc8c34 |
+ if(response && strcmp(response,CLEANRUV_FINISHED) == 0){
|
|
|
dc8c34 |
+ /* finished cleaning */
|
|
|
dc8c34 |
+ rc = 0;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (NULL != retsdata)
|
|
|
dc8c34 |
+ ber_bvfree(retsdata);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&response);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&retoid);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ rc = -1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
+ if(payload)
|
|
|
dc8c34 |
+ ber_bvfree(payload);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * Loop over the agmts, and check if they are in the last phase of aborting, meaning they have
|
|
|
dc8c34 |
+ * released the abort cleanallruv data from the config
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+static void
|
|
|
dc8c34 |
+check_replicas_are_done_aborting(cleanruv_data *data )
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ Object *agmt_obj;
|
|
|
dc8c34 |
+ Repl_Agmt *agmt;
|
|
|
dc8c34 |
+ char *filter = NULL;
|
|
|
dc8c34 |
+ int not_all_aborted = 1;
|
|
|
dc8c34 |
+ int interval = 10;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID,"Waiting for all the replicas to finish aborting...");
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ filter = PR_smprintf("(%s=%d:%s)", type_replicaAbortCleanRUV, data->rid, data->repl_root);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ while(not_all_aborted && !slapi_is_shutting_down()){
|
|
|
dc8c34 |
+ agmt_obj = agmtlist_get_first_agreement_for_replica (data->replica);
|
|
|
dc8c34 |
+ if(agmt_obj == NULL){
|
|
|
dc8c34 |
+ not_all_aborted = 0;
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ while (agmt_obj && !slapi_is_shutting_down()){
|
|
|
dc8c34 |
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
|
|
|
dc8c34 |
+ if(get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
|
|
|
dc8c34 |
+ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj);
|
|
|
dc8c34 |
+ not_all_aborted = 0;
|
|
|
dc8c34 |
+ continue;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(replica_cleanallruv_is_finished(agmt, filter, data->task) == 0){
|
|
|
dc8c34 |
+ not_all_aborted = 0;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ not_all_aborted = 1;
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(not_all_aborted == 0){
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Not all replicas finished aborting, retrying in %d seconds",interval);
|
|
|
dc8c34 |
+ PR_Lock( notify_lock );
|
|
|
dc8c34 |
+ PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) );
|
|
|
dc8c34 |
+ PR_Unlock( notify_lock );
|
|
|
dc8c34 |
+ if(interval < 14400){ /* 4 hour max */
|
|
|
dc8c34 |
+ interval = interval * 2;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ interval = 14400;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_ch_free_string(&filter);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
* Waits for all the repl agmts to be have have the maxcsn. Returns error only on abort or shutdown
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
-check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_Task *task)
|
|
|
dc8c34 |
+check_agmts_are_caught_up(cleanruv_data *data, char *maxcsn)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Object *agmt_obj;
|
|
|
dc8c34 |
Repl_Agmt *agmt;
|
|
|
dc8c34 |
@@ -1688,10 +1903,10 @@ check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_T
|
|
|
dc8c34 |
int not_all_caughtup = 1;
|
|
|
dc8c34 |
int interval = 10;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- rid_text = slapi_ch_smprintf("{replica %d ldap", rid);
|
|
|
dc8c34 |
+ rid_text = slapi_ch_smprintf("%d", data->rid);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- while(not_all_caughtup && !is_task_aborted(rid) && !slapi_is_shutting_down()){
|
|
|
dc8c34 |
- agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
|
|
|
dc8c34 |
+ while(not_all_caughtup && !is_task_aborted(data->rid) && !slapi_is_shutting_down()){
|
|
|
dc8c34 |
+ agmt_obj = agmtlist_get_first_agreement_for_replica (data->replica);
|
|
|
dc8c34 |
if(agmt_obj == NULL){
|
|
|
dc8c34 |
not_all_caughtup = 0;
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
@@ -1699,23 +1914,24 @@ check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_T
|
|
|
dc8c34 |
while (agmt_obj){
|
|
|
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 |
+ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj);
|
|
|
dc8c34 |
not_all_caughtup = 0;
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if(replica_cleanallruv_check_maxcsn(agmt, rid_text, maxcsn, task) == 0){
|
|
|
dc8c34 |
+ if(replica_cleanallruv_check_maxcsn(agmt, data->repl_root, rid_text, maxcsn, data->task) == 0){
|
|
|
dc8c34 |
not_all_caughtup = 0;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
not_all_caughtup = 1;
|
|
|
dc8c34 |
+ cleanruv_log(data->task, CLEANALLRUV_ID, "Replica not caught up (%s)",agmt_get_long_name(agmt));
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
|
|
|
dc8c34 |
- } /* agmt while */
|
|
|
dc8c34 |
+ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if(not_all_caughtup == 0 || is_task_aborted(rid) ){
|
|
|
dc8c34 |
+ if(not_all_caughtup == 0 || is_task_aborted(data->rid) ){
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- cleanruv_log(task, CLEANALLRUV_ID, "Not all replicas caught up, retrying in %d seconds",interval);
|
|
|
dc8c34 |
+ cleanruv_log(data->task, CLEANALLRUV_ID, "Not all replicas caught up, retrying in %d seconds",interval);
|
|
|
dc8c34 |
PR_Lock( notify_lock );
|
|
|
dc8c34 |
PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) );
|
|
|
dc8c34 |
PR_Unlock( notify_lock );
|
|
|
dc8c34 |
@@ -1728,7 +1944,7 @@ check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_T
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_ch_free_string(&rid_text);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if(is_task_aborted(rid)){
|
|
|
dc8c34 |
+ if(is_task_aborted(data->rid)){
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1763,6 +1979,7 @@ check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task)
|
|
|
dc8c34 |
not_all_alive = 0;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
not_all_alive = 1;
|
|
|
dc8c34 |
+ cleanruv_log(task, CLEANALLRUV_ID, "Replica not online (%s)",agmt_get_long_name(agmt));
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
|
|
|
dc8c34 |
@@ -1793,7 +2010,7 @@ check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task)
|
|
|
dc8c34 |
* Create the CLEANALLRUV extended op payload
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
struct berval *
|
|
|
dc8c34 |
-create_ruv_payload(char *value)
|
|
|
dc8c34 |
+create_cleanruv_payload(char *value)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
struct berval *req_data = NULL;
|
|
|
dc8c34 |
BerElement *tmp_bere = NULL;
|
|
|
dc8c34 |
@@ -1801,10 +2018,7 @@ create_ruv_payload(char *value)
|
|
|
dc8c34 |
if ((tmp_bere = der_alloc()) == NULL){
|
|
|
dc8c34 |
goto error;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (ber_printf(tmp_bere, "{s", value) == -1){
|
|
|
dc8c34 |
- goto error;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if (ber_printf(tmp_bere, "}") == -1){
|
|
|
dc8c34 |
+ if (ber_printf(tmp_bere, "{s}", value) == -1){
|
|
|
dc8c34 |
goto error;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (ber_flatten(tmp_bere, &req_data) == -1){
|
|
|
dc8c34 |
@@ -1832,7 +2046,7 @@ done:
|
|
|
dc8c34 |
* the CLEANALLRUV task.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
static void
|
|
|
dc8c34 |
-replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task)
|
|
|
dc8c34 |
+replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Repl_Connection *conn;
|
|
|
dc8c34 |
ConnResult crc = 0;
|
|
|
dc8c34 |
@@ -1859,7 +2073,7 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task)
|
|
|
dc8c34 |
conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- val.bv_len = PR_snprintf(data, sizeof(data), "CLEANRUV%d", rid);
|
|
|
dc8c34 |
+ val.bv_len = PR_snprintf(data, sizeof(data), "CLEANRUV%d", clean_data->rid);
|
|
|
dc8c34 |
sdn = agmt_get_replarea(agmt);
|
|
|
dc8c34 |
mod.mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES;
|
|
|
dc8c34 |
mod.mod_type = "nsds5task";
|
|
|
dc8c34 |
@@ -1876,7 +2090,7 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task)
|
|
|
dc8c34 |
rc = ldap_modify_ext_s( ld, repl_dn, mods, NULL, NULL);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if(rc != LDAP_SUCCESS){
|
|
|
dc8c34 |
- cleanruv_log(task, CLEANALLRUV_ID, "Failed to add CLEANRUV task replica "
|
|
|
dc8c34 |
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task 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 |
}
|
|
|
dc8c34 |
@@ -1906,6 +2120,23 @@ is_cleaned_rid(ReplicaId rid)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
+is_pre_cleaned_rid(ReplicaId rid)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ int i;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ slapi_rwlock_rdlock(rid_lock);
|
|
|
dc8c34 |
+ for(i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != 0; i++){
|
|
|
dc8c34 |
+ if(rid == pre_cleaned_rids[i]){
|
|
|
dc8c34 |
+ slapi_rwlock_unlock(rid_lock);
|
|
|
dc8c34 |
+ return 1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_rwlock_unlock(rid_lock);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return 0;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
is_task_aborted(ReplicaId rid)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
int i;
|
|
|
dc8c34 |
@@ -1924,6 +2155,22 @@ is_task_aborted(ReplicaId rid)
|
|
|
dc8c34 |
return 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+static void
|
|
|
dc8c34 |
+preset_cleaned_rid(ReplicaId rid)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ int i;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ slapi_rwlock_wrlock(rid_lock);
|
|
|
dc8c34 |
+ for(i = 0; i < CLEANRIDSIZ; i++){
|
|
|
dc8c34 |
+ if(pre_cleaned_rids[i] == 0){
|
|
|
dc8c34 |
+ pre_cleaned_rids[i] = rid;
|
|
|
dc8c34 |
+ pre_cleaned_rids[i + 1] = 0;
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_rwlock_unlock(rid_lock);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Just add the rid to the in memory, as we don't want it to survive after a restart,
|
|
|
dc8c34 |
* This prevent the changelog from sending updates from this rid, and the local ruv
|
|
|
dc8c34 |
@@ -1948,7 +2195,7 @@ set_cleaned_rid(ReplicaId rid)
|
|
|
dc8c34 |
* Add the rid and maxcsn to the repl config (so we can resume after a server restart)
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
void
|
|
|
dc8c34 |
-add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn)
|
|
|
dc8c34 |
+add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_PBlock *pb;
|
|
|
dc8c34 |
struct berval *vals[2];
|
|
|
dc8c34 |
@@ -1965,7 +2212,7 @@ add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn)
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Write the rid & maxcsn to the config entry
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- val.bv_len = PR_snprintf(data, sizeof(data),"%d:%s", rid, maxcsn);
|
|
|
dc8c34 |
+ val.bv_len = PR_snprintf(data, sizeof(data),"%d:%s:%s", rid, maxcsn, forcing);
|
|
|
dc8c34 |
dn = replica_get_dn(r);
|
|
|
dc8c34 |
pb = slapi_pblock_new();
|
|
|
dc8c34 |
mod.mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES;
|
|
|
dc8c34 |
@@ -1977,13 +2224,11 @@ add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn)
|
|
|
dc8c34 |
mods[0] = &mod;
|
|
|
dc8c34 |
mods[1] = NULL;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- replica_add_cleanruv_data(r, val.bv_val);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
slapi_modify_internal_set_pb (pb, dn, mods, NULL, NULL,
|
|
|
dc8c34 |
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_TYPE_OR_VALUE_EXISTS){
|
|
|
dc8c34 |
+ if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS && rc != LDAP_NO_SUCH_OBJECT){
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to update replica "
|
|
|
dc8c34 |
"config (%d), rid (%d)\n", rc, rid);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -2036,7 +2281,7 @@ add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root)
|
|
|
dc8c34 |
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 |
+ if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS && rc != LDAP_NO_SUCH_OBJECT){
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to update "
|
|
|
dc8c34 |
"replica config (%d), rid (%d)\n", rc, rid);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -2047,7 +2292,7 @@ add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
void
|
|
|
dc8c34 |
-delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root){
|
|
|
dc8c34 |
+delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
|
|
|
dc8c34 |
Slapi_PBlock *pb;
|
|
|
dc8c34 |
LDAPMod *mods[2];
|
|
|
dc8c34 |
LDAPMod mod;
|
|
|
dc8c34 |
@@ -2061,117 +2306,126 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root){
|
|
|
dc8c34 |
if(r == NULL)
|
|
|
dc8c34 |
return;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- /*
|
|
|
dc8c34 |
- * Remove this rid, and optimize the array
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
- slapi_rwlock_wrlock(abort_rid_lock);
|
|
|
dc8c34 |
- for(i = 0; i < CLEANRIDSIZ && aborted_rids[i] != rid; i++); /* found rid, stop */
|
|
|
dc8c34 |
- for(; i < CLEANRIDSIZ; i++){
|
|
|
dc8c34 |
- /* rewrite entire array */
|
|
|
dc8c34 |
- aborted_rids[i] = aborted_rids[i + 1];
|
|
|
dc8c34 |
+ if(skip){
|
|
|
dc8c34 |
+ /* skip the deleting of the config, and just remove the in memory rid */
|
|
|
dc8c34 |
+ slapi_rwlock_wrlock(abort_rid_lock);
|
|
|
dc8c34 |
+ for(i = 0; i < CLEANRIDSIZ && aborted_rids[i] != rid; i++); /* found rid, stop */
|
|
|
dc8c34 |
+ for(; i < CLEANRIDSIZ; i++){
|
|
|
dc8c34 |
+ /* rewrite entire array */
|
|
|
dc8c34 |
+ aborted_rids[i] = aborted_rids[i + 1];
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_rwlock_unlock(abort_rid_lock);
|
|
|
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 |
+ mod.mod_type = (char *)type_replicaAbortCleanRUV;
|
|
|
dc8c34 |
+ mod.mod_bvalues = vals;
|
|
|
dc8c34 |
+ vals [0] = &val;
|
|
|
dc8c34 |
+ vals [1] = NULL;
|
|
|
dc8c34 |
+ val.bv_val = data;
|
|
|
dc8c34 |
+ val.bv_len = strlen (data);
|
|
|
dc8c34 |
+ mods[0] = &mod;
|
|
|
dc8c34 |
+ mods[1] = NULL;
|
|
|
dc8c34 |
+
|
|
|
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, "Abort CleanAllRUV Task: failed to remove replica "
|
|
|
dc8c34 |
+ "config (%d), rid (%d)\n", rc, rid);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_pblock_destroy (pb);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&dn;;
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- slapi_rwlock_unlock(abort_rid_lock);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * Just remove the dse.ldif config, but we need to keep the cleaned rids in memory until we know we are done
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+static void
|
|
|
dc8c34 |
+delete_cleaned_rid_config(cleanruv_data *clean_data)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ Slapi_PBlock *pb;
|
|
|
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[CSN_STRSIZE];
|
|
|
dc8c34 |
+ char *dn;
|
|
|
dc8c34 |
+ int rc;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Prepare the mods for the config entry
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- dn = replica_get_dn(r);
|
|
|
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 |
+ dn = replica_get_dn(clean_data->replica);
|
|
|
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 |
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 |
- val.bv_len = strlen (data);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
mods[0] = &mod;
|
|
|
dc8c34 |
mods[1] = NULL;
|
|
|
dc8c34 |
-
|
|
|
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 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to remove replica "
|
|
|
dc8c34 |
- "config (%d), rid (%d)\n", rc, rid);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- slapi_pblock_destroy (pb);
|
|
|
dc8c34 |
- slapi_ch_free_string(&dn;;
|
|
|
dc8c34 |
- slapi_ch_free_string(&data);
|
|
|
dc8c34 |
-}
|
|
|
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 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Remove the rid from our list, and the config
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
void
|
|
|
dc8c34 |
-delete_cleaned_rid(Replica *r, ReplicaId rid, CSN *maxcsn)
|
|
|
dc8c34 |
+remove_cleaned_rid(ReplicaId rid)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- Slapi_PBlock *pb;
|
|
|
dc8c34 |
- Object *agmt_obj;
|
|
|
dc8c34 |
- Repl_Agmt *agmt;
|
|
|
dc8c34 |
- LDAPMod *mods[2];
|
|
|
dc8c34 |
- LDAPMod mod;
|
|
|
dc8c34 |
- struct berval *vals[2];
|
|
|
dc8c34 |
- struct berval val;
|
|
|
dc8c34 |
- char *dn;
|
|
|
dc8c34 |
- char data[CSN_STRSIZE + 10];
|
|
|
dc8c34 |
- char csnstr[CSN_STRSIZE];
|
|
|
dc8c34 |
- int rc;
|
|
|
dc8c34 |
int i;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- if(r == NULL || maxcsn == NULL)
|
|
|
dc8c34 |
- return;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Remove this rid, and optimize the array
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
slapi_rwlock_wrlock(rid_lock);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
for(i = 0; i < CLEANRIDSIZ && cleaned_rids[i] != rid; i++); /* found rid, stop */
|
|
|
dc8c34 |
for(; i < CLEANRIDSIZ; i++){
|
|
|
dc8c34 |
/* rewrite entire array */
|
|
|
dc8c34 |
cleaned_rids[i] = cleaned_rids[i + 1];
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- slapi_rwlock_unlock(rid_lock);
|
|
|
dc8c34 |
- /*
|
|
|
dc8c34 |
- * Prepare the mods for the config entry
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
- csn_as_string(maxcsn, PR_FALSE, csnstr);
|
|
|
dc8c34 |
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s", (int)rid, csnstr);
|
|
|
dc8c34 |
- dn = replica_get_dn(r);
|
|
|
dc8c34 |
- pb = slapi_pblock_new();
|
|
|
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 |
-
|
|
|
dc8c34 |
- replica_remove_cleanruv_data(r, data);
|
|
|
dc8c34 |
-
|
|
|
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 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config "
|
|
|
dc8c34 |
- "(%d), rid (%d)\n", rc, rid);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- slapi_pblock_destroy (pb);
|
|
|
dc8c34 |
- slapi_ch_free_string(&dn;;
|
|
|
dc8c34 |
- /*
|
|
|
dc8c34 |
- * Now release the cleaned rid from the repl agmts
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
- agmt_obj = agmtlist_get_first_agreement_for_replica (r);
|
|
|
dc8c34 |
- while (agmt_obj){
|
|
|
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 (r, agmt_obj);
|
|
|
dc8c34 |
- continue;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- agmt_set_cleanruv_data(agmt, rid, CLEANRUV_RELEASED);
|
|
|
dc8c34 |
- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
|
|
|
dc8c34 |
+ /* now do the preset cleaned rids */
|
|
|
dc8c34 |
+ for(i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != rid; i++); /* found rid, stop */
|
|
|
dc8c34 |
+ for(; i < CLEANRIDSIZ; i++){
|
|
|
dc8c34 |
+ /* rewrite entire array */
|
|
|
dc8c34 |
+ pre_cleaned_rids[i] = pre_cleaned_rids[i + 1];
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ slapi_rwlock_unlock(rid_lock);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -2181,18 +2435,17 @@ int
|
|
|
dc8c34 |
replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
|
|
|
dc8c34 |
int *returncode, char *returntext, void *arg)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- PRThread *thread = NULL;
|
|
|
dc8c34 |
struct berval *payload = NULL;
|
|
|
dc8c34 |
- Slapi_Task *task = NULL;
|
|
|
dc8c34 |
- Replica *replica;
|
|
|
dc8c34 |
- ReplicaId rid;
|
|
|
dc8c34 |
cleanruv_data *data = NULL;
|
|
|
dc8c34 |
+ PRThread *thread = NULL;
|
|
|
dc8c34 |
+ Slapi_Task *task = NULL;
|
|
|
dc8c34 |
Slapi_DN *sdn = NULL;
|
|
|
dc8c34 |
+ Replica *replica;
|
|
|
dc8c34 |
+ ReplicaId rid;;
|
|
|
dc8c34 |
Object *r;
|
|
|
dc8c34 |
- CSN *maxcsn = NULL;
|
|
|
dc8c34 |
+ const char *certify_all;
|
|
|
dc8c34 |
const char *base_dn;
|
|
|
dc8c34 |
const char *rid_str;
|
|
|
dc8c34 |
- const char *certify_all;
|
|
|
dc8c34 |
char *ridstr = NULL;
|
|
|
dc8c34 |
int rc = SLAPI_DSE_CALLBACK_OK;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -2216,13 +2469,6 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if ((base_dn = fetch_attr(e, "replica-base-dn", 0)) == NULL){
|
|
|
dc8c34 |
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing required attr \"replica-base-dn\"");
|
|
|
dc8c34 |
- cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
- *returncode = LDAP_OBJECT_CLASS_VIOLATION;
|
|
|
dc8c34 |
- rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
- goto out;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
certify_all = fetch_attr(e, "replica-certify-all", 0);
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Check the rid
|
|
|
dc8c34 |
@@ -2236,6 +2482,29 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ if ((base_dn = fetch_attr(e, "replica-base-dn", 0)) == NULL){
|
|
|
dc8c34 |
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing required attr \"replica-base-dn\"");
|
|
|
dc8c34 |
+ cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
|
|
|
dc8c34 |
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
+ goto out;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(!is_cleaned_rid(rid) && !is_pre_cleaned_rid(rid)){
|
|
|
dc8c34 |
+ /* we are not cleaning this rid */
|
|
|
dc8c34 |
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replica id (%d) is not being cleaned, nothing to abort.", rid);
|
|
|
dc8c34 |
+ cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
+ goto out;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(is_task_aborted(rid)){
|
|
|
dc8c34 |
+ /* we are already aborting this rid */
|
|
|
dc8c34 |
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replica id (%d) is already being aborted", rid);
|
|
|
dc8c34 |
+ cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext);
|
|
|
dc8c34 |
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
+ goto out;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Get the replica object
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -2248,7 +2517,7 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
- * Check verify value
|
|
|
dc8c34 |
+ * Check certify value
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if(certify_all){
|
|
|
dc8c34 |
if(strcasecmp(certify_all,"yes") && strcasecmp(certify_all,"no")){
|
|
|
dc8c34 |
@@ -2260,13 +2529,13 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
- certify_all = "no";
|
|
|
dc8c34 |
+ certify_all = "yes";
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Create payload
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
ridstr = slapi_ch_smprintf("%d:%s:%s", rid, base_dn, certify_all);
|
|
|
dc8c34 |
- payload = create_ruv_payload(ridstr);
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(ridstr);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if(payload == NULL){
|
|
|
dc8c34 |
cleanruv_log(task, ABORT_CLEANALLRUV_ID, "Failed to create extended op payload, aborting task");
|
|
|
dc8c34 |
@@ -2278,8 +2547,6 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
|
|
|
dc8c34 |
* Stop the cleaning, and delete the rid
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
replica = (Replica*)object_get_data (r);
|
|
|
dc8c34 |
- maxcsn = replica_get_cleanruv_maxcsn(replica, rid);
|
|
|
dc8c34 |
- delete_cleaned_rid(replica, rid, maxcsn);
|
|
|
dc8c34 |
add_aborted_rid(rid, replica, (char *)base_dn);
|
|
|
dc8c34 |
stop_ruv_cleaning();
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -2308,11 +2575,11 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter
|
|
|
dc8c34 |
object_release(r);
|
|
|
dc8c34 |
cleanruv_log(task, ABORT_CLEANALLRUV_ID,"Unable to create abort thread. Aborting task.");
|
|
|
dc8c34 |
*returncode = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->certify);
|
|
|
dc8c34 |
rc = SLAPI_DSE_CALLBACK_ERROR;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
out:
|
|
|
dc8c34 |
- csn_free(&maxcsn);
|
|
|
dc8c34 |
slapi_ch_free_string(&ridstr);
|
|
|
dc8c34 |
slapi_sdn_free(&sdn;;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -2337,6 +2604,8 @@ replica_abort_task_thread(void *arg)
|
|
|
dc8c34 |
int interval = 10;
|
|
|
dc8c34 |
int release_it = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Need to build the replica from the dn
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -2414,8 +2683,12 @@ done:
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Clean up the config
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- delete_aborted_rid(data->replica, data->rid, data->repl_root);
|
|
|
dc8c34 |
- cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted cleanAllRUV task for rid(%d)", data->rid);
|
|
|
dc8c34 |
+ delete_aborted_rid(data->replica, data->rid, data->repl_root, 1); /* delete just the config, leave rid in memory */
|
|
|
dc8c34 |
+ if(strcasecmp(data->certify, "yes") == 0){
|
|
|
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 |
}
|
|
|
dc8c34 |
if(data->task){
|
|
|
dc8c34 |
slapi_task_finish(data->task, agmt_not_notified);
|
|
|
dc8c34 |
@@ -2437,10 +2710,10 @@ replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, struct ber
|
|
|
dc8c34 |
Repl_Connection *conn = NULL;
|
|
|
dc8c34 |
ConnResult crc = 0;
|
|
|
dc8c34 |
int msgid = 0;
|
|
|
dc8c34 |
- int rc = 0;
|
|
|
dc8c34 |
+ int rc = -1;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if((conn = conn_new(ra)) == NULL){
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
crc = conn_send_extended_operation(conn, REPL_ABORT_CLEANRUV_OID, payload, NULL, &msgid);
|
|
|
dc8c34 |
@@ -2462,186 +2735,262 @@ replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, struct ber
|
|
|
dc8c34 |
|
|
|
dc8c34 |
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
-replica_cleanallruv_send_extop(Repl_Agmt *ra, ReplicaId rid, Slapi_Task *task, struct berval *payload, int check_result)
|
|
|
dc8c34 |
+replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int check_result)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Repl_Connection *conn = NULL;
|
|
|
dc8c34 |
ConnResult crc = 0;
|
|
|
dc8c34 |
int msgid = 0;
|
|
|
dc8c34 |
- int rc = 0;
|
|
|
dc8c34 |
+ int rc = -1;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if((conn = conn_new(ra)) == NULL){
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
- crc = conn_send_extended_operation(conn, REPL_CLEANRUV_OID, payload, NULL, &msgid);
|
|
|
dc8c34 |
+ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_OID, clean_data->payload, NULL, &msgid);
|
|
|
dc8c34 |
if(crc == CONN_OPERATION_SUCCESS && check_result){
|
|
|
dc8c34 |
struct berval *retsdata = NULL;
|
|
|
dc8c34 |
char *retoid = NULL;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1);
|
|
|
dc8c34 |
if (CONN_OPERATION_SUCCESS == crc ){
|
|
|
dc8c34 |
- struct berval **ruv_bervals = NULL;
|
|
|
dc8c34 |
- struct berval *data = NULL;
|
|
|
dc8c34 |
- char *data_guid = NULL;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- decode_repl_ext_response(retsdata, &rc, &ruv_bervals, &data_guid, &data);
|
|
|
dc8c34 |
- /* just free everything, we only wanted "rc" */
|
|
|
dc8c34 |
- slapi_ch_free_string(&data_guid);
|
|
|
dc8c34 |
- if(data)
|
|
|
dc8c34 |
- ber_bvfree(data);
|
|
|
dc8c34 |
- if (ruv_bervals)
|
|
|
dc8c34 |
- ber_bvecfree(ruv_bervals);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- if(rc == 0 ){ /* rc == 1 is success */
|
|
|
dc8c34 |
- cleanruv_log(task, CLEANALLRUV_ID,"Replica %s does not support the CLEANALLRUV task. Sending replica CLEANRUV task...",
|
|
|
dc8c34 |
+ char *response = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ decode_cleanruv_payload(retsdata, &response);
|
|
|
dc8c34 |
+ if(response && strcmp(response,CLEANRUV_ACCEPTED) == 0){
|
|
|
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 |
/*
|
|
|
dc8c34 |
* Ok, this replica doesn't know about CLEANALLRUV, so just manually
|
|
|
dc8c34 |
* add the CLEANRUV task to the replica.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- replica_send_cleanruv_task(ra, rid, task);
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- /* extop was accepted */
|
|
|
dc8c34 |
- rc = 0;
|
|
|
dc8c34 |
+ replica_send_cleanruv_task(ra, clean_data);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (NULL != retoid)
|
|
|
dc8c34 |
- ldap_memfree(retoid);
|
|
|
dc8c34 |
if (NULL != retsdata)
|
|
|
dc8c34 |
ber_bvfree(retsdata);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&retoid);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&response);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- agmt_set_cleanruv_data(ra, rid, CLEANRUV_NOTIFIED);
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* success or failure, just return the error code
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
rc = crc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- rc =-1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+static CSN*
|
|
|
dc8c34 |
+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 |
+
|
|
|
dc8c34 |
+ rid_text = slapi_ch_smprintf("%d", rid);
|
|
|
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 |
+ }
|
|
|
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 |
+ 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 |
+ 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 |
+ }
|
|
|
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: 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 |
+ }
|
|
|
dc8c34 |
+ slapi_ch_free_string(&rid_text);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if(is_task_aborted(rid)){
|
|
|
dc8c34 |
+ return NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return topcsn;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
-replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *rid_text, char *maxcsn, Slapi_Task *task)
|
|
|
dc8c34 |
+replica_cleanallruv_get_replica_maxcsn(Repl_Agmt *agmt, char *rid_text, char *basedn, CSN **csn)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Repl_Connection *conn = NULL;
|
|
|
dc8c34 |
- LDAP *ld;
|
|
|
dc8c34 |
- Slapi_DN *sdn;
|
|
|
dc8c34 |
- struct berval **vals;
|
|
|
dc8c34 |
- LDAPMessage *result = NULL, *entry = NULL;
|
|
|
dc8c34 |
- BerElement *ber;
|
|
|
dc8c34 |
- char *attrs[2];
|
|
|
dc8c34 |
- char *attr = NULL;
|
|
|
dc8c34 |
- char *iter = NULL;
|
|
|
dc8c34 |
- char *ruv_part = NULL;
|
|
|
dc8c34 |
- int found_rid = 0;
|
|
|
dc8c34 |
- int part_count = 0;
|
|
|
dc8c34 |
- int rc = 0, i;
|
|
|
dc8c34 |
+ ConnResult crc = -1;
|
|
|
dc8c34 |
+ struct berval *payload = NULL;
|
|
|
dc8c34 |
+ CSN *maxcsn = NULL;
|
|
|
dc8c34 |
+ char *data = NULL;
|
|
|
dc8c34 |
+ int msgid = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if((conn = conn_new(agmt)) == NULL){
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ data = slapi_ch_smprintf("%s:%s",rid_text, basedn);
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(data);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
- attrs[0] = "nsds50ruv";
|
|
|
dc8c34 |
- attrs[1] = NULL;
|
|
|
dc8c34 |
- ld = conn_get_ldap(conn);
|
|
|
dc8c34 |
- if(ld == NULL){
|
|
|
dc8c34 |
- conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- sdn = agmt_get_replarea(agmt);
|
|
|
dc8c34 |
- rc = ldap_search_ext_s(ld, slapi_sdn_get_dn(sdn), LDAP_SCOPE_SUBTREE,
|
|
|
dc8c34 |
- "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))",
|
|
|
dc8c34 |
- attrs, 0, NULL, NULL, NULL, 0, &result);
|
|
|
dc8c34 |
- slapi_sdn_free(&sdn;;
|
|
|
dc8c34 |
- if(rc != LDAP_SUCCESS){
|
|
|
dc8c34 |
- cleanruv_log(task, CLEANALLRUV_ID,"Failed to contact "
|
|
|
dc8c34 |
- "agmt (%s) error (%d), will retry later.", agmt_get_long_name(agmt), rc);
|
|
|
dc8c34 |
- conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- entry = ldap_first_entry( ld, result );
|
|
|
dc8c34 |
- if ( entry != NULL ) {
|
|
|
dc8c34 |
- for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL; attr = ldap_next_attribute( ld, entry, ber ) ){
|
|
|
dc8c34 |
- /* make sure the attribute is nsds50ruv */
|
|
|
dc8c34 |
- if(strcasecmp(attr,"nsds50ruv") != 0){
|
|
|
dc8c34 |
- ldap_memfree( attr );
|
|
|
dc8c34 |
- continue;
|
|
|
dc8c34 |
+ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_GET_MAXCSN_OID, payload, NULL, &msgid);
|
|
|
dc8c34 |
+ if(crc == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
+ struct berval *retsdata = NULL;
|
|
|
dc8c34 |
+ char *retoid = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1);
|
|
|
dc8c34 |
+ if (CONN_OPERATION_SUCCESS == crc ){
|
|
|
dc8c34 |
+ char *remote_maxcsn = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ decode_cleanruv_payload(retsdata, &remote_maxcsn);
|
|
|
dc8c34 |
+ if(remote_maxcsn && strcmp(remote_maxcsn, CLEANRUV_NO_MAXCSN)){
|
|
|
dc8c34 |
+ maxcsn = csn_new();
|
|
|
dc8c34 |
+ csn_init_by_string(maxcsn, remote_maxcsn);
|
|
|
dc8c34 |
+ *csn = maxcsn;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* no csn */
|
|
|
dc8c34 |
+ *csn = NULL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- found_rid = 0;
|
|
|
dc8c34 |
- if ((vals = ldap_get_values_len( ld, entry, attr)) != NULL ) {
|
|
|
dc8c34 |
- for ( i = 0; vals[i] && vals[i]->bv_val; i++ ) {
|
|
|
dc8c34 |
- /* look for this replica */
|
|
|
dc8c34 |
- if(strstr(vals[i]->bv_val, rid_text)){
|
|
|
dc8c34 |
- found_rid = 1;
|
|
|
dc8c34 |
- /* get the max csn compare it to our known max csn */
|
|
|
dc8c34 |
- ruv_part = ldap_utf8strtok_r(vals[i]->bv_val, " ", &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){
|
|
|
dc8c34 |
- /* we have the maxcsn */
|
|
|
dc8c34 |
- if(strcmp(ruv_part, maxcsn)){
|
|
|
dc8c34 |
- /* we are not caught up yet, free, and return */
|
|
|
dc8c34 |
- ldap_value_free_len(vals);
|
|
|
dc8c34 |
- ldap_memfree( attr );
|
|
|
dc8c34 |
- ldap_msgfree( result );
|
|
|
dc8c34 |
- if(ber){
|
|
|
dc8c34 |
- ber_free( ber, 0 );
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- /* ok this replica has all the updates from the deleted replica */
|
|
|
dc8c34 |
- rc = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- /* there is no maxcsn for this rid - treat it as caught up */
|
|
|
dc8c34 |
- rc = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if(!found_rid){
|
|
|
dc8c34 |
- /* must have been cleaned already */
|
|
|
dc8c34 |
+ slapi_ch_free_string(&retoid);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&remote_maxcsn);
|
|
|
dc8c34 |
+ if (NULL != retsdata)
|
|
|
dc8c34 |
+ ber_bvfree(retsdata);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data);
|
|
|
dc8c34 |
+ if(payload)
|
|
|
dc8c34 |
+ ber_bvfree(payload);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return (int)crc;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+static int
|
|
|
dc8c34 |
+replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *basedn, char *rid_text, char *maxcsn, Slapi_Task *task)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ Repl_Connection *conn = NULL;
|
|
|
dc8c34 |
+ ConnResult crc = 0;
|
|
|
dc8c34 |
+ struct berval *payload = NULL;
|
|
|
dc8c34 |
+ char *data = NULL;
|
|
|
dc8c34 |
+ int msgid = 0;
|
|
|
dc8c34 |
+ int rc = -1;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if((conn = conn_new(agmt)) == NULL){
|
|
|
dc8c34 |
+ return -1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ data = slapi_ch_smprintf("%s:%s",rid_text, basedn);
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(data);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
+ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_GET_MAXCSN_OID, payload, NULL, &msgid);
|
|
|
dc8c34 |
+ if(crc == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
+ struct berval *retsdata = NULL;
|
|
|
dc8c34 |
+ char *retoid = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1);
|
|
|
dc8c34 |
+ if (CONN_OPERATION_SUCCESS == crc ){
|
|
|
dc8c34 |
+ char *remote_maxcsn = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ decode_cleanruv_payload(retsdata, &remote_maxcsn);
|
|
|
dc8c34 |
+ if(remote_maxcsn && strcmp(remote_maxcsn, CLEANRUV_NO_MAXCSN)){
|
|
|
dc8c34 |
+ CSN *max, *repl_max;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ max = csn_new();
|
|
|
dc8c34 |
+ repl_max = csn_new();
|
|
|
dc8c34 |
+ csn_init_by_string(max, maxcsn);
|
|
|
dc8c34 |
+ csn_init_by_string(repl_max, remote_maxcsn);
|
|
|
dc8c34 |
+ if(csn_compare (repl_max, max) < 0){
|
|
|
dc8c34 |
+ /* we are not caught up yet, free, and return */
|
|
|
dc8c34 |
+ cleanruv_log(task, CLEANALLRUV_ID,"Replica maxcsn (%s) is not caught up with deleted replica's maxcsn(%s)",
|
|
|
dc8c34 |
+ remote_maxcsn, maxcsn);
|
|
|
dc8c34 |
+ rc = -1;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* ok this replica is caught up */
|
|
|
dc8c34 |
rc = 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- ldap_value_free_len(vals);
|
|
|
dc8c34 |
+ csn_free(&max;;
|
|
|
dc8c34 |
+ csn_free(&repl_max);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* no remote_maxcsn - return success */
|
|
|
dc8c34 |
+ rc = 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- ldap_memfree( attr );
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if ( ber != NULL ) {
|
|
|
dc8c34 |
- ber_free( ber, 0 );
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if(result)
|
|
|
dc8c34 |
- ldap_msgfree( result );
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- rc = -1;
|
|
|
dc8c34 |
+ slapi_ch_free_string(&retoid);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&remote_maxcsn);
|
|
|
dc8c34 |
+ if (NULL != retsdata)
|
|
|
dc8c34 |
+ ber_bvfree(retsdata);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data);
|
|
|
dc8c34 |
+ if(payload)
|
|
|
dc8c34 |
+ ber_bvfree(payload);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- return rc;
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
replica_cleanallruv_replica_alive(Repl_Agmt *agmt)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Repl_Connection *conn = NULL;
|
|
|
dc8c34 |
LDAP *ld = NULL;
|
|
|
dc8c34 |
LDAPMessage *result = NULL;
|
|
|
dc8c34 |
- int rc = 0;
|
|
|
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 |
ld = conn_get_ldap(conn);
|
|
|
dc8c34 |
if(ld == NULL){
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: failed to get LDAP "
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "CleanAllRUV_task: failed to get LDAP "
|
|
|
dc8c34 |
"handle from the replication agmt (%s). Moving on to the next agmt.\n",agmt_get_long_name(agmt));
|
|
|
dc8c34 |
conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
@@ -2655,8 +3004,6 @@ replica_cleanallruv_replica_alive(Repl_Agmt *agmt)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(result)
|
|
|
dc8c34 |
ldap_msgfree( result );
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- rc = -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -2664,83 +3011,51 @@ replica_cleanallruv_replica_alive(Repl_Agmt *agmt)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
-replica_cleanallruv_check_ruv(Repl_Agmt *ra, char *rid_text, Slapi_Task *task)
|
|
|
dc8c34 |
+replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *agmt, char *rid_text, Slapi_Task *task)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Repl_Connection *conn = NULL;
|
|
|
dc8c34 |
- BerElement *ber = NULL;
|
|
|
dc8c34 |
- struct berval **vals = NULL;
|
|
|
dc8c34 |
- LDAPMessage *result = NULL, *entry = NULL;
|
|
|
dc8c34 |
- LDAP *ld = NULL;
|
|
|
dc8c34 |
- Slapi_DN *sdn;
|
|
|
dc8c34 |
- char *attrs[2];
|
|
|
dc8c34 |
- char *attr = NULL;
|
|
|
dc8c34 |
- int rc = 0, i;
|
|
|
dc8c34 |
+ ConnResult crc = 0;
|
|
|
dc8c34 |
+ struct berval *payload = NULL;
|
|
|
dc8c34 |
+ char *data = NULL;
|
|
|
dc8c34 |
+ int msgid = 0;
|
|
|
dc8c34 |
+ int rc = -1;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if((conn = conn_new(ra)) == NULL){
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
+ if((conn = conn_new(agmt)) == NULL){
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ data = slapi_ch_smprintf("%s:%s",rid_text, repl_root);
|
|
|
dc8c34 |
+ payload = create_cleanruv_payload(data);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
- attrs[0] = "nsds50ruv";
|
|
|
dc8c34 |
- attrs[1] = NULL;
|
|
|
dc8c34 |
- ld = conn_get_ldap(conn);
|
|
|
dc8c34 |
- if(ld == NULL){
|
|
|
dc8c34 |
- cleanruv_log(task, CLEANALLRUV_ID,"Failed to get LDAP handle from "
|
|
|
dc8c34 |
- "the replication agmt (%s). Moving on to the next agmt.",agmt_get_long_name(ra));
|
|
|
dc8c34 |
- rc = -1;
|
|
|
dc8c34 |
- goto done;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_GET_MAXCSN_OID, payload, NULL, &msgid);
|
|
|
dc8c34 |
+ if(crc == CONN_OPERATION_SUCCESS){
|
|
|
dc8c34 |
+ struct berval *retsdata = NULL;
|
|
|
dc8c34 |
+ char *retoid = NULL;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- sdn = agmt_get_replarea(ra);
|
|
|
dc8c34 |
- rc = ldap_search_ext_s(ld, slapi_sdn_get_dn(sdn), LDAP_SCOPE_SUBTREE,
|
|
|
dc8c34 |
- "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))",
|
|
|
dc8c34 |
- attrs, 0, NULL, NULL, NULL, 0, &result);
|
|
|
dc8c34 |
- slapi_sdn_free(&sdn;;
|
|
|
dc8c34 |
- if(rc != LDAP_SUCCESS){
|
|
|
dc8c34 |
- cleanruv_log(task, CLEANALLRUV_ID,"Failed to contact "
|
|
|
dc8c34 |
- "agmt (%s) error (%d), will retry later.", agmt_get_long_name(ra), rc);
|
|
|
dc8c34 |
- rc = -1;
|
|
|
dc8c34 |
- goto done;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- entry = ldap_first_entry( ld, result );
|
|
|
dc8c34 |
- if ( entry != NULL ) {
|
|
|
dc8c34 |
- for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL; attr = ldap_next_attribute( ld, entry, ber ) ){
|
|
|
dc8c34 |
- /* make sure the attribute is nsds50ruv */
|
|
|
dc8c34 |
- if(strcasecmp(attr,"nsds50ruv") != 0){
|
|
|
dc8c34 |
- ldap_memfree( attr );
|
|
|
dc8c34 |
- continue;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if ((vals = ldap_get_values_len( ld, entry, attr)) != NULL ) {
|
|
|
dc8c34 |
- for ( i = 0; vals[i] && vals[i]->bv_val; i++ ) {
|
|
|
dc8c34 |
- /* look for this replica */
|
|
|
dc8c34 |
- if(strstr(vals[i]->bv_val, rid_text)){
|
|
|
dc8c34 |
- /* rid has not been cleaned yet, free and return */
|
|
|
dc8c34 |
- rc = -1;
|
|
|
dc8c34 |
- ldap_value_free_len(vals);
|
|
|
dc8c34 |
- ldap_memfree( attr );
|
|
|
dc8c34 |
- if ( ber != NULL ) {
|
|
|
dc8c34 |
- ber_free( ber, 0 );
|
|
|
dc8c34 |
- ber = NULL;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- goto done;
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- rc = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- ldap_value_free_len(vals);
|
|
|
dc8c34 |
+ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1);
|
|
|
dc8c34 |
+ if (CONN_OPERATION_SUCCESS == crc ){
|
|
|
dc8c34 |
+ char *remote_maxcsn = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ decode_cleanruv_payload(retsdata, &remote_maxcsn);
|
|
|
dc8c34 |
+ if(remote_maxcsn && strcmp(remote_maxcsn, CLEANRUV_NO_MAXCSN)){
|
|
|
dc8c34 |
+ /* remote replica still has dirty RUV element */
|
|
|
dc8c34 |
+ rc = -1;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* no maxcsn = we're clean */
|
|
|
dc8c34 |
+ rc = 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- ldap_memfree( attr );
|
|
|
dc8c34 |
- } /* for loop */
|
|
|
dc8c34 |
- if ( ber != NULL ) {
|
|
|
dc8c34 |
- ber_free( ber, 0 );
|
|
|
dc8c34 |
+ slapi_ch_free_string(&retoid);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&remote_maxcsn);
|
|
|
dc8c34 |
+ if (NULL != retsdata)
|
|
|
dc8c34 |
+ ber_bvfree(retsdata);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-done:
|
|
|
dc8c34 |
- if(result)
|
|
|
dc8c34 |
- ldap_msgfree( result );
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- return -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
conn_delete_internal_ext(conn);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data);
|
|
|
dc8c34 |
+ if(payload)
|
|
|
dc8c34 |
+ ber_bvfree(payload);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
|
|
|
dc8c34 |
index 3a6f422..e842c62 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl_extop.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl_extop.c
|
|
|
dc8c34 |
@@ -1451,7 +1451,6 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
cleanruv_data *data;
|
|
|
dc8c34 |
Replica *r;
|
|
|
dc8c34 |
ReplicaId rid;
|
|
|
dc8c34 |
- CSN *maxcsn = NULL;
|
|
|
dc8c34 |
struct berval *extop_payload = NULL;
|
|
|
dc8c34 |
char *extop_oid;
|
|
|
dc8c34 |
char *repl_root;
|
|
|
dc8c34 |
@@ -1463,7 +1462,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
|
|
|
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 |
|
|
|
dc8c34 |
- if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_OID) != 0 ||
|
|
|
dc8c34 |
+ if (NULL == extop_oid || strcmp(extop_oid, REPL_ABORT_CLEANRUV_OID) != 0 ||
|
|
|
dc8c34 |
NULL == extop_payload || NULL == extop_payload->bv_val){
|
|
|
dc8c34 |
/* something is wrong, error out */
|
|
|
dc8c34 |
return LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
@@ -1472,24 +1471,24 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
* Decode the payload, and grab our settings
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if(decode_cleanruv_payload(extop_payload, &payload)){
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: failed to decode payload. Aborting ext op\n");
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to decode payload. Aborting ext op\n");
|
|
|
dc8c34 |
return LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
|
|
|
dc8c34 |
repl_root = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
certify_all = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if(!is_cleaned_rid(rid) || is_task_aborted(rid)){
|
|
|
dc8c34 |
+ if(!is_cleaned_rid(rid) || !is_pre_cleaned_rid(rid) || is_task_aborted(rid)){
|
|
|
dc8c34 |
/* This replica has already been aborted, or was never cleaned, or already finished cleaning */
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: aborting cleanallruv task for rid(%d)\n", rid);
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: aborting cleanallruv task for rid(%d)\n", rid);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Get the node, so we can get the replica and its agreements
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: failed to get replication node "
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to get replication node "
|
|
|
dc8c34 |
"from (%s), aborting operation\n", repl_root);
|
|
|
dc8c34 |
rc = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
@@ -1498,14 +1497,14 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
object_acquire (mtnode_ext->replica);
|
|
|
dc8c34 |
release_it = 1;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: replica is missing from (%s), "
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: replica is missing from (%s), "
|
|
|
dc8c34 |
"aborting operation\n",repl_root);
|
|
|
dc8c34 |
rc = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
r = (Replica*)object_get_data (mtnode_ext->replica);
|
|
|
dc8c34 |
if(r == NULL){
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: replica is NULL, aborting task\n");
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: replica is NULL, aborting task\n");
|
|
|
dc8c34 |
rc = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1514,7 +1513,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data));
|
|
|
dc8c34 |
if (data == NULL) {
|
|
|
dc8c34 |
- slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort cleanAllRUV task: failed to allocate "
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort CleanAllRUV Task: failed to allocate "
|
|
|
dc8c34 |
"abort_cleanruv_data. Aborting task.\n");
|
|
|
dc8c34 |
rc = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto out;
|
|
|
dc8c34 |
@@ -1528,11 +1527,8 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
data->repl_root = slapi_ch_strdup(repl_root);
|
|
|
dc8c34 |
data->certify = slapi_ch_strdup(certify_all);
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
- * Stop the cleaning, and delete the rid
|
|
|
dc8c34 |
+ * Set the aborted rid and stop the cleaning
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- maxcsn = replica_get_cleanruv_maxcsn(r, rid);
|
|
|
dc8c34 |
- delete_cleaned_rid(r, rid, maxcsn);
|
|
|
dc8c34 |
- csn_free(&maxcsn);
|
|
|
dc8c34 |
add_aborted_rid(rid, r, repl_root);
|
|
|
dc8c34 |
stop_ruv_cleaning();
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -1542,7 +1538,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
|
|
dc8c34 |
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
|
|
|
dc8c34 |
if (thread == NULL) {
|
|
|
dc8c34 |
- slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort cleanAllRUV task: unable to create abort "
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort CleanAllRUV Task: unable to create abort "
|
|
|
dc8c34 |
"thread. Aborting task.\n");
|
|
|
dc8c34 |
release_it = 1; /* have to release mtnode_ext->replica now */
|
|
|
dc8c34 |
slapi_ch_free_string(&data->repl_root);
|
|
|
dc8c34 |
@@ -1583,10 +1579,11 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
struct berval *extop_payload;
|
|
|
dc8c34 |
struct berval *resp_bval = NULL;
|
|
|
dc8c34 |
BerElement *resp_bere = NULL;
|
|
|
dc8c34 |
- char *extop_oid;
|
|
|
dc8c34 |
- char *repl_root;
|
|
|
dc8c34 |
char *payload = NULL;
|
|
|
dc8c34 |
char *csnstr = NULL;
|
|
|
dc8c34 |
+ char *force = NULL;
|
|
|
dc8c34 |
+ char *extop_oid;
|
|
|
dc8c34 |
+ char *repl_root;
|
|
|
dc8c34 |
char *iter;
|
|
|
dc8c34 |
int release_it = 0;
|
|
|
dc8c34 |
int rid = 0;
|
|
|
dc8c34 |
@@ -1604,28 +1601,31 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
* Decode the payload
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if(decode_cleanruv_payload(extop_payload, &payload)){
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to decode payload. Aborting ext op\n");
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to decode payload. Aborting ext op\n");
|
|
|
dc8c34 |
goto free_and_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
|
|
|
dc8c34 |
repl_root = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
csnstr = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
+ force = ldap_utf8strtok_r(iter, ":", &iter);
|
|
|
dc8c34 |
+ if(force == NULL){
|
|
|
dc8c34 |
+ force = "no";
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
maxcsn = csn_new();
|
|
|
dc8c34 |
csn_init_by_string(maxcsn, csnstr);
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* If we already cleaned this server, just return success
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- if(is_cleaned_rid(rid)){
|
|
|
dc8c34 |
+ if(is_cleaned_rid(rid) || is_pre_cleaned_rid(rid) || is_task_aborted(rid)){
|
|
|
dc8c34 |
csn_free(&maxcsn);
|
|
|
dc8c34 |
rc = LDAP_SUCCESS;
|
|
|
dc8c34 |
goto free_and_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Get the node, so we can get the replica and its agreements
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to get replication node "
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to get replication node "
|
|
|
dc8c34 |
"from (%s), aborting operation\n", repl_root);
|
|
|
dc8c34 |
goto free_and_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1634,14 +1634,14 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
object_acquire (mtnode_ext->replica);
|
|
|
dc8c34 |
release_it = 1;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica is missing from (%s), "
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica is missing from (%s), "
|
|
|
dc8c34 |
"aborting operation\n",repl_root);
|
|
|
dc8c34 |
goto free_and_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
r = (Replica*)object_get_data (mtnode_ext->replica);
|
|
|
dc8c34 |
if(r == NULL){
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica is NULL, aborting task\n");
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica is NULL, aborting task\n");
|
|
|
dc8c34 |
goto free_and_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1651,10 +1651,10 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
*
|
|
|
dc8c34 |
* This will also release mtnode_ext->replica
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: launching cleanAllRUV thread...\n");
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: launching cleanAllRUV thread...\n");
|
|
|
dc8c34 |
data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data));
|
|
|
dc8c34 |
if (data == NULL) {
|
|
|
dc8c34 |
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to allocate "
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to allocate "
|
|
|
dc8c34 |
"cleanruv_Data\n");
|
|
|
dc8c34 |
goto free_and_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1664,15 +1664,19 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
data->task = NULL;
|
|
|
dc8c34 |
data->maxcsn = maxcsn;
|
|
|
dc8c34 |
data->payload = slapi_ch_bvdup(extop_payload);
|
|
|
dc8c34 |
+ data->force = slapi_ch_strdup(force);
|
|
|
dc8c34 |
+ data->repl_root = slapi_ch_strdup(repl_root);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread_ext,
|
|
|
dc8c34 |
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
|
|
dc8c34 |
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
|
|
|
dc8c34 |
if (thread == NULL) {
|
|
|
dc8c34 |
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: unable to create cleanAllRUV "
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: unable to create cleanAllRUV "
|
|
|
dc8c34 |
"monitoring thread. Aborting task.\n");
|
|
|
dc8c34 |
ber_bvfree(data->payload);
|
|
|
dc8c34 |
data->payload = NULL;
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->force);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&data->repl_root);
|
|
|
dc8c34 |
slapi_ch_free((void **)&data);
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
release_it = 0; /* thread will release data->repl_obj == mtnode_ext->replica */
|
|
|
dc8c34 |
@@ -1694,18 +1698,18 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
/* we've already been cleaned */
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: checking if we're caught up...\n");
|
|
|
dc8c34 |
- if(ruv_covers_csn_cleanallruv(ruv,maxcsn) || csn_get_replicaid(maxcsn) == 0){
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: checking if we're caught up...\n");
|
|
|
dc8c34 |
+ if(ruv_covers_csn_cleanallruv(ruv,maxcsn) || csn_get_replicaid(maxcsn) == 0|| strcmp(force,"yes") == 0){
|
|
|
dc8c34 |
/* We are caught up */
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
char csnstr[CSN_STRSIZE];
|
|
|
dc8c34 |
csn_as_string(maxcsn, PR_FALSE, csnstr);
|
|
|
dc8c34 |
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: not ruv caught up maxcsn(%s)\n", csnstr);
|
|
|
dc8c34 |
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: not ruv caught up maxcsn(%s)\n", csnstr);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
DS_Sleep(PR_SecondsToInterval(5));
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: we're caught up...\n");
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: we're caught up...\n");
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Set cleaned rid in memory only - does not survive a server restart
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -1721,8 +1725,8 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
|
|
|
dc8c34 |
* This read-only replica has no easy way to tell when it's safe to release the rid.
|
|
|
dc8c34 |
* So we won't release it, not until a server restart.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: You must restart the server if you want to reuse rid(%d).\n", rid);
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully cleaned rid(%d).\n", rid);
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: You must restart the server if you want to reuse rid(%d).\n", rid);
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: Successfully cleaned rid(%d).\n", rid);
|
|
|
dc8c34 |
rc = LDAP_SUCCESS;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1737,10 +1741,120 @@ free_and_return:
|
|
|
dc8c34 |
* Craft a message so we know this replica supports the task
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if ((resp_bere = der_alloc())){
|
|
|
dc8c34 |
+ ber_printf(resp_bere, "{s}", CLEANRUV_ACCEPTED);
|
|
|
dc8c34 |
+ ber_flatten(resp_bere, &resp_bval);
|
|
|
dc8c34 |
+ slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval);
|
|
|
dc8c34 |
+ slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
|
|
|
dc8c34 |
+ /* resp_bere */
|
|
|
dc8c34 |
+ if (NULL != resp_bere)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ ber_free(resp_bere, 1);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /* resp_bval */
|
|
|
dc8c34 |
+ if (NULL != resp_bval)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ ber_bvfree(resp_bval);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /* tell extendop code that we have already sent the result */
|
|
|
dc8c34 |
+ rc = SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ rc = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- ber_int_t response = 1;
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * Get the max csn for the designated repl area
|
|
|
dc8c34 |
+ */
|
|
|
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 |
|
|
|
dc8c34 |
- ber_printf(resp_bere, "{e}", response);
|
|
|
dc8c34 |
+ if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_GET_MAXCSN_OID) != 0 ||
|
|
|
dc8c34 |
+ NULL == extop_payload || NULL == extop_payload->bv_val){
|
|
|
dc8c34 |
+ /* something is wrong, error out */
|
|
|
dc8c34 |
+ goto free_and_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Decode the payload
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if(decode_cleanruv_payload(extop_payload, &payload)){
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Get MaxCSN Task: failed to decode payload. Aborting ext op\n");
|
|
|
dc8c34 |
+ goto free_and_return;
|
|
|
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 |
+ if(maxcsn == NULL){
|
|
|
dc8c34 |
+ maxcsn = slapi_ch_strdup(CLEANRUV_NO_MAXCSN);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Send the extended op response
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if ((resp_bere = der_alloc())){
|
|
|
dc8c34 |
+ ber_printf(resp_bere, "{s}", maxcsn);
|
|
|
dc8c34 |
ber_flatten(resp_bere, &resp_bval);
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval);
|
|
|
dc8c34 |
slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
|
|
|
dc8c34 |
@@ -1760,10 +1874,96 @@ free_and_return:
|
|
|
dc8c34 |
rc = LDAP_OPERATIONS_ERROR;
|
|
|
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 |
/*
|
|
|
dc8c34 |
+ * Search cn=config for the cleanallruv attributes (clean & abort)
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+multimaster_extop_cleanruv_check_status(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 *response = NULL;
|
|
|
dc8c34 |
+ char *filter = NULL;
|
|
|
dc8c34 |
+ char *extop_oid;
|
|
|
dc8c34 |
+ int res = 0;
|
|
|
dc8c34 |
+ int rc = LDAP_OPERATIONS_ERROR;
|
|
|
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 |
+
|
|
|
dc8c34 |
+ if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_CHECK_STATUS_OID) != 0 ||
|
|
|
dc8c34 |
+ NULL == extop_payload || NULL == extop_payload->bv_val){
|
|
|
dc8c34 |
+ /* something is wrong, error out */
|
|
|
dc8c34 |
+ goto free_and_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Decode the payload - which should just be a filter
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if(decode_cleanruv_payload(extop_payload, &filter)){
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Check Status Task: failed to decode payload. Aborting ext op\n");
|
|
|
dc8c34 |
+ goto free_and_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ search_pb = slapi_pblock_new();
|
|
|
dc8c34 |
+ slapi_search_internal_set_pb(search_pb, "cn=config", LDAP_SCOPE_SUBTREE,
|
|
|
dc8c34 |
+ filter, NULL, 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 |
+ if ( LDAP_SUCCESS == res ) {
|
|
|
dc8c34 |
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
|
|
dc8c34 |
+ if (NULL == entries || entries[0] == NULL) {
|
|
|
dc8c34 |
+ /* cleaning task has finished, send repsonse */
|
|
|
dc8c34 |
+ response = CLEANRUV_FINISHED;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ response = CLEANRUV_CLEANING;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Send the extended op response
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if ((resp_bere = der_alloc())){
|
|
|
dc8c34 |
+ ber_printf(resp_bere, "{s}", response);
|
|
|
dc8c34 |
+ ber_flatten(resp_bere, &resp_bval);
|
|
|
dc8c34 |
+ slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval);
|
|
|
dc8c34 |
+ slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
|
|
|
dc8c34 |
+ /* resp_bere */
|
|
|
dc8c34 |
+ if (NULL != resp_bere)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ ber_free(resp_bere, 1);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /* resp_bval */
|
|
|
dc8c34 |
+ if (NULL != resp_bval)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ ber_bvfree(resp_bval);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /* tell extendop code that we have already sent the result */
|
|
|
dc8c34 |
+ rc = SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+free_and_return:
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ slapi_free_search_results_internal(search_pb);
|
|
|
dc8c34 |
+ slapi_pblock_destroy(search_pb);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&filter);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
* This plugin entry point is a noop entry
|
|
|
dc8c34 |
* point. It's used when registering extops that
|
|
|
dc8c34 |
* are only used as responses. We'll never receive
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/replutil.c b/ldap/servers/plugins/replication/replutil.c
|
|
|
dc8c34 |
index 5e8019c..d007f6c 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/replutil.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/replutil.c
|
|
|
dc8c34 |
@@ -765,33 +765,32 @@ repl_set_mtn_state_and_referrals(
|
|
|
dc8c34 |
ldap_free_urldesc(lud);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if (!referrals_to_set) { /* deleting referrals */
|
|
|
dc8c34 |
- /* Set state before */
|
|
|
dc8c34 |
- if (!chain_on_update) {
|
|
|
dc8c34 |
- slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state);
|
|
|
dc8c34 |
+ if (!referrals_to_set) { /* deleting referrals */
|
|
|
dc8c34 |
+ /* Set state before */
|
|
|
dc8c34 |
+ if (!chain_on_update) {
|
|
|
dc8c34 |
+ slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /* We should delete referral only if we want to set the
|
|
|
dc8c34 |
+ replica database in backend state mode */
|
|
|
dc8c34 |
+ /* if chain on update mode, go ahead and set the referrals anyway */
|
|
|
dc8c34 |
+ if (strcasecmp(mtn_state, STATE_BACKEND) == 0 || chain_on_update) {
|
|
|
dc8c34 |
+ rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set);
|
|
|
dc8c34 |
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
|
|
|
dc8c34 |
+ /* we will get no such attribute (16) if we try to set the referrals to NULL if
|
|
|
dc8c34 |
+ there are no referrals - not an error */
|
|
|
dc8c34 |
+ rc = LDAP_SUCCESS;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- /* We should delete referral only if we want to set the
|
|
|
dc8c34 |
- replica database in backend state mode */
|
|
|
dc8c34 |
- /* if chain on update mode, go ahead and set the referrals anyway */
|
|
|
dc8c34 |
- if (strcasecmp(mtn_state, STATE_BACKEND) == 0 || chain_on_update) {
|
|
|
dc8c34 |
- rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set);
|
|
|
dc8c34 |
- if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
|
|
|
dc8c34 |
- /* we will get no such attribute (16) if we try to set the referrals to NULL if
|
|
|
dc8c34 |
- there are no referrals - not an error */
|
|
|
dc8c34 |
- rc = LDAP_SUCCESS;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- } else { /* Replacing */
|
|
|
dc8c34 |
- rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set);
|
|
|
dc8c34 |
- if (rc == LDAP_SUCCESS && !chain_on_update){
|
|
|
dc8c34 |
- slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else { /* Replacing */
|
|
|
dc8c34 |
+ rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set);
|
|
|
dc8c34 |
+ if (rc == LDAP_SUCCESS && !chain_on_update){
|
|
|
dc8c34 |
+ slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) {
|
|
|
dc8c34 |
+ if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) {
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "repl_set_mtn_referrals: could "
|
|
|
dc8c34 |
- "not set referrals for replica %s: %d\n",
|
|
|
dc8c34 |
- slapi_sdn_get_dn(repl_root_sdn), rc);
|
|
|
dc8c34 |
+ "not set referrals for replica %s: %d\n", slapi_sdn_get_dn(repl_root_sdn), rc);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
charray_free(referrals_to_set);
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
index 6d2e6f6..5c9585f 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
@@ -71,6 +71,11 @@ void modify_init(modify_context *mc,struct backentry *old_entry)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int modify_apply_mods(modify_context *mc, Slapi_Mods *smods)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
+ return modify_apply_mods_ignore_error(mc, smods, -1);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+int modify_apply_mods_ignore_error(modify_context *mc, Slapi_Mods *smods, int error)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
int ret = 0;
|
|
|
dc8c34 |
/* Make a copy of the entry */
|
|
|
dc8c34 |
PR_ASSERT(mc->old_entry != NULL);
|
|
|
dc8c34 |
@@ -78,7 +83,7 @@ int modify_apply_mods(modify_context *mc, Slapi_Mods *smods)
|
|
|
dc8c34 |
mc->new_entry = backentry_dup(mc->old_entry);
|
|
|
dc8c34 |
PR_ASSERT(smods!=NULL);
|
|
|
dc8c34 |
if ( mods_have_effect (mc->new_entry->ep_entry, smods) ) {
|
|
|
dc8c34 |
- ret = entry_apply_mods( mc->new_entry->ep_entry, slapi_mods_get_ldapmods_byref(smods));
|
|
|
dc8c34 |
+ ret = entry_apply_mods_ignore_error( mc->new_entry->ep_entry, slapi_mods_get_ldapmods_byref(smods), error);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
mc->smods= smods;
|
|
|
dc8c34 |
return ret;
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
|
|
|
dc8c34 |
index a56069b..fd62df9 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/misc.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/misc.c
|
|
|
dc8c34 |
@@ -444,7 +444,7 @@ ldbm_txn_ruv_modify_context( Slapi_PBlock *pb, modify_context *mc )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
modify_init( mc, bentry );
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if (modify_apply_mods( mc, smods )) {
|
|
|
dc8c34 |
+ if (modify_apply_mods_ignore_error( mc, smods, LDAP_TYPE_OR_VALUE_EXISTS )) {
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_ANY, "Error: ldbm_txn_ruv_modify_context failed to apply updates to RUV entry\n",
|
|
|
dc8c34 |
0, 0, 0 );
|
|
|
dc8c34 |
rc = -1;
|
|
|
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 48b3164..a7fb06d 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
@@ -347,6 +347,7 @@ void modify_init(modify_context *mc,struct backentry *old_entry);
|
|
|
dc8c34 |
int modify_apply_mods(modify_context *mc, Slapi_Mods *smods);
|
|
|
dc8c34 |
int modify_term(modify_context *mc,backend *be);
|
|
|
dc8c34 |
int modify_switch_entries(modify_context *mc,backend *be);
|
|
|
dc8c34 |
+int modify_apply_mods_ignore_error(modify_context *mc, Slapi_Mods *smods, int error);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* add.c
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
index 6339a6f..58a9d51 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
@@ -3259,6 +3259,12 @@ int slapi_entry_apply_mod( Slapi_Entry *e, LDAPMod *mod )
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
entry_apply_mods( Slapi_Entry *e, LDAPMod **mods )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
+ return entry_apply_mods_ignore_error(e, mods, -1);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+entry_apply_mods_ignore_error( Slapi_Entry *e, LDAPMod **mods, int ignore_error )
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
int err;
|
|
|
dc8c34 |
LDAPMod **mp = NULL;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -3268,7 +3274,9 @@ entry_apply_mods( Slapi_Entry *e, LDAPMod **mods )
|
|
|
dc8c34 |
for ( mp = mods; mp && *mp; mp++ )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
err = entry_apply_mod( e, *mp );
|
|
|
dc8c34 |
- if ( err != LDAP_SUCCESS ) {
|
|
|
dc8c34 |
+ if(err == ignore_error){
|
|
|
dc8c34 |
+ (*mp)->mod_op = LDAP_MOD_IGNORE;
|
|
|
dc8c34 |
+ } else if ( err != LDAP_SUCCESS ) {
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
index f7b4d04..ddeac62 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
@@ -331,7 +331,7 @@ int entry_next_deleted_attribute( const Slapi_Entry *e, Slapi_Attr **a);
|
|
|
dc8c34 |
/* entry.c */
|
|
|
dc8c34 |
int entry_apply_mods( Slapi_Entry *e, LDAPMod **mods );
|
|
|
dc8c34 |
int is_type_protected(const char *type);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+int entry_apply_mods_ignore_error( Slapi_Entry *e, LDAPMod **mods, int ignore_error );
|
|
|
dc8c34 |
int slapi_entries_diff(Slapi_Entry **old_entries, Slapi_Entry **new_entries, int testall, const char *logging_prestr, const int force_update, void *plg_id);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* entrywsi.c */
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.7.11.7
|
|
|
dc8c34 |
|