summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/dict.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/dict.c')
-rw-r--r--libglusterfs/src/dict.c227
1 files changed, 173 insertions, 54 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c
index 5ae61fd3d..3b7ddce5e 100644
--- a/libglusterfs/src/dict.c
+++ b/libglusterfs/src/dict.c
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <inttypes.h>
#include <limits.h>
+#include <fnmatch.h>
#ifndef _CONFIG_H
#define _CONFIG_H
@@ -181,8 +182,7 @@ data_copy (data_t *old)
err_out:
- if (newdata->data)
- FREE (newdata->data);
+ FREE (newdata->data);
mem_put (newdata);
return NULL;
@@ -209,7 +209,7 @@ _dict_lookup (dict_t *this, char *key)
}
int32_t
-dict_lookup (dict_t *this, char *key, data_pair_t **data)
+dict_lookup (dict_t *this, char *key, data_t **data)
{
if (!this || !key || !data) {
gf_log_callingfn ("dict", GF_LOG_WARNING,
@@ -217,22 +217,22 @@ dict_lookup (dict_t *this, char *key, data_pair_t **data)
return -1;
}
+ data_pair_t *tmp = NULL;
LOCK (&this->lock);
{
- *data = _dict_lookup (this, key);
+ tmp = _dict_lookup (this, key);
}
UNLOCK (&this->lock);
- if (*data)
- return 0;
- else
+
+ if (!tmp)
return -1;
+ *data = tmp->value;
+ return 0;
}
static int32_t
-_dict_set (dict_t *this,
- char *key,
- data_t *value)
+_dict_set (dict_t *this, char *key, data_t *value, gf_boolean_t replace)
{
int hashval;
data_pair_t *pair;
@@ -251,17 +251,22 @@ _dict_set (dict_t *this,
tmp = SuperFastHash (key, strlen (key));
hashval = (tmp % this->hash_size);
- pair = _dict_lookup (this, key);
- if (pair) {
- data_t *unref_data = pair->value;
- pair->value = data_ref (value);
- data_unref (unref_data);
- if (key_free)
- GF_FREE (key);
- /* Indicates duplicate key */
- return 0;
+ /* Search for a existing key if 'replace' is asked for */
+ if (replace) {
+ pair = _dict_lookup (this, key);
+
+ if (pair) {
+ data_t *unref_data = pair->value;
+ pair->value = data_ref (value);
+ data_unref (unref_data);
+ if (key_free)
+ GF_FREE (key);
+ /* Indicates duplicate key */
+ return 0;
+ }
}
+
if (this->free_pair_in_use) {
pair = mem_get0 (THIS->ctx->dict_pair_pool);
if (!pair) {
@@ -326,7 +331,28 @@ dict_set (dict_t *this,
LOCK (&this->lock);
- ret = _dict_set (this, key, value);
+ ret = _dict_set (this, key, value, 1);
+
+ UNLOCK (&this->lock);
+
+ return ret;
+}
+
+
+int32_t
+dict_add (dict_t *this, char *key, data_t *value)
+{
+ int32_t ret;
+
+ if (!this || !value) {
+ gf_log_callingfn ("dict", GF_LOG_WARNING,
+ "!this || !value for key=%s", key);
+ return -1;
+ }
+
+ LOCK (&this->lock);
+
+ ret = _dict_set (this, key, value, 0);
UNLOCK (&this->lock);
@@ -436,10 +462,8 @@ dict_destroy (dict_t *this)
mem_put (this->members);
}
- if (this->extra_free)
- GF_FREE (this->extra_free);
- if (this->extra_stdfree)
- free (this->extra_stdfree);
+ GF_FREE (this->extra_free);
+ free (this->extra_stdfree);
if (!this->is_static)
mem_put (this);
@@ -872,7 +896,7 @@ data_to_int32 (data_t *data)
int16_t
data_to_int16 (data_t *data)
{
- int16_t value = 0;
+ int16_t value = 0;
if (!data) {
gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL");
@@ -886,16 +910,16 @@ data_to_int16 (data_t *data)
memcpy (str, data->data, data->len);
str[data->len] = '\0';
- errno = 0;
- value = strtol (str, NULL, 0);
+ errno = 0;
+ value = strtol (str, NULL, 0);
- if ((SHRT_MAX > value) || (SHRT_MIN < value)) {
- errno = ERANGE;
+ if ((value > SHRT_MAX) || (value < SHRT_MIN)) {
+ errno = ERANGE;
gf_log_callingfn ("dict", GF_LOG_WARNING,
- "Error in data conversion: "
- "detected overflow");
+ "Error in data conversion: "
+ "detected overflow");
return -1;
- }
+ }
return (int16_t)value;
}
@@ -904,7 +928,7 @@ data_to_int16 (data_t *data)
int8_t
data_to_int8 (data_t *data)
{
- int32_t value = 0;
+ int8_t value = 0;
if (!data) {
gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL");
@@ -918,16 +942,16 @@ data_to_int8 (data_t *data)
memcpy (str, data->data, data->len);
str[data->len] = '\0';
- errno = 0;
- value = strtol (str, NULL, 0);
+ errno = 0;
+ value = strtol (str, NULL, 0);
- if ((SCHAR_MAX > value) || (SCHAR_MIN < value)) {
- errno = ERANGE;
+ if ((value > SCHAR_MAX) || (value < SCHAR_MIN)) {
+ errno = ERANGE;
gf_log_callingfn ("dict", GF_LOG_WARNING,
- "Error in data conversion: "
- "detected overflow");
+ "Error in data conversion: "
+ "detected overflow");
return -1;
- }
+ }
return (int8_t)value;
}
@@ -1054,47 +1078,141 @@ data_to_bin (data_t *data)
return data->data;
}
-void
+int
+dict_null_foreach_fn (dict_t *d, char *k,
+ data_t *v, void *tmp)
+{
+ return 0;
+}
+
+int
dict_foreach (dict_t *dict,
- void (*fn)(dict_t *this,
- char *key,
- data_t *value,
- void *data),
+ int (*fn)(dict_t *this,
+ char *key,
+ data_t *value,
+ void *data),
void *data)
{
if (!dict) {
gf_log_callingfn ("dict", GF_LOG_WARNING,
"dict is NULL");
- return;
+ return -1;
}
- data_pair_t *pairs = dict->members_list;
- data_pair_t *next = NULL;
+ int ret = -1;
+ data_pair_t *pairs = NULL;
+ data_pair_t *next = NULL;
+ pairs = dict->members_list;
while (pairs) {
next = pairs->next;
- fn (dict, pairs->key, pairs->value, data);
+ ret = fn (dict, pairs->key, pairs->value, data);
+ if (ret == -1)
+ return -1;
pairs = next;
}
+
+ return 0;
+}
+
+/* return values:
+ -1 = failure,
+ 0 = no matches found,
+ +n = n number of matches
+*/
+int
+dict_foreach_fnmatch (dict_t *dict, char *pattern,
+ int (*fn)(dict_t *this,
+ char *key,
+ data_t *value,
+ void *data),
+ void *data)
+{
+ if (!dict) {
+ gf_log_callingfn ("dict", GF_LOG_WARNING,
+ "dict is NULL");
+ return 0;
+ }
+
+ int ret = -1;
+ int count = 0;
+ data_pair_t *pairs = NULL;
+ data_pair_t *next = NULL;
+
+ pairs = dict->members_list;
+ while (pairs) {
+ next = pairs->next;
+ if (!fnmatch (pattern, pairs->key, 0)) {
+ ret = fn (dict, pairs->key, pairs->value, data);
+ if (ret == -1)
+ return -1;
+ count++;
+ }
+ pairs = next;
+ }
+
+ return count;
}
-static void
+/**
+ * dict_keys_join - pack the keys of the dictionary in a buffer.
+ *
+ * @value : buffer in which the keys will be packed (can be NULL)
+ * @size : size of the buffer which is sent (can be 0, in which case buffer
+ * is not packed but only length is returned)
+ * @dict : dictionary of which all the keys will be packed
+ * @filter_fn : keys matched in filter_fn() is counted.
+ *
+ * @return : @length of string after joining keys.
+ *
+ */
+
+int
+dict_keys_join (void *value, int size, dict_t *dict,
+ int (*filter_fn)(char *k))
+{
+ int len = 0;
+ data_pair_t *pairs = NULL;
+ data_pair_t *next = NULL;
+
+ pairs = dict->members_list;
+ while (pairs) {
+ next = pairs->next;
+
+ if (filter_fn && filter_fn (pairs->key)){
+ pairs = next;
+ continue;
+ }
+
+ if (value && (size > len))
+ strncpy (value + len, pairs->key, size - len);
+
+ len += (strlen (pairs->key) + 1);
+
+ pairs = next;
+ }
+
+ return len;
+}
+
+static int
_copy (dict_t *unused,
char *key,
data_t *value,
void *newdict)
{
- dict_set ((dict_t *)newdict, key, (value));
+ return dict_set ((dict_t *)newdict, key, (value));
}
-static void
+static int
_remove (dict_t *dict,
char *key,
data_t *value,
void *unused)
{
dict_del ((dict_t *)dict, key);
+ return 0;
}
@@ -2458,6 +2576,7 @@ dict_unserialize (char *orig_buf, int32_t size, dict_t **fill)
"available (%lu) < required (%lu)",
(long)(orig_buf + size),
(long)(buf + vallen));
+ goto out;
}
value = get_new_data ();
value->len = vallen;
@@ -2465,7 +2584,7 @@ dict_unserialize (char *orig_buf, int32_t size, dict_t **fill)
value->is_static = 0;
buf += vallen;
- dict_set (*fill, key, value);
+ dict_add (*fill, key, value);
}
ret = 0;
@@ -2486,7 +2605,7 @@ out:
*/
int32_t
-dict_allocate_and_serialize (dict_t *this, char **buf, size_t *length)
+dict_allocate_and_serialize (dict_t *this, char **buf, u_int *length)
{
int ret = -EINVAL;
ssize_t len = 0;