From a8d8e31362b90ac4f45927d269fa7d09654bf103 Mon Sep 17 00:00:00 2001
From: "Thierry bordaz (tbordaz)" <tbordaz@redhat.com>
Date: Thu, 2 May 2013 15:24:13 +0200
Subject: [PATCH] Ticket 47350 - Allow search to look up 'in memory RUV'

Bug Description:

	Allows a search to look up 'in memory RUV'

Fix Description:

	If the attribute "nsds50ruv" is requested when reading the replica entry,  the fix
	consist to return the RUV dump into the replica entry if the attribute 'nsds50ruv' is requested

https://fedorahosted.org/389/ticket/47350

Reviewed by: Rich Meggison

Platforms tested: F17

Flag Day: no

Doc impact: no
---
 .../plugins/replication/repl5_replica_config.c     | 49 ++++++++++++++++++++++
 ldap/servers/plugins/replication/repl5_ruv.c       | 39 +++++++++++++++++
 ldap/servers/plugins/replication/repl5_ruv.h       |  1 +
 3 files changed, 89 insertions(+)

diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 77f748f..8963f79 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -704,6 +704,49 @@ replica_config_delete (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter
 	return SLAPI_DSE_CALLBACK_OK;
 }
 
+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 (strncasecmp(*attrs, attr, strlen(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 +773,12 @@ 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);
+                }
+                
 		object_release (mtnode_ext->replica);
 	}
 
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index 9ce9768..114c2cc 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -1161,6 +1161,45 @@ ruv_get_cleaned_rids(RUV *ruv, ReplicaId *rids)
     }
 }
 
+/* 
+ * 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_string_passin(bv.bv_val);
+                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..6b88fb4 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -125,6 +125,7 @@ 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_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);
-- 
1.7.11.7

