summaryrefslogtreecommitdiffstats
path: root/libglusterfs
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/src/dict.c87
-rw-r--r--libglusterfs/src/dict.h5
2 files changed, 91 insertions, 1 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c
index b8b6aeab248..ffc92e72724 100644
--- a/libglusterfs/src/dict.c
+++ b/libglusterfs/src/dict.c
@@ -31,6 +31,11 @@
#include "globals.h"
#include "statedump.h"
+struct dict_cmp {
+ dict_t *dict;
+ gf_boolean_t (*value_ignore) (char *k);
+};
+
data_t *
get_new_data ()
{
@@ -107,7 +112,6 @@ dict_new (void)
return dict;
}
-
int32_t
is_data_equal (data_t *one,
data_t *two)
@@ -134,6 +138,87 @@ is_data_equal (data_t *one,
return 0;
}
+static int
+key_value_cmp (dict_t *one, char *key1, data_t *value1, void *data)
+{
+ struct dict_cmp *cmp = data;
+ dict_t *two = NULL;
+ data_t *value2 = NULL;
+
+ two = cmp->dict;
+ value2 = dict_get (two, key1);
+
+ if (value2) {
+ if (cmp->value_ignore && cmp->value_ignore (key1))
+ return 0;
+
+ if (is_data_equal (value1, value2) == 1)
+ return 0;
+ }
+
+ if (value2 == NULL) {
+ gf_log (THIS->name, GF_LOG_DEBUG,
+ "'%s' found only on one dict", key1);
+ } else {
+ gf_log (THIS->name, GF_LOG_DEBUG, "'%s' is different in two "
+ "dicts (%u, %u)", key1, value1->len, value2->len);
+ }
+
+ return -1;
+}
+
+/* If both dicts are NULL then equal. If one of the dicts is NULL but the
+ * other has only ignorable keys then also they are equal. If both dicts are
+ * non-null then check if for each non-ignorable key, values are same or
+ * not. value_ignore function is used to skip comparing values for the keys
+ * which must be present in both the dictionaries but the value could be
+ * different.
+ */
+gf_boolean_t
+are_dicts_equal (dict_t *one, dict_t *two,
+ gf_boolean_t (*match) (dict_t *d, char *k, data_t *v,
+ void *data),
+ gf_boolean_t (*value_ignore) (char *k))
+{
+ int num_matches1 = 0;
+ int num_matches2 = 0;
+ struct dict_cmp cmp = {0};
+
+ if (one == two)
+ return _gf_true;
+
+ if (!match)
+ match = dict_match_everything;
+
+ cmp.dict = two;
+ cmp.value_ignore = value_ignore;
+ if (!two) {
+ num_matches1 = dict_foreach_match (one, match, NULL,
+ dict_null_foreach_fn, NULL);
+ goto done;
+ } else {
+ num_matches1 = dict_foreach_match (one, match, NULL,
+ key_value_cmp, &cmp);
+ }
+
+ if (num_matches1 == -1)
+ return _gf_false;
+
+ if ((num_matches1 == one->count) && (one->count == two->count))
+ return _gf_true;
+
+ num_matches2 = dict_foreach_match (two, match, NULL,
+ dict_null_foreach_fn, NULL);
+done:
+ /* If the number of matches is same in 'two' then for all the
+ * valid-keys that exist in 'one' the value matched and no extra valid
+ * keys exist in 'two' alone. Otherwise there exists at least one extra
+ * valid-key in 'two' which doesn't exist in 'one' */
+ if (num_matches1 == num_matches2)
+ return _gf_true;
+ return _gf_false;
+}
+
void
data_destroy (data_t *data)
{
diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h
index 3708eede06d..a9004e96a50 100644
--- a/libglusterfs/src/dict.h
+++ b/libglusterfs/src/dict.h
@@ -264,4 +264,9 @@ dict_match_everything (dict_t *d, char *k, data_t *v, void *data);
dict_t *
dict_for_key_value (const char *name, const char *value, size_t size);
+gf_boolean_t
+are_dicts_equal (dict_t *one, dict_t *two,
+ gf_boolean_t (*match) (dict_t *d, char *k, data_t *v,
+ void *data),
+ gf_boolean_t (*value_ignore) (char *k));
#endif