diff options
Diffstat (limited to 'libglusterfs/src/dict.c')
| -rw-r--r-- | libglusterfs/src/dict.c | 632 |
1 files changed, 317 insertions, 315 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index d75ce11c016..1d9be9217a6 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -16,19 +16,14 @@ #include <limits.h> #include <fnmatch.h> -#include "glusterfs.h" -#include "common-utils.h" -#include "dict.h" -#include "hashfn.h" -#include "logging.h" -#include "compat.h" -#include "compat-errno.h" -#include "byte-order.h" -#include "globals.h" -#include "statedump.h" -#include "libglusterfs-messages.h" - -#include "glusterfs-fops.h" +#include "glusterfs/dict.h" +#define XXH_INLINE_ALL +#include "xxhash.h" +#include "glusterfs/compat.h" +#include "glusterfs/compat-errno.h" +#include "glusterfs/byte-order.h" +#include "glusterfs/statedump.h" +#include "glusterfs/libglusterfs-messages.h" struct dict_cmp { dict_t *dict; @@ -55,15 +50,13 @@ struct dict_cmp { static data_t * get_new_data() { - data_t *data = NULL; + data_t *data = mem_get(THIS->ctx->dict_data_pool); - data = mem_get(THIS->ctx->dict_data_pool); if (!data) return NULL; GF_ATOMIC_INIT(data->refcount, 0); data->is_static = _gf_false; - LOCK_INIT(&data->lock); return data; } @@ -104,23 +97,17 @@ get_new_dict_full(int size_hint) } } + dict->free_pair.key = NULL; + dict->totkvlen = 0; LOCK_INIT(&dict->lock); return dict; } dict_t * -get_new_dict(void) -{ - return get_new_dict_full(1); -} - -dict_t * dict_new(void) { - dict_t *dict = NULL; - - dict = get_new_dict_full(1); + dict_t *dict = get_new_dict_full(1); if (dict) dict_ref(dict); @@ -132,6 +119,7 @@ int32_t is_data_equal(data_t *one, data_t *two) { struct iatt *iatt1, *iatt2; + struct mdata_iatt *mdata_iatt1, *mdata_iatt2; if (!one || !two || !one->data || !two->data) { gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, @@ -196,6 +184,24 @@ is_data_equal(data_t *one, data_t *two) */ return 1; } + if (one->data_type == GF_DATA_TYPE_MDATA) { + if ((one->len < sizeof(struct mdata_iatt)) || + (two->len < sizeof(struct mdata_iatt))) { + return 0; + } + mdata_iatt1 = (struct mdata_iatt *)one->data; + mdata_iatt2 = (struct mdata_iatt *)two->data; + + if (mdata_iatt1->ia_atime != mdata_iatt2->ia_atime || + mdata_iatt1->ia_mtime != mdata_iatt2->ia_mtime || + mdata_iatt1->ia_ctime != mdata_iatt2->ia_ctime || + mdata_iatt1->ia_atime_nsec != mdata_iatt2->ia_atime_nsec || + mdata_iatt1->ia_mtime_nsec != mdata_iatt2->ia_mtime_nsec || + mdata_iatt1->ia_ctime_nsec != mdata_iatt2->ia_ctime_nsec) { + return 0; + } + return 1; + } if (one->len != two->len) return 0; @@ -210,11 +216,8 @@ 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); + dict_t *two = cmp->dict; + data_t *value2 = dict_get(two, key1); if (value2) { if (cmp->value_ignore && cmp->value_ignore(key1)) @@ -291,8 +294,6 @@ void data_destroy(data_t *data) { if (data) { - LOCK_DESTROY(&data->lock); - if (!data->is_static) GF_FREE(data->data); @@ -317,13 +318,12 @@ data_copy(data_t *old) newdata->len = old->len; if (old->data) { - newdata->data = memdup(old->data, old->len); + newdata->data = gf_memdup(old->data, old->len); if (!newdata->data) goto err_out; } newdata->data_type = old->data_type; - LOCK_INIT(&newdata->lock); return newdata; err_out: @@ -337,7 +337,7 @@ err_out: * checked by callers. */ static data_pair_t * -dict_lookup_common(dict_t *this, char *key, uint32_t hash) +dict_lookup_common(const dict_t *this, const char *key, const uint32_t hash) { int hashval = 0; data_pair_t *pair; @@ -359,8 +359,6 @@ dict_lookup_common(dict_t *this, char *key, uint32_t hash) int32_t dict_lookup(dict_t *this, char *key, data_t **data) { - uint32_t hash; - if (!this || !key || !data) { gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, "!this || !key || " @@ -370,7 +368,7 @@ dict_lookup(dict_t *this, char *key, data_t **data) data_pair_t *tmp = NULL; - hash = SuperFastHash(key, strlen(key)); + uint32_t hash = (uint32_t)XXH64(key, strlen(key), 0); LOCK(&this->lock); { @@ -386,8 +384,8 @@ dict_lookup(dict_t *this, char *key, data_t **data) } static int32_t -dict_set_lk(dict_t *this, char *key, data_t *value, const uint32_t hash, - gf_boolean_t replace) +dict_set_lk(dict_t *this, char *key, const int key_len, data_t *value, + const uint32_t hash, gf_boolean_t replace) { int hashval = 0; data_pair_t *pair; @@ -401,19 +399,19 @@ dict_set_lk(dict_t *this, char *key, data_t *value, const uint32_t hash, return -1; } key_free = 1; - key_hash = SuperFastHash(key, keylen); + key_hash = (uint32_t)XXH64(key, keylen, 0); } else { - keylen = strlen(key); + keylen = key_len; key_hash = hash; } /* Search for a existing key if 'replace' is asked for */ if (replace) { pair = dict_lookup_common(this, key, key_hash); - if (pair) { data_t *unref_data = pair->value; pair->value = data_ref(value); + this->totkvlen += (value->len - unref_data->len); data_unref(unref_data); if (key_free) GF_FREE(key); @@ -422,16 +420,15 @@ dict_set_lk(dict_t *this, char *key, data_t *value, const uint32_t hash, } } - if (this->free_pair_in_use) { + if (this->free_pair.key) { /* the free_pair is used */ pair = mem_get(THIS->ctx->dict_pair_pool); if (!pair) { if (key_free) GF_FREE(key); return -1; } - } else { + } else { /* assign the pair to the free pair */ pair = &this->free_pair; - this->free_pair_in_use = _gf_true; } if (key_free) { @@ -441,9 +438,7 @@ dict_set_lk(dict_t *this, char *key, data_t *value, const uint32_t hash, } else { pair->key = (char *)GF_MALLOC(keylen + 1, gf_common_mt_char); if (!pair->key) { - if (pair == &this->free_pair) { - this->free_pair_in_use = _gf_false; - } else { + if (pair != &this->free_pair) { mem_put(pair); } return -1; @@ -452,6 +447,7 @@ dict_set_lk(dict_t *this, char *key, data_t *value, const uint32_t hash, } pair->key_hash = key_hash; pair->value = data_ref(value); + this->totkvlen += (keylen + 1 + value->len); /* If the divisor is 1, the modulo is always 0, * in such case avoid hash calculation. @@ -501,12 +497,12 @@ dict_setn(dict_t *this, char *key, const int keylen, data_t *value) } if (key) { - key_hash = SuperFastHash(key, keylen); + key_hash = (uint32_t)XXH64(key, keylen, 0); } LOCK(&this->lock); - ret = dict_set_lk(this, key, value, key_hash, 1); + ret = dict_set_lk(this, key, keylen, value, key_hash, 1); UNLOCK(&this->lock); @@ -535,12 +531,12 @@ dict_addn(dict_t *this, char *key, const int keylen, data_t *value) } if (key) { - key_hash = SuperFastHash(key, keylen); + key_hash = (uint32_t)XXH64(key, keylen, 0); } LOCK(&this->lock); - ret = dict_set_lk(this, key, value, key_hash, 0); + ret = dict_set_lk(this, key, keylen, value, key_hash, 0); UNLOCK(&this->lock); @@ -551,7 +547,7 @@ data_t * dict_get(dict_t *this, char *key) { if (!this || !key) { - gf_msg_callingfn("dict", GF_LOG_INFO, EINVAL, LG_MSG_INVALID_ARG, + gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG, "!this || key=%s", (key) ? key : "()"); return NULL; } @@ -566,12 +562,12 @@ dict_getn(dict_t *this, char *key, const int keylen) uint32_t hash; if (!this || !key) { - gf_msg_callingfn("dict", GF_LOG_INFO, EINVAL, LG_MSG_INVALID_ARG, + gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG, "!this || key=%s", (key) ? key : "()"); return NULL; } - hash = SuperFastHash(key, keylen); + hash = (uint32_t)XXH64(key, keylen, 0); LOCK(&this->lock); { @@ -629,7 +625,7 @@ dict_deln(dict_t *this, char *key, const int keylen) return; } - hash = SuperFastHash(key, keylen); + hash = (uint32_t)XXH64(key, keylen, 0); LOCK(&this->lock); @@ -649,6 +645,7 @@ dict_deln(dict_t *this, char *key, const int keylen) else this->members[hashval] = pair->hash_next; + this->totkvlen -= pair->value->len; data_unref(pair->value); if (pair->prev) @@ -659,9 +656,10 @@ dict_deln(dict_t *this, char *key, const int keylen) if (pair->next) pair->next->prev = pair->prev; + this->totkvlen -= (strlen(pair->key) + 1); GF_FREE(pair->key); if (pair == &this->free_pair) { - this->free_pair_in_use = _gf_false; + this->free_pair.key = NULL; } else { mem_put(pair); } @@ -701,16 +699,18 @@ dict_destroy(dict_t *this) GF_FREE(prev->key); if (prev != &this->free_pair) { mem_put(prev); + } else { + this->free_pair.key = NULL; } total_pairs++; prev = pair; } + this->totkvlen = 0; if (this->members != &this->members_internal) { mem_put(this->members); } - GF_FREE(this->extra_free); free(this->extra_stdfree); /* update 'ctx->stats.dict.details' using max_count */ @@ -742,7 +742,7 @@ dict_unref(dict_t *this) uint64_t ref = 0; if (!this) { - gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, + gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG, "dict is NULL"); return; } @@ -757,7 +757,7 @@ dict_t * dict_ref(dict_t *this) { if (!this) { - gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, + gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG, "dict is NULL"); return NULL; } @@ -769,7 +769,7 @@ dict_ref(dict_t *this) void data_unref(data_t *this) { - int32_t ref; + uint64_t ref; if (!this) { gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, @@ -809,6 +809,7 @@ int_to_data(int64_t value) data->len = gf_asprintf(&data->data, "%" PRId64, value); if (-1 == data->len) { gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } data->len++; /* account for terminating NULL */ @@ -828,6 +829,7 @@ data_from_int64(int64_t value) data->len = gf_asprintf(&data->data, "%" PRId64, value); if (-1 == data->len) { gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } data->len++; /* account for terminating NULL */ @@ -847,6 +849,7 @@ data_from_int32(int32_t value) data->len = gf_asprintf(&data->data, "%" PRId32, value); if (-1 == data->len) { gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } @@ -867,6 +870,7 @@ data_from_int16(int16_t value) data->len = gf_asprintf(&data->data, "%" PRId16, value); if (-1 == data->len) { gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } @@ -887,6 +891,7 @@ data_from_int8(int8_t value) data->len = gf_asprintf(&data->data, "%d", value); if (-1 == data->len) { gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } @@ -907,6 +912,7 @@ data_from_uint64(uint64_t value) data->len = gf_asprintf(&data->data, "%" PRIu64, value); if (-1 == data->len) { gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } @@ -919,9 +925,7 @@ data_from_uint64(uint64_t value) data_t * data_from_double(double value) { - data_t *data = NULL; - - data = get_new_data(); + data_t *data = get_new_data(); if (!data) { return NULL; @@ -929,6 +933,8 @@ data_from_double(double value) data->len = gf_asprintf(&data->data, "%f", value); if (data->len == -1) { + gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } data->len++; /* account for terminating NULL */ @@ -948,6 +954,7 @@ data_from_uint32(uint32_t value) data->len = gf_asprintf(&data->data, "%" PRIu32, value); if (-1 == data->len) { gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } @@ -967,6 +974,8 @@ data_from_uint16(uint16_t value) } data->len = gf_asprintf(&data->data, "%" PRIu16, value); if (-1 == data->len) { + gf_msg_debug("dict", 0, "asprintf failed"); + data_destroy(data); return NULL; } @@ -1094,6 +1103,7 @@ static char *data_type_name[GF_DATA_TYPE_MAX] = { [GF_DATA_TYPE_PTR] = "pointer", [GF_DATA_TYPE_GFUUID] = "gf-uuid", [GF_DATA_TYPE_IATT] = "iatt", + [GF_DATA_TYPE_MDATA] = "mdata", }; int64_t @@ -1101,119 +1111,146 @@ data_to_int64(data_t *data) { VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1); - return (int64_t)strtoull(data->data, NULL, 0); + char *endptr = NULL; + int64_t value = 0; + + errno = 0; + value = strtoll(data->data, &endptr, 0); + + if (endptr && *endptr != '\0') + /* Unrecognized characters at the end of string. */ + errno = EINVAL; + if (errno) { + gf_msg_callingfn("dict", GF_LOG_WARNING, errno, + LG_MSG_DATA_CONVERSION_ERROR, + "Error in data conversion: '%s' can't " + "be represented as int64_t", + data->data); + return -1; + } + return value; } +/* Like above but implies signed range check. */ + +#define DATA_TO_RANGED_SIGNED(endptr, value, data, type, min, max) \ + do { \ + errno = 0; \ + value = strtoll(data->data, &endptr, 0); \ + if (endptr && *endptr != '\0') \ + errno = EINVAL; \ + if (errno || value > max || value < min) { \ + gf_msg_callingfn("dict", GF_LOG_WARNING, errno, \ + LG_MSG_DATA_CONVERSION_ERROR, \ + "Error in data conversion: '%s' can't " \ + "be represented as " #type, \ + data->data); \ + return -1; \ + } \ + return (type)value; \ + } while (0) + int32_t data_to_int32(data_t *data) { - VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1); + char *endptr = NULL; + int64_t value = 0; - return strtoul(data->data, NULL, 0); + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1); + DATA_TO_RANGED_SIGNED(endptr, value, data, int32_t, INT_MIN, INT_MAX); } int16_t data_to_int16(data_t *data) { - VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1); - - int16_t value = 0; + char *endptr = NULL; + int64_t value = 0; - errno = 0; - value = strtol(data->data, NULL, 0); - - if ((value > SHRT_MAX) || (value < SHRT_MIN)) { - errno = ERANGE; - gf_msg_callingfn("dict", GF_LOG_WARNING, errno, - LG_MSG_DATA_CONVERSION_ERROR, - "Error in data" - " conversion: detected overflow"); - return -1; - } - - return (int16_t)value; + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1); + DATA_TO_RANGED_SIGNED(endptr, value, data, int16_t, SHRT_MIN, SHRT_MAX); } int8_t data_to_int8(data_t *data) { + char *endptr = NULL; + int64_t value = 0; + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1); + DATA_TO_RANGED_SIGNED(endptr, value, data, int8_t, CHAR_MIN, CHAR_MAX); +} - int8_t value = 0; +uint64_t +data_to_uint64(data_t *data) +{ + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); + + char *endptr = NULL; + uint64_t value = 0; errno = 0; - value = strtol(data->data, NULL, 0); + value = strtoull(data->data, &endptr, 0); - if ((value > SCHAR_MAX) || (value < SCHAR_MIN)) { - errno = ERANGE; + if (endptr && *endptr != '\0') + errno = EINVAL; + if (errno) { gf_msg_callingfn("dict", GF_LOG_WARNING, errno, LG_MSG_DATA_CONVERSION_ERROR, - "Error in data" - " conversion: detected overflow"); + "Error in data conversion: '%s' can't " + "be represented as uint64_t", + data->data); return -1; } - - return (int8_t)value; + return value; } -uint64_t -data_to_uint64(data_t *data) -{ - VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); +/* Like above but implies unsigned range check. */ - return strtoll(data->data, NULL, 0); -} +#define DATA_TO_RANGED_UNSIGNED(endptr, value, data, type, max) \ + do { \ + errno = 0; \ + value = strtoull(data->data, &endptr, 0); \ + if (endptr && *endptr != '\0') \ + errno = EINVAL; \ + if (errno || value > max) { \ + gf_msg_callingfn("dict", GF_LOG_WARNING, errno, \ + LG_MSG_DATA_CONVERSION_ERROR, \ + "Error in data conversion: '%s' can't " \ + "be represented as " #type, \ + data->data); \ + return -1; \ + } \ + return (type)value; \ + } while (0) uint32_t data_to_uint32(data_t *data) { - VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); + char *endptr = NULL; + uint64_t value = 0; - return strtol(data->data, NULL, 0); + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); + DATA_TO_RANGED_UNSIGNED(endptr, value, data, uint32_t, UINT_MAX); } uint16_t data_to_uint16(data_t *data) { - VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); - - uint16_t value = 0; + char *endptr = NULL; + uint64_t value = 0; - errno = 0; - value = strtol(data->data, NULL, 0); - - if ((USHRT_MAX - value) < 0) { - errno = ERANGE; - gf_msg_callingfn("dict", GF_LOG_WARNING, errno, - LG_MSG_DATA_CONVERSION_ERROR, - "Error in data conversion: " - "overflow detected"); - return -1; - } - - return (uint16_t)value; + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); + DATA_TO_RANGED_UNSIGNED(endptr, value, data, uint16_t, USHRT_MAX); } uint8_t data_to_uint8(data_t *data) { - VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); - - uint32_t value = 0; - - errno = 0; - value = strtol(data->data, NULL, 0); - - if ((UCHAR_MAX - (uint8_t)value) < 0) { - errno = ERANGE; - gf_msg_callingfn("dict", GF_LOG_WARNING, errno, - LG_MSG_DATA_CONVERSION_ERROR, - "data " - "conversion overflow detected"); - return -1; - } + char *endptr = NULL; + uint64_t value = 0; - return (uint8_t)value; + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1); + DATA_TO_RANGED_UNSIGNED(endptr, value, data, uint8_t, UCHAR_MAX); } char * @@ -1247,8 +1284,8 @@ data_to_iatt(data_t *data, char *key) * pass more data but are backward compatible (if the initial contents * of the struct are maintained, of course). */ if (data->len < sizeof(struct iatt)) { - gf_msg("glusterfs", GF_LOG_ERROR, ENOBUFS, LG_MSG_UNDERSIZED_BUF, - "data value for '%s' is smaller than expected", key); + gf_smsg("glusterfs", GF_LOG_ERROR, ENOBUFS, LG_MSG_UNDERSIZED_BUF, + "key=%s", key, NULL); return NULL; } @@ -1265,8 +1302,8 @@ int dict_remove_foreach_fn(dict_t *d, char *k, data_t *v, void *_tmp) { if (!d || !k) { - gf_msg("glusterfs", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ENTRY, - "%s is NULL", d ? "key" : "dictionary"); + gf_smsg("glusterfs", GF_LOG_WARNING, EINVAL, LG_MSG_KEY_OR_VALUE_NULL, + "d=%s", d ? "key" : "dictionary", NULL); return -1; } @@ -1285,9 +1322,7 @@ dict_foreach(dict_t *dict, int (*fn)(dict_t *this, char *key, data_t *value, void *data), void *data) { - int ret = 0; - - ret = dict_foreach_match(dict, dict_match_everything, NULL, fn, data); + int ret = dict_foreach_match(dict, dict_match_everything, NULL, fn, data); if (ret > 0) ret = 0; @@ -1318,10 +1353,9 @@ dict_foreach_match(dict_t *dict, int ret = -1; int count = 0; - data_pair_t *pairs = NULL; + data_pair_t *pairs = dict->members_list; data_pair_t *next = NULL; - pairs = dict->members_list; while (pairs) { next = pairs->next; if (match(dict, pairs->key, pairs->value, match_data)) { @@ -1372,10 +1406,9 @@ 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 *pairs = dict->members_list; data_pair_t *next = NULL; - pairs = dict->members_list; while (pairs) { next = pairs->next; @@ -1462,33 +1495,14 @@ fail: * -val error, val = errno */ -int -dict_get_with_ref(dict_t *this, char *key, data_t **data) -{ - if (!this || !key || !data) { - gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, - "dict OR key (%s) is NULL", key); - return -EINVAL; - } - - return dict_get_with_refn(this, key, strlen(key), data); -} - -int +static int dict_get_with_refn(dict_t *this, char *key, const int keylen, data_t **data) { data_pair_t *pair = NULL; int ret = -ENOENT; uint32_t hash; - if (!this || !key || !data) { - gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, - "dict OR key (%s) is NULL", key); - ret = -EINVAL; - goto err; - } - - hash = SuperFastHash(key, keylen); + hash = (uint32_t)XXH64(key, keylen, 0); LOCK(&this->lock); { @@ -1500,10 +1514,22 @@ dict_get_with_refn(dict_t *this, char *key, const int keylen, data_t **data) } } UNLOCK(&this->lock); -err: + return ret; } +int +dict_get_with_ref(dict_t *this, char *key, data_t **data) +{ + if (!this || !key || !data) { + gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, + "dict OR key (%s) is NULL", key); + return -EINVAL; + } + + return dict_get_with_refn(this, key, strlen(key), data); +} + static int data_to_ptr_common(data_t *data, void **val) { @@ -1677,7 +1703,7 @@ dict_get_int8(dict_t *this, char *key, int8_t *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -1723,7 +1749,7 @@ dict_get_int16(dict_t *this, char *key, int16_t *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -1795,7 +1821,7 @@ dict_get_int32(dict_t *this, char *key, int32_t *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -1838,10 +1864,9 @@ err: int dict_set_int32(dict_t *this, char *key, int32_t val) { - data_t *data = NULL; + data_t *data = data_from_int32(val); int ret = 0; - data = data_from_int32(val); if (!data) { ret = -EINVAL; goto err; @@ -1861,7 +1886,7 @@ dict_get_int64(dict_t *this, char *key, int64_t *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -1884,10 +1909,9 @@ err: int dict_set_int64(dict_t *this, char *key, int64_t val) { - data_t *data = NULL; + data_t *data = data_from_int64(val); int ret = 0; - data = data_from_int64(val); if (!data) { ret = -EINVAL; goto err; @@ -1907,7 +1931,7 @@ dict_get_uint16(dict_t *this, char *key, uint16_t *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -1930,10 +1954,9 @@ err: int dict_set_uint16(dict_t *this, char *key, uint16_t val) { - data_t *data = NULL; + data_t *data = data_from_uint16(val); int ret = 0; - data = data_from_uint16(val); if (!data) { ret = -EINVAL; goto err; @@ -1953,7 +1976,7 @@ dict_get_uint32(dict_t *this, char *key, uint32_t *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -1976,10 +1999,9 @@ err: int dict_set_uint32(dict_t *this, char *key, uint32_t val) { - data_t *data = NULL; + data_t *data = data_from_uint32(val); int ret = 0; - data = data_from_uint32(val); if (!data) { ret = -EINVAL; goto err; @@ -1999,7 +2021,7 @@ dict_get_uint64(dict_t *this, char *key, uint64_t *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -2022,10 +2044,9 @@ err: int dict_set_uint64(dict_t *this, char *key, uint64_t val) { - data_t *data = NULL; + data_t *data = data_from_uint64(val); int ret = 0; - data = data_from_uint64(val); if (!data) { ret = -EINVAL; goto err; @@ -2096,7 +2117,7 @@ _dict_modify_flag(dict_t *this, char *key, int flag, int op) */ GF_ASSERT(flag >= 0 && flag < DICT_MAX_FLAGS); - hash = SuperFastHash(key, strlen(key)); + hash = (uint32_t)XXH64(key, strlen(key), 0); LOCK(&this->lock); { pair = dict_lookup_common(this, key, hash); @@ -2110,8 +2131,8 @@ _dict_modify_flag(dict_t *this, char *key, int flag, int op) } else { ptr = GF_CALLOC(1, DICT_MAX_FLAGS / 8, gf_common_mt_char); if (!ptr) { - gf_msg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, - "unable to allocate flag bit array"); + gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, + "flag bit array", NULL); ret = -ENOMEM; goto err; } @@ -2119,8 +2140,8 @@ _dict_modify_flag(dict_t *this, char *key, int flag, int op) data = data_from_dynptr(ptr, DICT_MAX_FLAGS / 8); if (!data) { - gf_msg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, - "unable to allocate data"); + gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, "data", + NULL); GF_FREE(ptr); ret = -ENOMEM; goto err; @@ -2131,30 +2152,29 @@ _dict_modify_flag(dict_t *this, char *key, int flag, int op) else BIT_CLEAR((unsigned char *)(data->data), flag); - if (this->free_pair_in_use) { + if (this->free_pair.key) { /* the free pair is in use */ pair = mem_get0(THIS->ctx->dict_pair_pool); if (!pair) { - gf_msg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, - "unable to allocate dict pair"); + gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, + "dict pair", NULL); ret = -ENOMEM; goto err; } - } else { + } else { /* use the free pair */ pair = &this->free_pair; - this->free_pair_in_use = _gf_true; } pair->key = (char *)GF_MALLOC(strlen(key) + 1, gf_common_mt_char); if (!pair->key) { - gf_msg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, - "unable to allocate dict pair"); + gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, + "dict pair", NULL); ret = -ENOMEM; goto err; } strcpy(pair->key, key); pair->key_hash = hash; pair->value = data_ref(data); - + this->totkvlen += (strlen(key) + 1 + data->len); hashval = hash % this->hash_size; pair->hash_next = this->members[hashval]; this->members[hashval] = pair; @@ -2179,12 +2199,11 @@ err: UNLOCK(&this->lock); if (pair) { - if (pair->key) - free(pair->key); - - if (pair == &this->free_pair) { - this->free_pair_in_use = _gf_false; - } else { + if (pair->key) { + GF_FREE(pair->key); + pair->key = NULL; + } + if (pair != &this->free_pair) { mem_put(pair); } } @@ -2192,8 +2211,8 @@ err: if (data) data_destroy(data); - gf_msg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_DICT_SET_FAILED, - "unable to set key (%s) in dict ", key); + gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_DICT_SET_FAILED, "key=%s", key, + NULL); return ret; } @@ -2225,7 +2244,7 @@ dict_get_double(dict_t *this, char *key, double *val) data_t *data = NULL; int ret = 0; - if (!this || !key || !val) { + if (!val) { ret = -EINVAL; goto err; } @@ -2248,10 +2267,9 @@ err: int dict_set_double(dict_t *this, char *key, double val) { - data_t *data = NULL; + data_t *data = data_from_double(val); int ret = 0; - data = data_from_double(val); if (!data) { ret = -EINVAL; goto err; @@ -2268,10 +2286,9 @@ err: int dict_set_static_ptr(dict_t *this, char *key, void *ptr) { - data_t *data = NULL; + data_t *data = data_from_ptr_common(ptr, _gf_true); int ret = 0; - data = data_from_ptr_common(ptr, _gf_true); if (!data) { ret = -EINVAL; goto err; @@ -2288,10 +2305,9 @@ err: int dict_set_dynptr(dict_t *this, char *key, void *ptr, size_t len) { - data_t *data = NULL; + data_t *data = data_from_dynptr(ptr, len); int ret = 0; - data = data_from_dynptr(ptr, len); if (!data) { ret = -EINVAL; goto err; @@ -2311,7 +2327,7 @@ dict_get_ptr(dict_t *this, char *key, void **ptr) data_t *data = NULL; int ret = 0; - if (!this || !key || !ptr) { + if (!ptr) { ret = -EINVAL; goto err; } @@ -2341,7 +2357,7 @@ dict_get_ptr_and_len(dict_t *this, char *key, void **ptr, int *len) data_t *data = NULL; int ret = 0; - if (!this || !key || !ptr) { + if (!ptr) { ret = -EINVAL; goto err; } @@ -2399,7 +2415,7 @@ dict_get_str(dict_t *this, char *key, char **str) data_t *data = NULL; int ret = -EINVAL; - if (!this || !key || !str) { + if (!str) { goto err; } ret = dict_get_with_ref(this, key, &data); @@ -2421,10 +2437,9 @@ err: int dict_set_str(dict_t *this, char *key, char *str) { - data_t *data = NULL; + data_t *data = str_to_data(str); int ret = 0; - data = str_to_data(str); if (!data) { ret = -EINVAL; goto err; @@ -2464,10 +2479,9 @@ int dict_set_nstrn(dict_t *this, char *key, const int keylen, char *str, const int vallen) { - data_t *data = NULL; + data_t *data = strn_to_data(str, vallen); int ret = 0; - data = strn_to_data(str, vallen); if (!data) { ret = -EINVAL; goto err; @@ -2484,12 +2498,11 @@ err: int dict_set_dynstr_with_alloc(dict_t *this, char *key, const char *str) { - char *alloc_str = NULL; + char *alloc_str = gf_strdup(str); int ret = -1; - alloc_str = gf_strdup(str); if (!alloc_str) - return -1; + return ret; ret = dict_set_dynstr(this, key, alloc_str); if (ret == -EINVAL) @@ -2508,10 +2521,9 @@ dict_set_dynstr(dict_t *this, char *key, char *str) int dict_set_dynstrn(dict_t *this, char *key, const int keylen, char *str) { - data_t *data = NULL; + data_t *data = data_from_dynstr(str); int ret = 0; - data = data_from_dynstr(str); if (!data) { ret = -EINVAL; goto err; @@ -2530,10 +2542,9 @@ err: int dict_set_option(dict_t *this, char *key, char *str) { - data_t *data = NULL; + data_t *data = data_from_dynstr(str); int ret = 0; - data = data_from_dynstr(str); if (!data) { ret = -EINVAL; goto err; @@ -2552,9 +2563,8 @@ dict_add_dynstr_with_alloc(dict_t *this, char *key, char *str) { data_t *data = NULL; int ret = 0; - char *alloc_str = NULL; + char *alloc_str = gf_strdup(str); - alloc_str = gf_strdup(str); if (!alloc_str) goto out; @@ -2579,7 +2589,7 @@ dict_get_bin(dict_t *this, char *key, void **bin) data_t *data = NULL; int ret = -EINVAL; - if (!this || !key || !bin) { + if (!bin) { goto err; } @@ -2682,7 +2692,7 @@ dict_get_gfuuid(dict_t *this, char *key, uuid_t *gfid) data_t *data = NULL; int ret = -EINVAL; - if (!this || !key || !gfid) { + if (!gfid) { goto err; } ret = dict_get_with_ref(this, key, &data); @@ -2702,6 +2712,45 @@ err: } int +dict_set_mdata(dict_t *this, char *key, struct mdata_iatt *mdata, + bool is_static) +{ + return dict_set_bin_common(this, key, mdata, sizeof(struct mdata_iatt), + is_static, GF_DATA_TYPE_MDATA); +} + +int +dict_get_mdata(dict_t *this, char *key, struct mdata_iatt *mdata) +{ + data_t *data = NULL; + int ret = -EINVAL; + + if (!mdata) { + goto err; + } + ret = dict_get_with_ref(this, key, &data); + if (ret < 0) { + goto err; + } + + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_MDATA, key, -EINVAL); + if (data->len < sizeof(struct mdata_iatt)) { + gf_smsg("glusterfs", GF_LOG_ERROR, ENOBUFS, LG_MSG_UNDERSIZED_BUF, + "key=%s", key, NULL); + ret = -ENOBUFS; + goto err; + } + + memcpy(mdata, data->data, min(data->len, sizeof(struct mdata_iatt))); + +err: + if (data) + data_unref(data); + + return ret; +} + +int dict_set_iatt(dict_t *this, char *key, struct iatt *iatt, bool is_static) { return dict_set_bin_common(this, key, iatt, sizeof(struct iatt), is_static, @@ -2714,7 +2763,7 @@ dict_get_iatt(dict_t *this, char *key, struct iatt *iatt) data_t *data = NULL; int ret = -EINVAL; - if (!this || !key || !iatt) { + if (!iatt) { goto err; } ret = dict_get_with_ref(this, key, &data); @@ -2774,7 +2823,7 @@ dict_get_str_boolean(dict_t *this, char *key, int default_val) VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, key, -EINVAL); - ret = gf_string2boolean(data->data, &boo); + ret = gf_strn2boolean(data->data, data->len - 1, &boo); if (ret == -1) goto err; @@ -2794,6 +2843,7 @@ dict_rename_key(dict_t *this, char *key, char *replace_key) int ret = -EINVAL; uint32_t hash; uint32_t replacekey_hash; + int replacekey_len; /* replacing a key by itself is a NO-OP */ if (strcmp(key, replace_key) == 0) @@ -2805,8 +2855,9 @@ dict_rename_key(dict_t *this, char *key, char *replace_key) return ret; } - hash = SuperFastHash(key, strlen(key)); - replacekey_hash = SuperFastHash(replace_key, strlen(replace_key)); + hash = (uint32_t)XXH64(key, strlen(key), 0); + replacekey_len = strlen(replace_key); + replacekey_hash = (uint32_t)XXH64(replace_key, replacekey_len, 0); LOCK(&this->lock); { @@ -2815,8 +2866,8 @@ dict_rename_key(dict_t *this, char *key, char *replace_key) if (!pair) ret = -ENODATA; else - ret = dict_set_lk(this, replace_key, pair->value, replacekey_hash, - 1); + ret = dict_set_lk(this, replace_key, replacekey_len, pair->value, + replacekey_hash, 1); } UNLOCK(&this->lock); @@ -2835,10 +2886,6 @@ dict_rename_key(dict_t *this, char *key, char *replace_key) * 4 4 4 <key len> <value len> */ -#define DICT_HDR_LEN 4 -#define DICT_DATA_HDR_KEY_LEN 4 -#define DICT_DATA_HDR_VAL_LEN 4 - /** * dict_serialized_length_lk - return the length of serialized dict. This * procedure has to be called with this->lock held. @@ -2848,58 +2895,20 @@ dict_rename_key(dict_t *this, char *key, char *replace_key) * : failure: -errno */ -static int +int dict_serialized_length_lk(dict_t *this) { int ret = -EINVAL; int count = this->count; - int len = DICT_HDR_LEN; - data_pair_t *pair = this->members_list; + const int keyhdrlen = DICT_DATA_HDR_KEY_LEN + DICT_DATA_HDR_VAL_LEN; if (count < 0) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_COUNT_LESS_THAN_ZERO, - "count (%d) < 0!", count); + gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_COUNT_LESS_THAN_ZERO, + "count=%d", count, NULL); goto out; } - while (count) { - if (!pair) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, - LG_MSG_COUNT_LESS_THAN_DATA_PAIRS, - "less than count data pairs found!"); - goto out; - } - - len += DICT_DATA_HDR_KEY_LEN + DICT_DATA_HDR_VAL_LEN; - - if (!pair->key) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_NULL_PTR, - "pair->key is null!"); - goto out; - } - - len += strlen(pair->key) + 1 /* for '\0' */; - - if (!pair->value) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_NULL_PTR, - "pair->value is null!"); - goto out; - } - - if (pair->value->len < 0) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, - LG_MSG_VALUE_LENGTH_LESS_THAN_ZERO, "value->len (%d) < 0", - pair->value->len); - goto out; - } - - len += pair->value->len; - - pair = pair->next; - count--; - } - - ret = len; + ret = DICT_HDR_LEN + this->totkvlen + (count * keyhdrlen); out: return ret; } @@ -2926,14 +2935,13 @@ dict_serialize_lk(dict_t *this, char *buf) int32_t netword = 0; if (!buf) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, - "buf is null!"); + gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, NULL); goto out; } if (count < 0) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_COUNT_LESS_THAN_ZERO, - "count (%d) < 0!", count); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_COUNT_LESS_THAN_ZERO, + "count=%d", count, NULL); goto out; } @@ -2943,14 +2951,13 @@ dict_serialize_lk(dict_t *this, char *buf) while (count) { if (!pair) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_PAIRS_LESS_THAN_COUNT, - "less than count data pairs found!"); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_PAIRS_LESS_THAN_COUNT, + NULL); goto out; } if (!pair->key) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_PTR, - "pair->key is null!"); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_PTR, NULL); goto out; } @@ -2960,8 +2967,7 @@ dict_serialize_lk(dict_t *this, char *buf) buf += DICT_DATA_HDR_KEY_LEN; if (!pair->value) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_PTR, - "pair->value is null!"); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_PTR, NULL); goto out; } @@ -3109,8 +3115,8 @@ dict_unserialize(char *orig_buf, int32_t size, dict_t **fill) buf += DICT_HDR_LEN; if (count < 0) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_COUNT_LESS_THAN_ZERO, - "count (%d) <= 0", count); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_COUNT_LESS_THAN_ZERO, + "count=%d", count, NULL); goto out; } @@ -3175,12 +3181,12 @@ dict_unserialize(char *orig_buf, int32_t size, dict_t **fill) goto out; } value->len = vallen; - value->data = memdup(buf, vallen); + value->data = gf_memdup(buf, vallen); value->data_type = GF_DATA_TYPE_STR_OLD; value->is_static = _gf_false; buf += vallen; - ret = dict_add(*fill, key, value); + ret = dict_addn(*fill, key, keylen, value); if (ret < 0) goto out; } @@ -3266,32 +3272,30 @@ dict_serialize_value_with_delim_lk(dict_t *this, char *buf, int32_t *serz_len, data_pair_t *pair = this->members_list; if (!buf) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "buf is null"); + gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, NULL); goto out; } if (count < 0) { - gf_msg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, - "count (%d) < 0", count); + gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "count=%d", + count, NULL); goto out; } while (count) { if (!pair) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_PAIRS_LESS_THAN_COUNT, - "less than count data pairs found"); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_PAIRS_LESS_THAN_COUNT, + NULL); goto out; } if (!pair->key || !pair->value) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_KEY_OR_VALUE_NULL, - "key or value is null"); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_KEY_OR_VALUE_NULL, NULL); goto out; } if (!pair->value->data) { - gf_msg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_VALUE_IN_DICT, - "null value found in dict"); + gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_VALUE_IN_DICT, NULL); goto out; } @@ -3365,7 +3369,7 @@ dict_dump_to_log(dict_t *dict) { int ret = -1; char *dump = NULL; - int dump_size = 64 * 1024; + const int dump_size = 64 * 1024; char *format = "(%s:%s)"; if (!dict) { @@ -3383,12 +3387,11 @@ dict_dump_to_log(dict_t *dict) ret = dict_dump_to_str(dict, dump, dump_size, format); if (ret) { - gf_msg("dict", GF_LOG_WARNING, 0, LG_MSG_FAILED_TO_LOG_DICT, - "Failed to log dictionary"); + gf_smsg("dict", GF_LOG_WARNING, 0, LG_MSG_FAILED_TO_LOG_DICT, NULL); goto out; } - gf_msg("dict", GF_LOG_INFO, 0, LG_MSG_DICT_ERROR, "dict=%p (%s)", dict, - dump); + gf_smsg("dict", GF_LOG_INFO, 0, LG_MSG_DICT_ERROR, "dict=%p", dict, + "dump=%s", dump, NULL); out: GF_FREE(dump); @@ -3400,7 +3403,7 @@ dict_dump_to_statedump(dict_t *dict, char *dict_name, char *domain) { int ret = -1; char *dump = NULL; - int dump_size = 64 * 1024; + const int dump_size = 64 * 1024; char key[4096] = { 0, }; @@ -3421,8 +3424,8 @@ dict_dump_to_statedump(dict_t *dict, char *dict_name, char *domain) ret = dict_dump_to_str(dict, dump, dump_size, format); if (ret) { - gf_msg(domain, GF_LOG_WARNING, 0, LG_MSG_FAILED_TO_LOG_DICT, - "Failed to log dictionary %s", dict_name); + gf_smsg(domain, GF_LOG_WARNING, 0, LG_MSG_FAILED_TO_LOG_DICT, "name=%s", + dict_name, NULL); goto out; } gf_proc_dump_build_key(key, domain, "%s", dict_name); @@ -3438,10 +3441,9 @@ dict_t * dict_for_key_value(const char *name, const char *value, size_t size, gf_boolean_t is_static) { - dict_t *xattr = NULL; + dict_t *xattr = dict_new(); int ret = 0; - xattr = dict_new(); if (!xattr) return NULL; @@ -3473,7 +3475,7 @@ dict_has_key_from_array(dict_t *dict, char **strings, gf_boolean_t *result) LOCK(&dict->lock); { for (i = 0; strings[i]; i++) { - hash = SuperFastHash(strings[i], strlen(strings[i])); + hash = (uint32_t)XXH64(strings[i], strlen(strings[i]), 0); if (dict_lookup_common(dict, strings[i], hash)) { *result = _gf_true; goto unlock; |
