diff options
Diffstat (limited to 'libglusterfs')
-rw-r--r-- | libglusterfs/src/dict.c | 87 | ||||
-rw-r--r-- | libglusterfs/src/dict.h | 5 |
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 |