ldap/servers/plugins/replication/repl5.h | 2
ldap/servers/plugins/replication/repl5_init.c | 3
ldap/servers/plugins/replication/repl5_plugins.c | 31 ++++++
ldap/servers/plugins/replication/repl5_replica.c | 23 ++++
ldap/servers/plugins/replication/repl5_replica_config.c | 76 ++++++++++++++++
ldap/servers/plugins/replication/repl5_ruv.c | 76 ++++++++++++++++
ldap/servers/plugins/replication/repl5_ruv.h | 2
7 files changed, 208 insertions(+), 5 deletions(-)
New commits:
commit 6c26f0ba8a33a7f1dff6a5b848e0dc39e1c9c41f
Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com>
Date: Thu May 2 15:24:13 2013 +0200
Ticket 47350 - Allow search to look up 'in memory RUV'
Bug Description:
On a running instance and for a given replica the RUV is an in memory data
structure.
This data structure is writen to disk at each update and there it is named database
RUV.
With ticket
https://fedorahosted.org/389/ticket/564, the update of the database RUV
would be done
asynchronously. The consequence is that the database RUV would be late compare to the
current
update status.
It is important for monitoring reason to look up the current update status and so to
be able to
read the in memory RUV
Fix Description:
The fix consists to return the in memory RUV if attributes "nsds50ruv"
and/or "nsruvReplicaLastModified" are
requested when reading the entry (replica_config_search):
cn=replica,cn=\"<suffix>\",cn=mapping tree,cn=config
In addition to provide backward compatibility, if the database ruv is lookup
(i.e. nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff,<suffix>), it actually
returns the in memory ruv
(i.e. cn=replica,cn=\"<suffix>\",cn=mapping tree,cn=config). This is
achieved with a registered MMR preop callback
(multimaster_preop_init), that is called when send the result entry
(SLAPI_PLUGIN_PRE_ENTRY_FN).
https://fedorahosted.org/389/ticket/47350
Reviewed by: Rich Meggison, Noriko Hosoi
Platforms tested: F17
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/replication/repl5.h
b/ldap/servers/plugins/replication/repl5.h
index c7639e3..8da2d3b 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -212,6 +212,7 @@ int multimaster_preop_modify (Slapi_PBlock *pb);
int multimaster_preop_modrdn (Slapi_PBlock *pb);
int multimaster_preop_search (Slapi_PBlock *pb);
int multimaster_preop_compare (Slapi_PBlock *pb);
+int multimaster_ruv_search(Slapi_PBlock *pb);
int multimaster_bepreop_add (Slapi_PBlock *pb);
int multimaster_bepreop_delete (Slapi_PBlock *pb);
int multimaster_bepreop_modify (Slapi_PBlock *pb);
@@ -591,6 +592,7 @@ void replica_set_tombstone_reap_interval (Replica *r, long interval);
void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv);
void replica_set_ruv_dirty (Replica *r);
void replica_write_ruv (Replica *r);
+Slapi_Entry *get_in_memory_ruv(Slapi_DN *suffix_sdn);
char *replica_get_dn(Replica *r);
void replica_check_for_tasks(Replica*r, Slapi_Entry *e);
void replica_update_state (time_t when, void *arg);
diff --git a/ldap/servers/plugins/replication/repl5_init.c
b/ldap/servers/plugins/replication/repl5_init.c
index 8471f00..1533db9 100644
--- a/ldap/servers/plugins/replication/repl5_init.c
+++ b/ldap/servers/plugins/replication/repl5_init.c
@@ -259,7 +259,8 @@ multimaster_preop_init( Slapi_PBlock *pb )
slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_MODIFY_FN, (void *) multimaster_preop_modify )
!= 0 ||
slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_MODRDN_FN, (void *) multimaster_preop_modrdn
) != 0 ||
slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void *) multimaster_preop_search
) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_COMPARE_FN, (void *)
multimaster_preop_compare ) != 0)
+ slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_COMPARE_FN, (void *)
multimaster_preop_compare ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_ENTRY_FN, (void *)
multimaster_ruv_search ) != 0)
{
slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_preop_init
failed\n" );
rc= -1;
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c
b/ldap/servers/plugins/replication/repl5_plugins.c
index 43c1596..cb5fe5c 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -640,6 +640,37 @@ multimaster_preop_compare (Slapi_PBlock *pb)
return 0;
}
+int
+multimaster_ruv_search(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e, *e_alt;
+ Slapi_DN *suffix_sdn;
+
+ slapi_pblock_get(pb, SLAPI_SEARCH_ENTRY_ORIG, &e);
+
+ if (e == NULL)
+ return 0;
+
+ if (is_ruv_tombstone_entry(e)) {
+ /* We are about to send back the database RUV, we need to return
+ * in memory RUV instead
+ */
+
+ /* Retrieve the suffix DN from the RUV entry */
+ suffix_sdn = slapi_sdn_new();
+ slapi_sdn_get_parent(slapi_entry_get_sdn(e), suffix_sdn);
+
+ /* Now set the in memory RUV into the pblock */
+ if ((e_alt = get_in_memory_ruv(suffix_sdn)) != NULL) {
+ slapi_pblock_set(pb, SLAPI_SEARCH_ENTRY_COPY, e_alt);
+ }
+
+ slapi_sdn_free(&suffix_sdn);
+ }
+
+ return 0;
+}
+
static void
purge_entry_state_information (Slapi_PBlock *pb)
{
diff --git a/ldap/servers/plugins/replication/repl5_replica.c
b/ldap/servers/plugins/replication/repl5_replica.c
index 5a19833..6c73d05 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -104,7 +104,7 @@ typedef struct reap_callback_data
/* Forward declarations of helper functions*/
-static Slapi_Entry* _replica_get_config_entry (const Slapi_DN *root);
+static Slapi_Entry* _replica_get_config_entry (const Slapi_DN *root, char **attrs);
static int _replica_check_validity (const Replica *r);
static int _replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext);
static int _replica_update_entry (Replica *r, Slapi_Entry *e, char *errortext);
@@ -139,7 +139,7 @@ replica_new(const Slapi_DN *root)
PR_ASSERT (root);
/* check if there is a replica associated with the tree */
- e = _replica_get_config_entry (root);
+ e = _replica_get_config_entry (root, NULL);
if (e)
{
errorbuf[0] = '\0';
@@ -1556,7 +1556,7 @@ int replica_check_for_data_reload (Replica *r, void *arg)
mapping tree node for the replica's backend */
static Slapi_Entry*
-_replica_get_config_entry (const Slapi_DN *root)
+_replica_get_config_entry (const Slapi_DN *root, char **attrs)
{
int rc = 0;
char *dn = NULL;
@@ -1573,7 +1573,7 @@ _replica_get_config_entry (const Slapi_DN *root)
}
pb = slapi_pblock_new ();
- slapi_search_internal_set_pb (pb, dn, LDAP_SCOPE_BASE, "objectclass=*", NULL,
0, NULL,
+ slapi_search_internal_set_pb (pb, dn, LDAP_SCOPE_BASE, "objectclass=*", attrs,
0, NULL,
NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
slapi_search_internal_pb (pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
@@ -1590,6 +1590,21 @@ _replica_get_config_entry (const Slapi_DN *root)
return e;
}
+/* It does an internal search to read the in memory RUV
+ * of the provided suffix
+ */
+Slapi_Entry *
+get_in_memory_ruv(Slapi_DN *suffix_sdn)
+{
+ char *attrs[3];
+
+ /* these two attributes needs to be asked when reading the RUV */
+ attrs[0] = type_ruvElement;
+ attrs[1] = type_ruvElementUpdatetime;
+ attrs[2] = NULL;
+ return(_replica_get_config_entry(suffix_sdn, attrs));
+}
+
char *
replica_get_dn(Replica *r)
{
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c
b/ldap/servers/plugins/replication/repl5_replica_config.c
index 77f748f..9dc9169 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -704,6 +704,70 @@ replica_config_delete (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry*
entryAfter
return SLAPI_DSE_CALLBACK_OK;
}
+static void
+replica_config_search_last_modified(Slapi_PBlock *pb, Slapi_Entry* e, Replica *replica)
+{
+ Object *ruv_obj = NULL;
+ RUV *ruv = NULL;
+ Slapi_Value **values;
+
+ if (replica == NULL)
+ return;
+ ruv_obj = replica_get_ruv(replica);
+ ruv = object_get_data(ruv_obj);
+
+ if ((values = ruv_last_modified_to_valuearray(ruv)) != NULL) {
+ slapi_entry_add_values_sv(e, type_ruvElementUpdatetime, values);
+ valuearray_free(&values);
+ }
+
+ object_release(ruv_obj);
+
+}
+
+static void
+replica_config_search_ruv(Slapi_PBlock *pb, Slapi_Entry* e, Replica *replica)
+{
+ Object *ruv_obj = NULL;
+ RUV *ruv = NULL;
+ Slapi_Value **values;
+
+ if (replica == NULL)
+ return;
+ ruv_obj = replica_get_ruv(replica);
+ ruv = object_get_data(ruv_obj);
+
+ if ((values = ruv_to_valuearray(ruv)) != NULL) {
+ slapi_entry_add_values_sv(e, type_ruvElement, values);
+ valuearray_free(&values);
+ }
+
+ object_release(ruv_obj);
+
+}
+
+/* Returns PR_TRUE if 'attr' is present in the search requested attributes
+ * else it returns PR_FALSE
+ */
+static PRBool
+search_requested_attr(Slapi_PBlock *pb, char *attr)
+{
+ char **attrs = NULL;
+ int i;
+
+ slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &attrs);
+ if ((attr == NULL) || (attrs == NULL))
+ return PR_FALSE;
+
+ for (i = 0; attrs[i] != NULL; i++) {
+ if (strcasecmp(attrs[i], attr) == 0) {
+ return PR_TRUE;
+ }
+ }
+
+ return PR_FALSE;
+}
+
static int
replica_config_search (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int
*returncode,
char *returntext, void *arg)
@@ -730,6 +794,18 @@ replica_config_search (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry*
entryAfter
if (replica) {
reapActive = replica_get_tombstone_reap_active(replica);
}
+
+ /* Check if the in memory ruv is requested */
+ if (search_requested_attr(pb, type_ruvElement)) {
+ replica_config_search_ruv(pb, e, replica);
+ }
+
+ /* Check if the last update time is requested */
+ if (search_requested_attr(pb, type_ruvElementUpdatetime)) {
+ replica_config_search_last_modified(pb, e, replica);
+ }
+
+
object_release (mtnode_ext->replica);
}
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c
b/ldap/servers/plugins/replication/repl5_ruv.c
index 107c4f0..43f2c84 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -1178,6 +1178,82 @@ ruv_get_cleaned_rids(RUV *ruv, ReplicaId *rids)
}
}
+/*
+ * This routine dump the ruv (last modified time) into a value array
+ * the call must free the returned value array
+ */
+Slapi_Value **
+ruv_last_modified_to_valuearray(RUV *ruv)
+{
+ RUVElement *ruv_e;
+ int cookie;
+ Slapi_Value *value;
+ Slapi_Value **values = NULL;
+ char *buffer;
+
+
+ /* Acquire the ruv lock */
+ slapi_rwlock_rdlock(ruv->lock);
+
+ /* Now loop for each RUVElement and store its string value into the valueset*/
+ for (ruv_e = dl_get_first(ruv->elements, &cookie);
+ NULL != ruv_e;
+ ruv_e = dl_get_next(ruv->elements, &cookie)) {
+
+ buffer = slapi_ch_smprintf("%s%d%s%s} %08lx", prefix_ruvcsn,
ruv_e->rid,
+ ruv_e->replica_purl == NULL ? "" : " ",
+ ruv_e->replica_purl == NULL ? "" : ruv_e->replica_purl,
+ ruv_e->last_modified);
+ value = slapi_value_new_string_passin(buffer);
+ valuearray_add_value(&values, value);
+ slapi_value_free(&value);
+ }
+
+ slapi_rwlock_unlock(ruv->lock);
+
+ return (values);
+}
+
+/*
+ * This routine dump the ruv (replicageneration and ruvElements) into a value array
+ * the call must free the returned value array
+ */
+Slapi_Value **
+ruv_to_valuearray(RUV *ruv)
+{
+ RUVElement *ruv_e;
+ int cookie;
+ Slapi_Value *value;
+ Slapi_Value **values = NULL;
+ struct berval bv;
+ char *buffer;
+
+ /* Acquire the ruv lock */
+ slapi_rwlock_rdlock(ruv->lock);
+
+ /* dump the replicageneration */
+ buffer = slapi_ch_smprintf("%s %s", prefix_replicageneration,
ruv->replGen);
+ value = slapi_value_new_string_passin(buffer);
+ valuearray_add_value(&values, value);
+ slapi_value_free(&value);
+
+ /* Now loop for each RUVElement and store its string value into the valueset*/
+ for (ruv_e = dl_get_first(ruv->elements, &cookie);
+ NULL != ruv_e;
+ ruv_e = dl_get_next(ruv->elements, &cookie)) {
+
+ ruv_element_to_string(ruv_e, &bv, NULL, 0);
+ value = slapi_value_new_berval(&bv);
+ slapi_ber_bvdone(&bv);
+ valuearray_add_value(&values, value);
+ slapi_value_free(&value);
+ }
+
+ slapi_rwlock_unlock(ruv->lock);
+
+ return (values);
+}
+
int
ruv_to_smod(const RUV *ruv, Slapi_Mod *smod)
{
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h
b/ldap/servers/plugins/replication/repl5_ruv.h
index 036951f..c9b85ac 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -125,6 +125,8 @@ int ruv_get_min_csn(const RUV *ruv, CSN **csn);
int ruv_get_max_csn(const RUV *ruv, CSN **csn);
int ruv_get_rid_max_csn(const RUV *ruv, CSN **csn, ReplicaId rid);
int ruv_enumerate_elements (const RUV *ruv, FNEnumRUV fn, void *arg);
+Slapi_Value **ruv_last_modified_to_valuearray(RUV *ruv);
+Slapi_Value **ruv_to_valuearray(RUV *ruv);
int ruv_to_smod(const RUV *ruv, Slapi_Mod *smod);
int ruv_last_modified_to_smod(const RUV *ruv, Slapi_Mod *smod);
int ruv_to_bervals(const RUV *ruv, struct berval ***bvals);