"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/libglusterfs/src/dict.c" (16 Sep 2020, 79377 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dict.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
    3   This file is part of GlusterFS.
    4 
    5   This file is licensed to you under your choice of the GNU Lesser
    6   General Public License, version 3 or any later version (LGPLv3 or
    7   later), or the GNU General Public License, version 2 (GPLv2), in all
    8   cases as published by the Free Software Foundation.
    9 */
   10 
   11 #include <unistd.h>
   12 #include <string.h>
   13 #include <stdlib.h>
   14 #include <stdio.h>
   15 #include <inttypes.h>
   16 #include <limits.h>
   17 #include <fnmatch.h>
   18 
   19 #include "glusterfs/dict.h"
   20 #define XXH_INLINE_ALL
   21 #include "xxhash.h"
   22 #include "glusterfs/compat.h"
   23 #include "glusterfs/compat-errno.h"
   24 #include "glusterfs/byte-order.h"
   25 #include "glusterfs/statedump.h"
   26 #include "glusterfs/libglusterfs-messages.h"
   27 
   28 struct dict_cmp {
   29     dict_t *dict;
   30     gf_boolean_t (*value_ignore)(char *k);
   31 };
   32 
   33 #define VALIDATE_DATA_AND_LOG(data, type, key, ret_val)                        \
   34     do {                                                                       \
   35         if (!data || !data->data) {                                            \
   36             gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG, \
   37                              "data is NULL");                                  \
   38             return ret_val;                                                    \
   39         }                                                                      \
   40         /* Not of the asked type, or old version */                            \
   41         if ((data->data_type != type) &&                                       \
   42             (data->data_type != GF_DATA_TYPE_STR_OLD)) {                       \
   43             gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG, \
   44                              "key %s, %s type asked, has %s type", key,        \
   45                              data_type_name[type],                             \
   46                              data_type_name[data->data_type]);                 \
   47         }                                                                      \
   48     } while (0)
   49 
   50 static data_t *
   51 get_new_data()
   52 {
   53     data_t *data = mem_get(THIS->ctx->dict_data_pool);
   54 
   55     if (!data)
   56         return NULL;
   57 
   58     GF_ATOMIC_INIT(data->refcount, 0);
   59     data->is_static = _gf_false;
   60 
   61     return data;
   62 }
   63 
   64 static dict_t *
   65 get_new_dict_full(int size_hint)
   66 {
   67     dict_t *dict = mem_get0(THIS->ctx->dict_pool);
   68 
   69     if (!dict) {
   70         return NULL;
   71     }
   72 
   73     dict->hash_size = size_hint;
   74     if (size_hint == 1) {
   75         /*
   76          * This is the only case we ever see currently.  If we ever
   77          * need to support resizing the hash table, the resize function
   78          * will have to take into account the possibility that
   79          * "members" is not separately allocated (i.e. don't just call
   80          * realloc() blindly.
   81          */
   82         dict->members = &dict->members_internal;
   83     } else {
   84         /*
   85          * We actually need to allocate space for size_hint *pointers*
   86          * but we actually allocate space for one *structure*.  Since
   87          * a data_pair_t consists of five pointers, we're wasting four
   88          * pointers' worth for N=1, and will overrun what we allocated
   89          * for N>5.  If anybody ever starts using size_hint, we'll need
   90          * to fix this.
   91          */
   92         GF_ASSERT(size_hint <= (sizeof(data_pair_t) / sizeof(data_pair_t *)));
   93         dict->members = mem_get0(THIS->ctx->dict_pair_pool);
   94         if (!dict->members) {
   95             mem_put(dict);
   96             return NULL;
   97         }
   98     }
   99 
  100     dict->free_pair.key = NULL;
  101     LOCK_INIT(&dict->lock);
  102 
  103     return dict;
  104 }
  105 
  106 dict_t *
  107 dict_new(void)
  108 {
  109     dict_t *dict = get_new_dict_full(1);
  110 
  111     if (dict)
  112         dict_ref(dict);
  113 
  114     return dict;
  115 }
  116 
  117 int32_t
  118 is_data_equal(data_t *one, data_t *two)
  119 {
  120     struct iatt *iatt1, *iatt2;
  121     struct mdata_iatt *mdata_iatt1, *mdata_iatt2;
  122 
  123     if (!one || !two || !one->data || !two->data) {
  124         gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
  125                          "input arguments are provided "
  126                          "with value data_t as NULL");
  127         return -1;
  128     }
  129 
  130     if (one == two)
  131         return 1;
  132 
  133     if (one->data == two->data)
  134         return 1;
  135 
  136     if (one->data_type != two->data_type) {
  137         return 0;
  138     }
  139 
  140     if (one->data_type == GF_DATA_TYPE_IATT) {
  141         if ((one->len < sizeof(struct iatt)) ||
  142             (two->len < sizeof(struct iatt))) {
  143             return 0;
  144         }
  145 
  146         iatt1 = (struct iatt *)one->data;
  147         iatt2 = (struct iatt *)two->data;
  148 
  149         /* Two iatt structs are considered equal if main fields are
  150          * equal, even if times differ.
  151          * TODO: maybe when ctime if fully operational we could
  152          *       enforce time matching. */
  153         if (iatt1->ia_ino != iatt2->ia_ino) {
  154             return 0;
  155         }
  156         if (iatt1->ia_type != iatt2->ia_type) {
  157             return 0;
  158         }
  159         if ((iatt1->ia_type == IA_IFBLK) || (iatt1->ia_type == IA_IFCHR)) {
  160             if (iatt1->ia_rdev != iatt2->ia_rdev) {
  161                 return 0;
  162             }
  163         }
  164         if (gf_uuid_compare(iatt1->ia_gfid, iatt2->ia_gfid) != 0) {
  165             return 0;
  166         }
  167 
  168         /* TODO: ia_uid, ia_gid, ia_prot and ia_size can be changed
  169          *       with some commands. Here we don't have enough
  170          *       information to decide if they should match or not. */
  171         /*
  172                         if ((iatt1->ia_uid != iatt2->ia_uid) ||
  173                             (iatt1->ia_gid != iatt2->ia_gid) ||
  174                             (st_mode_from_ia(iatt1->ia_prot, iatt1->ia_type) !=
  175                                     st_mode_from_ia(iatt2->ia_prot,
  176            iatt2->ia_type))) { return 0;
  177                         }
  178                         if (iatt1->ia_type == IA_IFREG) {
  179                                 if (iatt1->ia_size != iatt2->ia_size) {
  180                                         return 0;
  181                                 }
  182                         }
  183         */
  184         return 1;
  185     }
  186     if (one->data_type == GF_DATA_TYPE_MDATA) {
  187         if ((one->len < sizeof(struct mdata_iatt)) ||
  188             (two->len < sizeof(struct mdata_iatt))) {
  189             return 0;
  190         }
  191         mdata_iatt1 = (struct mdata_iatt *)one->data;
  192         mdata_iatt2 = (struct mdata_iatt *)two->data;
  193 
  194         if (mdata_iatt1->ia_atime != mdata_iatt2->ia_atime ||
  195             mdata_iatt1->ia_mtime != mdata_iatt2->ia_mtime ||
  196             mdata_iatt1->ia_ctime != mdata_iatt2->ia_ctime ||
  197             mdata_iatt1->ia_atime_nsec != mdata_iatt2->ia_atime_nsec ||
  198             mdata_iatt1->ia_mtime_nsec != mdata_iatt2->ia_mtime_nsec ||
  199             mdata_iatt1->ia_ctime_nsec != mdata_iatt2->ia_ctime_nsec) {
  200             return 0;
  201         }
  202         return 1;
  203     }
  204 
  205     if (one->len != two->len)
  206         return 0;
  207 
  208     if (memcmp(one->data, two->data, one->len) == 0)
  209         return 1;
  210 
  211     return 0;
  212 }
  213 
  214 static int
  215 key_value_cmp(dict_t *one, char *key1, data_t *value1, void *data)
  216 {
  217     struct dict_cmp *cmp = data;
  218     dict_t *two = cmp->dict;
  219     data_t *value2 = dict_get(two, key1);
  220 
  221     if (value2) {
  222         if (cmp->value_ignore && cmp->value_ignore(key1))
  223             return 0;
  224 
  225         if (is_data_equal(value1, value2) == 1)
  226             return 0;
  227     }
  228 
  229     if (value2 == NULL) {
  230         gf_msg_debug(THIS->name, 0, "'%s' found only on one dict", key1);
  231     } else {
  232         gf_msg_debug(THIS->name, 0,
  233                      "'%s' is different in two dicts "
  234                      "(%u, %u)",
  235                      key1, value1->len, value2->len);
  236     }
  237 
  238     return -1;
  239 }
  240 
  241 /* If both dicts are NULL then equal. If one of the dicts is NULL but the
  242  * other has only ignorable keys then also they are equal. If both dicts are
  243  * non-null then check if for each non-ignorable key, values are same or
  244  * not.  value_ignore function is used to skip comparing values for the keys
  245  * which must be present in both the dictionaries but the value could be
  246  * different.
  247  */
  248 gf_boolean_t
  249 are_dicts_equal(dict_t *one, dict_t *two,
  250                 gf_boolean_t (*match)(dict_t *d, char *k, data_t *v,
  251                                       void *data),
  252                 gf_boolean_t (*value_ignore)(char *k))
  253 {
  254     int num_matches1 = 0;
  255     int num_matches2 = 0;
  256     struct dict_cmp cmp = {0};
  257 
  258     if (one == two)
  259         return _gf_true;
  260 
  261     if (!match)
  262         match = dict_match_everything;
  263 
  264     if ((one == NULL) || (two == NULL)) {
  265         num_matches1 = dict_foreach_match(one ? one : two, match, NULL,
  266                                           dict_null_foreach_fn, NULL);
  267         goto done;
  268     }
  269 
  270     cmp.dict = two;
  271     cmp.value_ignore = value_ignore;
  272     num_matches1 = dict_foreach_match(one, match, NULL, key_value_cmp, &cmp);
  273 
  274     if (num_matches1 == -1)
  275         return _gf_false;
  276 
  277     if ((num_matches1 == one->count) && (one->count == two->count))
  278         return _gf_true;
  279 
  280     num_matches2 = dict_foreach_match(two, match, NULL, dict_null_foreach_fn,
  281                                       NULL);
  282 done:
  283     /* If the number of matches is same in 'two' then for all the
  284      * valid-keys that exist in 'one' the value matched and no extra valid
  285      * keys exist in 'two' alone. Otherwise there exists at least one extra
  286      * valid-key in 'two' which doesn't exist in 'one' */
  287     if (num_matches1 == num_matches2)
  288         return _gf_true;
  289     return _gf_false;
  290 }
  291 
  292 void
  293 data_destroy(data_t *data)
  294 {
  295     if (data) {
  296         if (!data->is_static)
  297             GF_FREE(data->data);
  298 
  299         data->len = 0xbabababa;
  300         mem_put(data);
  301     }
  302 }
  303 
  304 data_t *
  305 data_copy(data_t *old)
  306 {
  307     if (!old) {
  308         gf_msg_callingfn("dict", GF_LOG_WARNING, 0, LG_MSG_NULL_PTR,
  309                          "old is NULL");
  310         return NULL;
  311     }
  312 
  313     data_t *newdata = mem_get0(THIS->ctx->dict_data_pool);
  314     if (!newdata) {
  315         return NULL;
  316     }
  317 
  318     newdata->len = old->len;
  319     if (old->data) {
  320         newdata->data = gf_memdup(old->data, old->len);
  321         if (!newdata->data)
  322             goto err_out;
  323     }
  324     newdata->data_type = old->data_type;
  325 
  326     return newdata;
  327 
  328 err_out:
  329     mem_put(newdata);
  330 
  331     return NULL;
  332 }
  333 
  334 /* Always need to be called under lock
  335  * Always this and key variables are not null -
  336  * checked by callers.
  337  */
  338 static data_pair_t *
  339 dict_lookup_common(const dict_t *this, const char *key, const uint32_t hash)
  340 {
  341     int hashval = 0;
  342     data_pair_t *pair;
  343 
  344     /* If the divisor is 1, the modulo is always 0,
  345      * in such case avoid hash calculation.
  346      */
  347     if (this->hash_size != 1)
  348         hashval = hash % this->hash_size;
  349 
  350     for (pair = this->members[hashval]; pair != NULL; pair = pair->hash_next) {
  351         if (pair->key && (hash == pair->key_hash) && !strcmp(pair->key, key))
  352             return pair;
  353     }
  354 
  355     return NULL;
  356 }
  357 
  358 int32_t
  359 dict_lookup(dict_t *this, char *key, data_t **data)
  360 {
  361     if (!this || !key || !data) {
  362         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  363                          "!this || !key || "
  364                          "!data");
  365         return -1;
  366     }
  367 
  368     data_pair_t *tmp = NULL;
  369 
  370     uint32_t hash = (uint32_t)XXH64(key, strlen(key), 0);
  371 
  372     LOCK(&this->lock);
  373     {
  374         tmp = dict_lookup_common(this, key, hash);
  375     }
  376     UNLOCK(&this->lock);
  377 
  378     if (!tmp)
  379         return -1;
  380 
  381     *data = tmp->value;
  382     return 0;
  383 }
  384 
  385 static int32_t
  386 dict_set_lk(dict_t *this, char *key, const int key_len, data_t *value,
  387             const uint32_t hash, gf_boolean_t replace)
  388 {
  389     int hashval = 0;
  390     data_pair_t *pair;
  391     int key_free = 0;
  392     uint32_t key_hash;
  393     int keylen;
  394 
  395     if (!key) {
  396         keylen = gf_asprintf(&key, "ref:%p", value);
  397         if (-1 == keylen) {
  398             return -1;
  399         }
  400         key_free = 1;
  401         key_hash = (uint32_t)XXH64(key, keylen, 0);
  402     } else {
  403         keylen = key_len;
  404         key_hash = hash;
  405     }
  406 
  407     /* Search for a existing key if 'replace' is asked for */
  408     if (replace) {
  409         pair = dict_lookup_common(this, key, key_hash);
  410         if (pair) {
  411             data_t *unref_data = pair->value;
  412             pair->value = data_ref(value);
  413             data_unref(unref_data);
  414             if (key_free)
  415                 GF_FREE(key);
  416             /* Indicates duplicate key */
  417             return 0;
  418         }
  419     }
  420 
  421     if (this->free_pair.key) { /* the free_pair is used */
  422         pair = mem_get(THIS->ctx->dict_pair_pool);
  423         if (!pair) {
  424             if (key_free)
  425                 GF_FREE(key);
  426             return -1;
  427         }
  428     } else { /* assign the pair to the free pair */
  429         pair = &this->free_pair;
  430     }
  431 
  432     if (key_free) {
  433         /* It's ours.  Use it. */
  434         pair->key = key;
  435         key_free = 0;
  436     } else {
  437         pair->key = (char *)GF_MALLOC(keylen + 1, gf_common_mt_char);
  438         if (!pair->key) {
  439             if (pair != &this->free_pair) {
  440                 mem_put(pair);
  441             }
  442             return -1;
  443         }
  444         strcpy(pair->key, key);
  445     }
  446     pair->key_hash = key_hash;
  447     pair->value = data_ref(value);
  448 
  449     /* If the divisor is 1, the modulo is always 0,
  450      * in such case avoid hash calculation.
  451      */
  452     if (this->hash_size != 1) {
  453         hashval = (key_hash % this->hash_size);
  454     }
  455     pair->hash_next = this->members[hashval];
  456     this->members[hashval] = pair;
  457 
  458     pair->next = this->members_list;
  459     pair->prev = NULL;
  460     if (this->members_list)
  461         this->members_list->prev = pair;
  462     this->members_list = pair;
  463     this->count++;
  464 
  465     if (key_free)
  466         GF_FREE(key);
  467 
  468     if (this->max_count < this->count)
  469         this->max_count = this->count;
  470     return 0;
  471 }
  472 
  473 int32_t
  474 dict_set(dict_t *this, char *key, data_t *value)
  475 {
  476     if (key)
  477         return dict_setn(this, key, strlen(key), value);
  478     else
  479         return dict_setn(this, NULL, 0, value);
  480 }
  481 
  482 int32_t
  483 dict_setn(dict_t *this, char *key, const int keylen, data_t *value)
  484 {
  485     int32_t ret;
  486     uint32_t key_hash = 0;
  487 
  488     if (!this || !value) {
  489         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  490                          "!this || !value for "
  491                          "key=%s",
  492                          key);
  493         return -1;
  494     }
  495 
  496     if (key) {
  497         key_hash = (uint32_t)XXH64(key, keylen, 0);
  498     }
  499 
  500     LOCK(&this->lock);
  501 
  502     ret = dict_set_lk(this, key, keylen, value, key_hash, 1);
  503 
  504     UNLOCK(&this->lock);
  505 
  506     return ret;
  507 }
  508 
  509 int32_t
  510 dict_add(dict_t *this, char *key, data_t *value)
  511 {
  512     if (key)
  513         return dict_addn(this, key, strlen(key), value);
  514     else
  515         return dict_addn(this, NULL, 0, value);
  516 }
  517 
  518 int32_t
  519 dict_addn(dict_t *this, char *key, const int keylen, data_t *value)
  520 {
  521     int32_t ret;
  522     uint32_t key_hash = 0;
  523 
  524     if (!this || !value) {
  525         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  526                          "!this || !value for key=%s", key);
  527         return -1;
  528     }
  529 
  530     if (key) {
  531         key_hash = (uint32_t)XXH64(key, keylen, 0);
  532     }
  533 
  534     LOCK(&this->lock);
  535 
  536     ret = dict_set_lk(this, key, keylen, value, key_hash, 0);
  537 
  538     UNLOCK(&this->lock);
  539 
  540     return ret;
  541 }
  542 
  543 data_t *
  544 dict_get(dict_t *this, char *key)
  545 {
  546     if (!this || !key) {
  547         gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG,
  548                          "!this || key=%s", (key) ? key : "()");
  549         return NULL;
  550     }
  551 
  552     return dict_getn(this, key, strlen(key));
  553 }
  554 
  555 data_t *
  556 dict_getn(dict_t *this, char *key, const int keylen)
  557 {
  558     data_pair_t *pair;
  559     uint32_t hash;
  560 
  561     if (!this || !key) {
  562         gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG,
  563                          "!this || key=%s", (key) ? key : "()");
  564         return NULL;
  565     }
  566 
  567     hash = (uint32_t)XXH64(key, keylen, 0);
  568 
  569     LOCK(&this->lock);
  570     {
  571         pair = dict_lookup_common(this, key, hash);
  572     }
  573     UNLOCK(&this->lock);
  574 
  575     if (pair)
  576         return pair->value;
  577 
  578     return NULL;
  579 }
  580 
  581 int
  582 dict_key_count(dict_t *this)
  583 {
  584     int ret = -1;
  585 
  586     if (!this) {
  587         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  588                          "dict passed is NULL");
  589         return ret;
  590     }
  591 
  592     LOCK(&this->lock);
  593     {
  594         ret = this->count;
  595     }
  596     UNLOCK(&this->lock);
  597 
  598     return ret;
  599 }
  600 
  601 void
  602 dict_del(dict_t *this, char *key)
  603 {
  604     if (!this || !key) {
  605         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  606                          "!this || key=%s", key);
  607         return;
  608     }
  609 
  610     return dict_deln(this, key, strlen(key));
  611 }
  612 
  613 void
  614 dict_deln(dict_t *this, char *key, const int keylen)
  615 {
  616     int hashval = 0;
  617     uint32_t hash;
  618 
  619     if (!this || !key) {
  620         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  621                          "!this || key=%s", key);
  622         return;
  623     }
  624 
  625     hash = (uint32_t)XXH64(key, keylen, 0);
  626 
  627     LOCK(&this->lock);
  628 
  629     /* If the divisor is 1, the modulo is always 0,
  630      * in such case avoid hash calculation.
  631      */
  632     if (this->hash_size != 1)
  633         hashval = hash % this->hash_size;
  634 
  635     data_pair_t *pair = this->members[hashval];
  636     data_pair_t *prev = NULL;
  637 
  638     while (pair) {
  639         if ((hash == pair->key_hash) && strcmp(pair->key, key) == 0) {
  640             if (prev)
  641                 prev->hash_next = pair->hash_next;
  642             else
  643                 this->members[hashval] = pair->hash_next;
  644 
  645             data_unref(pair->value);
  646 
  647             if (pair->prev)
  648                 pair->prev->next = pair->next;
  649             else
  650                 this->members_list = pair->next;
  651 
  652             if (pair->next)
  653                 pair->next->prev = pair->prev;
  654 
  655             GF_FREE(pair->key);
  656             if (pair == &this->free_pair) {
  657                 this->free_pair.key = NULL;
  658             } else {
  659                 mem_put(pair);
  660             }
  661             this->count--;
  662             break;
  663         }
  664 
  665         prev = pair;
  666         pair = pair->hash_next;
  667     }
  668 
  669     UNLOCK(&this->lock);
  670 
  671     return;
  672 }
  673 
  674 void
  675 dict_destroy(dict_t *this)
  676 {
  677     if (!this) {
  678         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  679                          "dict is NULL");
  680         return;
  681     }
  682 
  683     data_pair_t *pair = this->members_list;
  684     data_pair_t *prev = this->members_list;
  685     glusterfs_ctx_t *ctx = NULL;
  686     uint64_t current_max = 0;
  687     uint32_t total_pairs = 0;
  688 
  689     LOCK_DESTROY(&this->lock);
  690 
  691     while (prev) {
  692         pair = pair->next;
  693         data_unref(prev->value);
  694         GF_FREE(prev->key);
  695         if (prev != &this->free_pair) {
  696             mem_put(prev);
  697         } else {
  698             this->free_pair.key = NULL;
  699         }
  700         total_pairs++;
  701         prev = pair;
  702     }
  703 
  704     if (this->members != &this->members_internal) {
  705         mem_put(this->members);
  706     }
  707 
  708     free(this->extra_stdfree);
  709 
  710     /* update 'ctx->stats.dict.details' using max_count */
  711     ctx = THIS->ctx;
  712 
  713     /* NOTE: below logic is not totaly race proof */
  714     /* thread0 and thread1 gets current_max as 10 */
  715     /* thread0 has 'this->max_count as 11 */
  716     /* thread1 has 'this->max_count as 20 */
  717     /* thread1 goes ahead and sets the max_dict_pairs to 20 */
  718     /* thread0 then goes and sets it to 11 */
  719     /* As it is for information purpose only, no functionality will be
  720        broken by this, but a point to consider about ATOMIC macros. */
  721     current_max = GF_ATOMIC_GET(ctx->stats.max_dict_pairs);
  722     if (current_max < this->max_count)
  723         GF_ATOMIC_INIT(ctx->stats.max_dict_pairs, this->max_count);
  724 
  725     GF_ATOMIC_ADD(ctx->stats.total_pairs_used, total_pairs);
  726     GF_ATOMIC_INC(ctx->stats.total_dicts_used);
  727 
  728     mem_put(this);
  729 
  730     return;
  731 }
  732 
  733 void
  734 dict_unref(dict_t *this)
  735 {
  736     uint64_t ref = 0;
  737 
  738     if (!this) {
  739         gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG,
  740                          "dict is NULL");
  741         return;
  742     }
  743 
  744     ref = GF_ATOMIC_DEC(this->refcount);
  745 
  746     if (!ref)
  747         dict_destroy(this);
  748 }
  749 
  750 dict_t *
  751 dict_ref(dict_t *this)
  752 {
  753     if (!this) {
  754         gf_msg_callingfn("dict", GF_LOG_DEBUG, EINVAL, LG_MSG_INVALID_ARG,
  755                          "dict is NULL");
  756         return NULL;
  757     }
  758 
  759     GF_ATOMIC_INC(this->refcount);
  760     return this;
  761 }
  762 
  763 void
  764 data_unref(data_t *this)
  765 {
  766     uint64_t ref;
  767 
  768     if (!this) {
  769         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  770                          "data is NULL");
  771         return;
  772     }
  773 
  774     ref = GF_ATOMIC_DEC(this->refcount);
  775 
  776     if (!ref)
  777         data_destroy(this);
  778 }
  779 
  780 data_t *
  781 data_ref(data_t *this)
  782 {
  783     if (!this) {
  784         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
  785                          "data is NULL");
  786         return NULL;
  787     }
  788 
  789     GF_ATOMIC_INC(this->refcount);
  790 
  791     return this;
  792 }
  793 
  794 data_t *
  795 int_to_data(int64_t value)
  796 {
  797     data_t *data = get_new_data();
  798 
  799     if (!data) {
  800         return NULL;
  801     }
  802 
  803     data->len = gf_asprintf(&data->data, "%" PRId64, value);
  804     if (-1 == data->len) {
  805         gf_msg_debug("dict", 0, "asprintf failed");
  806         data_destroy(data);
  807         return NULL;
  808     }
  809     data->len++; /* account for terminating NULL */
  810     data->data_type = GF_DATA_TYPE_INT;
  811 
  812     return data;
  813 }
  814 
  815 data_t *
  816 data_from_int64(int64_t value)
  817 {
  818     data_t *data = get_new_data();
  819 
  820     if (!data) {
  821         return NULL;
  822     }
  823     data->len = gf_asprintf(&data->data, "%" PRId64, value);
  824     if (-1 == data->len) {
  825         gf_msg_debug("dict", 0, "asprintf failed");
  826         data_destroy(data);
  827         return NULL;
  828     }
  829     data->len++; /* account for terminating NULL */
  830     data->data_type = GF_DATA_TYPE_INT;
  831 
  832     return data;
  833 }
  834 
  835 data_t *
  836 data_from_int32(int32_t value)
  837 {
  838     data_t *data = get_new_data();
  839 
  840     if (!data) {
  841         return NULL;
  842     }
  843     data->len = gf_asprintf(&data->data, "%" PRId32, value);
  844     if (-1 == data->len) {
  845         gf_msg_debug("dict", 0, "asprintf failed");
  846         data_destroy(data);
  847         return NULL;
  848     }
  849 
  850     data->len++; /* account for terminating NULL */
  851     data->data_type = GF_DATA_TYPE_INT;
  852 
  853     return data;
  854 }
  855 
  856 data_t *
  857 data_from_int16(int16_t value)
  858 {
  859     data_t *data = get_new_data();
  860 
  861     if (!data) {
  862         return NULL;
  863     }
  864     data->len = gf_asprintf(&data->data, "%" PRId16, value);
  865     if (-1 == data->len) {
  866         gf_msg_debug("dict", 0, "asprintf failed");
  867         data_destroy(data);
  868         return NULL;
  869     }
  870 
  871     data->len++; /* account for terminating NULL */
  872     data->data_type = GF_DATA_TYPE_INT;
  873 
  874     return data;
  875 }
  876 
  877 data_t *
  878 data_from_int8(int8_t value)
  879 {
  880     data_t *data = get_new_data();
  881 
  882     if (!data) {
  883         return NULL;
  884     }
  885     data->len = gf_asprintf(&data->data, "%d", value);
  886     if (-1 == data->len) {
  887         gf_msg_debug("dict", 0, "asprintf failed");
  888         data_destroy(data);
  889         return NULL;
  890     }
  891 
  892     data->len++; /* account for terminating NULL */
  893     data->data_type = GF_DATA_TYPE_INT;
  894 
  895     return data;
  896 }
  897 
  898 data_t *
  899 data_from_uint64(uint64_t value)
  900 {
  901     data_t *data = get_new_data();
  902 
  903     if (!data) {
  904         return NULL;
  905     }
  906     data->len = gf_asprintf(&data->data, "%" PRIu64, value);
  907     if (-1 == data->len) {
  908         gf_msg_debug("dict", 0, "asprintf failed");
  909         data_destroy(data);
  910         return NULL;
  911     }
  912 
  913     data->len++; /* account for terminating NULL */
  914     data->data_type = GF_DATA_TYPE_UINT;
  915 
  916     return data;
  917 }
  918 
  919 data_t *
  920 data_from_double(double value)
  921 {
  922     data_t *data = get_new_data();
  923 
  924     if (!data) {
  925         return NULL;
  926     }
  927 
  928     data->len = gf_asprintf(&data->data, "%f", value);
  929     if (data->len == -1) {
  930         gf_msg_debug("dict", 0, "asprintf failed");
  931         data_destroy(data);
  932         return NULL;
  933     }
  934     data->len++; /* account for terminating NULL */
  935     data->data_type = GF_DATA_TYPE_DOUBLE;
  936 
  937     return data;
  938 }
  939 
  940 data_t *
  941 data_from_uint32(uint32_t value)
  942 {
  943     data_t *data = get_new_data();
  944 
  945     if (!data) {
  946         return NULL;
  947     }
  948     data->len = gf_asprintf(&data->data, "%" PRIu32, value);
  949     if (-1 == data->len) {
  950         gf_msg_debug("dict", 0, "asprintf failed");
  951         data_destroy(data);
  952         return NULL;
  953     }
  954 
  955     data->len++; /* account for terminating NULL */
  956     data->data_type = GF_DATA_TYPE_UINT;
  957 
  958     return data;
  959 }
  960 
  961 data_t *
  962 data_from_uint16(uint16_t value)
  963 {
  964     data_t *data = get_new_data();
  965 
  966     if (!data) {
  967         return NULL;
  968     }
  969     data->len = gf_asprintf(&data->data, "%" PRIu16, value);
  970     if (-1 == data->len) {
  971         gf_msg_debug("dict", 0, "asprintf failed");
  972         data_destroy(data);
  973         return NULL;
  974     }
  975 
  976     data->len++; /* account for terminating NULL */
  977     data->data_type = GF_DATA_TYPE_UINT;
  978 
  979     return data;
  980 }
  981 
  982 static data_t *
  983 data_from_ptr_common(void *value, gf_boolean_t is_static)
  984 {
  985     /* it is valid to set 0/NULL as a value, no need to check *value */
  986 
  987     data_t *data = get_new_data();
  988     if (!data) {
  989         return NULL;
  990     }
  991 
  992     data->data = value;
  993     data->len = 0;
  994     data->is_static = is_static;
  995 
  996     data->data_type = GF_DATA_TYPE_PTR;
  997     return data;
  998 }
  999 
 1000 data_t *
 1001 str_to_data(char *value)
 1002 {
 1003     if (!value) {
 1004         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1005                          "value is NULL");
 1006         return NULL;
 1007     }
 1008 
 1009     return strn_to_data(value, strlen(value));
 1010 }
 1011 
 1012 data_t *
 1013 strn_to_data(char *value, const int vallen)
 1014 {
 1015     if (!value) {
 1016         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1017                          "value is NULL");
 1018         return NULL;
 1019     }
 1020     data_t *data = get_new_data();
 1021 
 1022     if (!data) {
 1023         return NULL;
 1024     }
 1025     data->len = vallen + 1;
 1026     data->data_type = GF_DATA_TYPE_STR;
 1027 
 1028     data->data = value;
 1029     data->is_static = _gf_true;
 1030 
 1031     return data;
 1032 }
 1033 
 1034 static data_t *
 1035 data_from_dynstr(char *value)
 1036 {
 1037     if (!value) {
 1038         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1039                          "value is NULL");
 1040         return NULL;
 1041     }
 1042 
 1043     data_t *data = get_new_data();
 1044 
 1045     if (!data)
 1046         return NULL;
 1047     data->len = strlen(value) + 1;
 1048     data->data = value;
 1049     data->data_type = GF_DATA_TYPE_STR;
 1050 
 1051     return data;
 1052 }
 1053 
 1054 data_t *
 1055 data_from_dynptr(void *value, int32_t len)
 1056 {
 1057     data_t *data = get_new_data();
 1058 
 1059     if (!data)
 1060         return NULL;
 1061 
 1062     data->len = len;
 1063     data->data = value;
 1064     data->data_type = GF_DATA_TYPE_PTR;
 1065 
 1066     return data;
 1067 }
 1068 
 1069 data_t *
 1070 bin_to_data(void *value, int32_t len)
 1071 {
 1072     if (!value) {
 1073         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1074                          "value is NULL");
 1075         return NULL;
 1076     }
 1077 
 1078     data_t *data = get_new_data();
 1079 
 1080     if (!data)
 1081         return NULL;
 1082 
 1083     data->is_static = _gf_true;
 1084     data->len = len;
 1085     data->data = value;
 1086 
 1087     return data;
 1088 }
 1089 
 1090 static char *data_type_name[GF_DATA_TYPE_MAX] = {
 1091     [GF_DATA_TYPE_UNKNOWN] = "unknown",
 1092     [GF_DATA_TYPE_STR_OLD] = "string-old-version",
 1093     [GF_DATA_TYPE_INT] = "integer",
 1094     [GF_DATA_TYPE_UINT] = "unsigned integer",
 1095     [GF_DATA_TYPE_DOUBLE] = "float",
 1096     [GF_DATA_TYPE_STR] = "string",
 1097     [GF_DATA_TYPE_PTR] = "pointer",
 1098     [GF_DATA_TYPE_GFUUID] = "gf-uuid",
 1099     [GF_DATA_TYPE_IATT] = "iatt",
 1100     [GF_DATA_TYPE_MDATA] = "mdata",
 1101 };
 1102 
 1103 int64_t
 1104 data_to_int64(data_t *data)
 1105 {
 1106     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1);
 1107 
 1108     return (int64_t)strtoull(data->data, NULL, 0);
 1109 }
 1110 
 1111 int32_t
 1112 data_to_int32(data_t *data)
 1113 {
 1114     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1);
 1115 
 1116     return strtoul(data->data, NULL, 0);
 1117 }
 1118 
 1119 int16_t
 1120 data_to_int16(data_t *data)
 1121 {
 1122     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1);
 1123 
 1124     int16_t value = 0;
 1125 
 1126     errno = 0;
 1127     value = strtol(data->data, NULL, 0);
 1128 
 1129     if ((value > SHRT_MAX) || (value < SHRT_MIN)) {
 1130         errno = ERANGE;
 1131         gf_msg_callingfn("dict", GF_LOG_WARNING, errno,
 1132                          LG_MSG_DATA_CONVERSION_ERROR,
 1133                          "Error in data"
 1134                          " conversion: detected overflow");
 1135         return -1;
 1136     }
 1137 
 1138     return (int16_t)value;
 1139 }
 1140 
 1141 int8_t
 1142 data_to_int8(data_t *data)
 1143 {
 1144     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, "null", -1);
 1145 
 1146     int8_t value = 0;
 1147 
 1148     errno = 0;
 1149     value = strtol(data->data, NULL, 0);
 1150 
 1151     if ((value > SCHAR_MAX) || (value < SCHAR_MIN)) {
 1152         errno = ERANGE;
 1153         gf_msg_callingfn("dict", GF_LOG_WARNING, errno,
 1154                          LG_MSG_DATA_CONVERSION_ERROR,
 1155                          "Error in data"
 1156                          " conversion: detected overflow");
 1157         return -1;
 1158     }
 1159 
 1160     return (int8_t)value;
 1161 }
 1162 
 1163 uint64_t
 1164 data_to_uint64(data_t *data)
 1165 {
 1166     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1);
 1167 
 1168     return strtoll(data->data, NULL, 0);
 1169 }
 1170 
 1171 uint32_t
 1172 data_to_uint32(data_t *data)
 1173 {
 1174     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1);
 1175 
 1176     return strtol(data->data, NULL, 0);
 1177 }
 1178 
 1179 uint16_t
 1180 data_to_uint16(data_t *data)
 1181 {
 1182     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1);
 1183 
 1184     uint16_t value = 0;
 1185 
 1186     errno = 0;
 1187     value = strtol(data->data, NULL, 0);
 1188 
 1189     if ((USHRT_MAX - value) < 0) {
 1190         errno = ERANGE;
 1191         gf_msg_callingfn("dict", GF_LOG_WARNING, errno,
 1192                          LG_MSG_DATA_CONVERSION_ERROR,
 1193                          "Error in data conversion: "
 1194                          "overflow detected");
 1195         return -1;
 1196     }
 1197 
 1198     return (uint16_t)value;
 1199 }
 1200 
 1201 uint8_t
 1202 data_to_uint8(data_t *data)
 1203 {
 1204     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, "null", -1);
 1205 
 1206     errno = 0;
 1207     uint32_t value = strtol(data->data, NULL, 0);
 1208 
 1209     if ((UCHAR_MAX - (uint8_t)value) < 0) {
 1210         errno = ERANGE;
 1211         gf_msg_callingfn("dict", GF_LOG_WARNING, errno,
 1212                          LG_MSG_DATA_CONVERSION_ERROR,
 1213                          "data "
 1214                          "conversion overflow detected");
 1215         return -1;
 1216     }
 1217 
 1218     return (uint8_t)value;
 1219 }
 1220 
 1221 char *
 1222 data_to_str(data_t *data)
 1223 {
 1224     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_STR, "null", NULL);
 1225     return data->data;
 1226 }
 1227 
 1228 void *
 1229 data_to_ptr(data_t *data)
 1230 {
 1231     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, "null", NULL);
 1232     return data->data;
 1233 }
 1234 
 1235 void *
 1236 data_to_bin(data_t *data)
 1237 {
 1238     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, "null", NULL);
 1239     return data->data;
 1240 }
 1241 
 1242 struct iatt *
 1243 data_to_iatt(data_t *data, char *key)
 1244 {
 1245     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_IATT, key, NULL);
 1246 
 1247     /* We only check for smaller size. If it's bigger we simply ignore
 1248      * the extra data. This way it's easy to do changes in the future that
 1249      * pass more data but are backward compatible (if the initial contents
 1250      * of the struct are maintained, of course). */
 1251     if (data->len < sizeof(struct iatt)) {
 1252         gf_smsg("glusterfs", GF_LOG_ERROR, ENOBUFS, LG_MSG_UNDERSIZED_BUF,
 1253                 "key=%s", key, NULL);
 1254         return NULL;
 1255     }
 1256 
 1257     return (struct iatt *)data->data;
 1258 }
 1259 
 1260 int
 1261 dict_null_foreach_fn(dict_t *d, char *k, data_t *v, void *tmp)
 1262 {
 1263     return 0;
 1264 }
 1265 
 1266 int
 1267 dict_remove_foreach_fn(dict_t *d, char *k, data_t *v, void *_tmp)
 1268 {
 1269     if (!d || !k) {
 1270         gf_smsg("glusterfs", GF_LOG_WARNING, EINVAL, LG_MSG_KEY_OR_VALUE_NULL,
 1271                 "d=%s", d ? "key" : "dictionary", NULL);
 1272         return -1;
 1273     }
 1274 
 1275     dict_del(d, k);
 1276     return 0;
 1277 }
 1278 
 1279 gf_boolean_t
 1280 dict_match_everything(dict_t *d, char *k, data_t *v, void *data)
 1281 {
 1282     return _gf_true;
 1283 }
 1284 
 1285 int
 1286 dict_foreach(dict_t *dict,
 1287              int (*fn)(dict_t *this, char *key, data_t *value, void *data),
 1288              void *data)
 1289 {
 1290     int ret = dict_foreach_match(dict, dict_match_everything, NULL, fn, data);
 1291 
 1292     if (ret > 0)
 1293         ret = 0;
 1294 
 1295     return ret;
 1296 }
 1297 
 1298 /* return values:
 1299    -1 = failure,
 1300     0 = no matches found,
 1301    +n = n number of matches
 1302 */
 1303 int
 1304 dict_foreach_match(dict_t *dict,
 1305                    gf_boolean_t (*match)(dict_t *this, char *key, data_t *value,
 1306                                          void *mdata),
 1307                    void *match_data,
 1308                    int (*action)(dict_t *this, char *key, data_t *value,
 1309                                  void *adata),
 1310                    void *action_data)
 1311 {
 1312     if (!dict || !match || !action) {
 1313         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1314                          "dict|match|action is "
 1315                          "NULL");
 1316         return -1;
 1317     }
 1318 
 1319     int ret = -1;
 1320     int count = 0;
 1321     data_pair_t *pairs = dict->members_list;
 1322     data_pair_t *next = NULL;
 1323 
 1324     while (pairs) {
 1325         next = pairs->next;
 1326         if (match(dict, pairs->key, pairs->value, match_data)) {
 1327             ret = action(dict, pairs->key, pairs->value, action_data);
 1328             if (ret < 0)
 1329                 return ret;
 1330             count++;
 1331         }
 1332         pairs = next;
 1333     }
 1334 
 1335     return count;
 1336 }
 1337 
 1338 static gf_boolean_t
 1339 dict_fnmatch(dict_t *d, char *k, data_t *val, void *match_data)
 1340 {
 1341     return (fnmatch(match_data, k, 0) == 0);
 1342 }
 1343 /* return values:
 1344    -1 = failure,
 1345     0 = no matches found,
 1346    +n = n number of matches
 1347 */
 1348 int
 1349 dict_foreach_fnmatch(dict_t *dict, char *pattern,
 1350                      int (*fn)(dict_t *this, char *key, data_t *value,
 1351                                void *data),
 1352                      void *data)
 1353 {
 1354     return dict_foreach_match(dict, dict_fnmatch, pattern, fn, data);
 1355 }
 1356 
 1357 /**
 1358  * dict_keys_join - pack the keys of the dictionary in a buffer.
 1359  *
 1360  * @value     : buffer in which the keys will be packed (can be NULL)
 1361  * @size      : size of the buffer which is sent (can be 0, in which case buffer
 1362  *              is not packed but only length is returned)
 1363  * @dict      : dictionary of which all the keys will be packed
 1364  * @filter_fn : keys matched in filter_fn() is counted.
 1365  *
 1366  * @return : @length of string after joining keys.
 1367  *
 1368  */
 1369 
 1370 int
 1371 dict_keys_join(void *value, int size, dict_t *dict, int (*filter_fn)(char *k))
 1372 {
 1373     int len = 0;
 1374     data_pair_t *pairs = dict->members_list;
 1375     data_pair_t *next = NULL;
 1376 
 1377     while (pairs) {
 1378         next = pairs->next;
 1379 
 1380         if (filter_fn && filter_fn(pairs->key)) {
 1381             pairs = next;
 1382             continue;
 1383         }
 1384 
 1385         if (value && (size > len))
 1386             strncpy(value + len, pairs->key, size - len);
 1387 
 1388         len += (strlen(pairs->key) + 1);
 1389 
 1390         pairs = next;
 1391     }
 1392 
 1393     return len;
 1394 }
 1395 
 1396 static int
 1397 dict_copy_one(dict_t *unused, char *key, data_t *value, void *newdict)
 1398 {
 1399     return dict_set((dict_t *)newdict, key, (value));
 1400 }
 1401 
 1402 dict_t *
 1403 dict_copy(dict_t *dict, dict_t *new)
 1404 {
 1405     if (!dict) {
 1406         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1407                          "dict is NULL");
 1408         return NULL;
 1409     }
 1410 
 1411     if (!new)
 1412         new = get_new_dict_full(dict->hash_size);
 1413 
 1414     dict_foreach(dict, dict_copy_one, new);
 1415 
 1416     return new;
 1417 }
 1418 
 1419 int
 1420 dict_reset(dict_t *dict)
 1421 {
 1422     int32_t ret = -1;
 1423     if (!dict) {
 1424         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1425                          "dict is NULL");
 1426         goto out;
 1427     }
 1428     dict_foreach(dict, dict_remove_foreach_fn, NULL);
 1429     ret = 0;
 1430 out:
 1431     return ret;
 1432 }
 1433 
 1434 dict_t *
 1435 dict_copy_with_ref(dict_t *dict, dict_t *new)
 1436 {
 1437     dict_t *local_new = NULL;
 1438 
 1439     GF_VALIDATE_OR_GOTO("dict", dict, fail);
 1440 
 1441     if (new == NULL) {
 1442         local_new = dict_new();
 1443         GF_VALIDATE_OR_GOTO("dict", local_new, fail);
 1444         new = local_new;
 1445     }
 1446 
 1447     dict_foreach(dict, dict_copy_one, new);
 1448 fail:
 1449     return new;
 1450 }
 1451 
 1452 /*
 1453  * !!!!!!! CLEANED UP CODE !!!!!!!
 1454  */
 1455 
 1456 /**
 1457  * Common cleaned up interface:
 1458  *
 1459  * Return value:  0   success
 1460  *               -val error, val = errno
 1461  */
 1462 
 1463 int
 1464 dict_get_with_ref(dict_t *this, char *key, data_t **data)
 1465 {
 1466     if (!this || !key || !data) {
 1467         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1468                          "dict OR key (%s) is NULL", key);
 1469         return -EINVAL;
 1470     }
 1471 
 1472     return dict_get_with_refn(this, key, strlen(key), data);
 1473 }
 1474 
 1475 int
 1476 dict_get_with_refn(dict_t *this, char *key, const int keylen, data_t **data)
 1477 {
 1478     data_pair_t *pair = NULL;
 1479     int ret = -ENOENT;
 1480     uint32_t hash;
 1481 
 1482     if (!this || !key || !data) {
 1483         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1484                          "dict OR key (%s) is NULL", key);
 1485         ret = -EINVAL;
 1486         goto err;
 1487     }
 1488 
 1489     hash = (uint32_t)XXH64(key, keylen, 0);
 1490 
 1491     LOCK(&this->lock);
 1492     {
 1493         pair = dict_lookup_common(this, key, hash);
 1494 
 1495         if (pair) {
 1496             ret = 0;
 1497             *data = data_ref(pair->value);
 1498         }
 1499     }
 1500     UNLOCK(&this->lock);
 1501 err:
 1502     return ret;
 1503 }
 1504 
 1505 static int
 1506 data_to_ptr_common(data_t *data, void **val)
 1507 {
 1508     int ret = 0;
 1509 
 1510     if (!data) {
 1511         ret = -EINVAL;
 1512         goto err;
 1513     }
 1514 
 1515     *val = data->data;
 1516 err:
 1517     return ret;
 1518 }
 1519 
 1520 static int
 1521 data_to_int8_ptr(data_t *data, int8_t *val)
 1522 {
 1523     int ret = 0;
 1524 
 1525     if (!data || !val) {
 1526         ret = -EINVAL;
 1527         goto err;
 1528     }
 1529 
 1530     errno = 0;
 1531     *val = strtol(data->data, NULL, 0);
 1532     if (errno != 0)
 1533         ret = -errno;
 1534 
 1535 err:
 1536     return ret;
 1537 }
 1538 
 1539 static int
 1540 data_to_int16_ptr(data_t *data, int16_t *val)
 1541 {
 1542     int ret = 0;
 1543 
 1544     if (!data || !val) {
 1545         ret = -EINVAL;
 1546         goto err;
 1547     }
 1548 
 1549     errno = 0;
 1550     *val = strtol(data->data, NULL, 0);
 1551     if (errno != 0)
 1552         ret = -errno;
 1553 
 1554 err:
 1555     return ret;
 1556 }
 1557 
 1558 static int
 1559 data_to_int32_ptr(data_t *data, int32_t *val)
 1560 {
 1561     int ret = 0;
 1562 
 1563     if (!data || !val) {
 1564         ret = -EINVAL;
 1565         goto err;
 1566     }
 1567 
 1568     errno = 0;
 1569     *val = strtol(data->data, NULL, 0);
 1570     if (errno != 0)
 1571         ret = -errno;
 1572 
 1573 err:
 1574     return ret;
 1575 }
 1576 
 1577 static int
 1578 data_to_int64_ptr(data_t *data, int64_t *val)
 1579 {
 1580     int ret = 0;
 1581 
 1582     if (!data || !val) {
 1583         ret = -EINVAL;
 1584         goto err;
 1585     }
 1586 
 1587     errno = 0;
 1588     *val = strtoll(data->data, NULL, 0);
 1589     if (errno != 0)
 1590         ret = -errno;
 1591 
 1592 err:
 1593     return ret;
 1594 }
 1595 
 1596 static int
 1597 data_to_uint16_ptr(data_t *data, uint16_t *val)
 1598 {
 1599     int ret = 0;
 1600 
 1601     if (!data || !val) {
 1602         ret = -EINVAL;
 1603         goto err;
 1604     }
 1605 
 1606     errno = 0;
 1607     *val = strtoul(data->data, NULL, 0);
 1608     if (errno != 0)
 1609         ret = -errno;
 1610 
 1611 err:
 1612     return ret;
 1613 }
 1614 
 1615 static int
 1616 data_to_uint32_ptr(data_t *data, uint32_t *val)
 1617 {
 1618     int ret = 0;
 1619 
 1620     if (!data || !val) {
 1621         ret = -EINVAL;
 1622         goto err;
 1623     }
 1624 
 1625     errno = 0;
 1626     *val = strtoul(data->data, NULL, 0);
 1627     if (errno != 0)
 1628         ret = -errno;
 1629 
 1630 err:
 1631     return ret;
 1632 }
 1633 
 1634 static int
 1635 data_to_uint64_ptr(data_t *data, uint64_t *val)
 1636 {
 1637     int ret = 0;
 1638 
 1639     if (!data || !val) {
 1640         ret = -EINVAL;
 1641         goto err;
 1642     }
 1643 
 1644     errno = 0;
 1645     *val = strtoull(data->data, NULL, 0);
 1646     if (errno != 0)
 1647         ret = -errno;
 1648 
 1649 err:
 1650     return ret;
 1651 }
 1652 
 1653 static int
 1654 data_to_double_ptr(data_t *data, double *val)
 1655 {
 1656     int ret = 0;
 1657 
 1658     if (!data || !val) {
 1659         ret = -EINVAL;
 1660         goto err;
 1661     }
 1662 
 1663     errno = 0;
 1664     *val = strtod(data->data, NULL);
 1665     if (errno != 0)
 1666         ret = -errno;
 1667 
 1668 err:
 1669     return ret;
 1670 }
 1671 
 1672 int
 1673 dict_get_int8(dict_t *this, char *key, int8_t *val)
 1674 {
 1675     data_t *data = NULL;
 1676     int ret = 0;
 1677 
 1678     if (!this || !key || !val) {
 1679         ret = -EINVAL;
 1680         goto err;
 1681     }
 1682 
 1683     ret = dict_get_with_ref(this, key, &data);
 1684     if (ret != 0) {
 1685         goto err;
 1686     }
 1687 
 1688     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, key, -EINVAL);
 1689 
 1690     ret = data_to_int8_ptr(data, val);
 1691 
 1692 err:
 1693     if (data)
 1694         data_unref(data);
 1695     return ret;
 1696 }
 1697 
 1698 int
 1699 dict_set_int8(dict_t *this, char *key, int8_t val)
 1700 {
 1701     data_t *data = NULL;
 1702     int ret = 0;
 1703 
 1704     data = data_from_int8(val);
 1705     if (!data) {
 1706         ret = -EINVAL;
 1707         goto err;
 1708     }
 1709 
 1710     ret = dict_set(this, key, data);
 1711     if (ret < 0)
 1712         data_destroy(data);
 1713 
 1714 err:
 1715     return ret;
 1716 }
 1717 
 1718 int
 1719 dict_get_int16(dict_t *this, char *key, int16_t *val)
 1720 {
 1721     data_t *data = NULL;
 1722     int ret = 0;
 1723 
 1724     if (!this || !key || !val) {
 1725         ret = -EINVAL;
 1726         goto err;
 1727     }
 1728 
 1729     ret = dict_get_with_ref(this, key, &data);
 1730     if (ret != 0) {
 1731         goto err;
 1732     }
 1733 
 1734     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, key, -EINVAL);
 1735 
 1736     ret = data_to_int16_ptr(data, val);
 1737 
 1738 err:
 1739     if (data)
 1740         data_unref(data);
 1741     return ret;
 1742 }
 1743 
 1744 int
 1745 dict_set_int16(dict_t *this, char *key, int16_t val)
 1746 {
 1747     data_t *data = NULL;
 1748     int ret = 0;
 1749 
 1750     data = data_from_int16(val);
 1751     if (!data) {
 1752         ret = -EINVAL;
 1753         goto err;
 1754     }
 1755 
 1756     ret = dict_set(this, key, data);
 1757     if (ret < 0)
 1758         data_destroy(data);
 1759 
 1760 err:
 1761     return ret;
 1762 }
 1763 
 1764 int
 1765 dict_get_int32n(dict_t *this, char *key, const int keylen, int32_t *val)
 1766 {
 1767     data_t *data = NULL;
 1768     int ret = 0;
 1769 
 1770     if (!this || !key || !val) {
 1771         ret = -EINVAL;
 1772         goto err;
 1773     }
 1774 
 1775     ret = dict_get_with_refn(this, key, keylen, &data);
 1776     if (ret != 0) {
 1777         goto err;
 1778     }
 1779 
 1780     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, key, -EINVAL);
 1781 
 1782     ret = data_to_int32_ptr(data, val);
 1783 
 1784 err:
 1785     if (data)
 1786         data_unref(data);
 1787     return ret;
 1788 }
 1789 
 1790 int
 1791 dict_get_int32(dict_t *this, char *key, int32_t *val)
 1792 {
 1793     data_t *data = NULL;
 1794     int ret = 0;
 1795 
 1796     if (!this || !key || !val) {
 1797         ret = -EINVAL;
 1798         goto err;
 1799     }
 1800 
 1801     ret = dict_get_with_ref(this, key, &data);
 1802     if (ret != 0) {
 1803         goto err;
 1804     }
 1805 
 1806     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, key, -EINVAL);
 1807 
 1808     ret = data_to_int32_ptr(data, val);
 1809 
 1810 err:
 1811     if (data)
 1812         data_unref(data);
 1813     return ret;
 1814 }
 1815 
 1816 int
 1817 dict_set_int32n(dict_t *this, char *key, const int keylen, int32_t val)
 1818 {
 1819     data_t *data = NULL;
 1820     int ret = 0;
 1821 
 1822     data = data_from_int32(val);
 1823     if (!data) {
 1824         ret = -EINVAL;
 1825         goto err;
 1826     }
 1827 
 1828     ret = dict_setn(this, key, keylen, data);
 1829     if (ret < 0)
 1830         data_destroy(data);
 1831 
 1832 err:
 1833     return ret;
 1834 }
 1835 
 1836 int
 1837 dict_set_int32(dict_t *this, char *key, int32_t val)
 1838 {
 1839     data_t *data = data_from_int32(val);
 1840     int ret = 0;
 1841 
 1842     if (!data) {
 1843         ret = -EINVAL;
 1844         goto err;
 1845     }
 1846 
 1847     ret = dict_set(this, key, data);
 1848     if (ret < 0)
 1849         data_destroy(data);
 1850 
 1851 err:
 1852     return ret;
 1853 }
 1854 
 1855 int
 1856 dict_get_int64(dict_t *this, char *key, int64_t *val)
 1857 {
 1858     data_t *data = NULL;
 1859     int ret = 0;
 1860 
 1861     if (!this || !key || !val) {
 1862         ret = -EINVAL;
 1863         goto err;
 1864     }
 1865 
 1866     ret = dict_get_with_ref(this, key, &data);
 1867     if (ret != 0) {
 1868         goto err;
 1869     }
 1870 
 1871     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, key, -EINVAL);
 1872 
 1873     ret = data_to_int64_ptr(data, val);
 1874 
 1875 err:
 1876     if (data)
 1877         data_unref(data);
 1878     return ret;
 1879 }
 1880 
 1881 int
 1882 dict_set_int64(dict_t *this, char *key, int64_t val)
 1883 {
 1884     data_t *data = data_from_int64(val);
 1885     int ret = 0;
 1886 
 1887     if (!data) {
 1888         ret = -EINVAL;
 1889         goto err;
 1890     }
 1891 
 1892     ret = dict_set(this, key, data);
 1893     if (ret < 0)
 1894         data_destroy(data);
 1895 
 1896 err:
 1897     return ret;
 1898 }
 1899 
 1900 int
 1901 dict_get_uint16(dict_t *this, char *key, uint16_t *val)
 1902 {
 1903     data_t *data = NULL;
 1904     int ret = 0;
 1905 
 1906     if (!this || !key || !val) {
 1907         ret = -EINVAL;
 1908         goto err;
 1909     }
 1910 
 1911     ret = dict_get_with_ref(this, key, &data);
 1912     if (ret != 0) {
 1913         goto err;
 1914     }
 1915 
 1916     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, key, -EINVAL);
 1917 
 1918     ret = data_to_uint16_ptr(data, val);
 1919 
 1920 err:
 1921     if (data)
 1922         data_unref(data);
 1923     return ret;
 1924 }
 1925 
 1926 int
 1927 dict_set_uint16(dict_t *this, char *key, uint16_t val)
 1928 {
 1929     data_t *data = data_from_uint16(val);
 1930     int ret = 0;
 1931 
 1932     if (!data) {
 1933         ret = -EINVAL;
 1934         goto err;
 1935     }
 1936 
 1937     ret = dict_set(this, key, data);
 1938     if (ret < 0)
 1939         data_destroy(data);
 1940 
 1941 err:
 1942     return ret;
 1943 }
 1944 
 1945 int
 1946 dict_get_uint32(dict_t *this, char *key, uint32_t *val)
 1947 {
 1948     data_t *data = NULL;
 1949     int ret = 0;
 1950 
 1951     if (!this || !key || !val) {
 1952         ret = -EINVAL;
 1953         goto err;
 1954     }
 1955 
 1956     ret = dict_get_with_ref(this, key, &data);
 1957     if (ret != 0) {
 1958         goto err;
 1959     }
 1960 
 1961     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, key, -EINVAL);
 1962 
 1963     ret = data_to_uint32_ptr(data, val);
 1964 
 1965 err:
 1966     if (data)
 1967         data_unref(data);
 1968     return ret;
 1969 }
 1970 
 1971 int
 1972 dict_set_uint32(dict_t *this, char *key, uint32_t val)
 1973 {
 1974     data_t *data = data_from_uint32(val);
 1975     int ret = 0;
 1976 
 1977     if (!data) {
 1978         ret = -EINVAL;
 1979         goto err;
 1980     }
 1981 
 1982     ret = dict_set(this, key, data);
 1983     if (ret < 0)
 1984         data_destroy(data);
 1985 
 1986 err:
 1987     return ret;
 1988 }
 1989 
 1990 int
 1991 dict_get_uint64(dict_t *this, char *key, uint64_t *val)
 1992 {
 1993     data_t *data = NULL;
 1994     int ret = 0;
 1995 
 1996     if (!this || !key || !val) {
 1997         ret = -EINVAL;
 1998         goto err;
 1999     }
 2000 
 2001     ret = dict_get_with_ref(this, key, &data);
 2002     if (ret != 0) {
 2003         goto err;
 2004     }
 2005 
 2006     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_UINT, key, -EINVAL);
 2007 
 2008     ret = data_to_uint64_ptr(data, val);
 2009 
 2010 err:
 2011     if (data)
 2012         data_unref(data);
 2013     return ret;
 2014 }
 2015 
 2016 int
 2017 dict_set_uint64(dict_t *this, char *key, uint64_t val)
 2018 {
 2019     data_t *data = data_from_uint64(val);
 2020     int ret = 0;
 2021 
 2022     if (!data) {
 2023         ret = -EINVAL;
 2024         goto err;
 2025     }
 2026 
 2027     ret = dict_set(this, key, data);
 2028     if (ret < 0)
 2029         data_destroy(data);
 2030 
 2031 err:
 2032     return ret;
 2033 }
 2034 
 2035 /*
 2036  * dict_check_flag can be used to check a one bit flag in an array of flags
 2037  * The flag argument indicates the bit position (within the array of bits).
 2038  * Currently limited to max of 256 flags for a key.
 2039  * return value,
 2040  * 1 : flag is set
 2041  * 0 : flag is not set
 2042  * <0: Error
 2043  */
 2044 int
 2045 dict_check_flag(dict_t *this, char *key, int flag)
 2046 {
 2047     data_t *data = NULL;
 2048     int ret = -ENOENT;
 2049 
 2050     ret = dict_get_with_ref(this, key, &data);
 2051     if (ret < 0) {
 2052         return ret;
 2053     }
 2054 
 2055     if (BIT_VALUE((unsigned char *)(data->data), flag))
 2056         ret = 1;
 2057     else
 2058         ret = 0;
 2059 
 2060     data_unref(data);
 2061     return ret;
 2062 }
 2063 
 2064 /*
 2065  * _dict_modify_flag can be used to set/clear a bit flag in an array of flags
 2066  * flag: indicates the bit position. limited to max of DICT_MAX_FLAGS.
 2067  * op: Indicates operation DICT_FLAG_SET / DICT_FLAG_CLEAR
 2068  */
 2069 static int
 2070 _dict_modify_flag(dict_t *this, char *key, int flag, int op)
 2071 {
 2072     data_t *data = NULL;
 2073     int ret = 0;
 2074     data_pair_t *pair = NULL;
 2075     char *ptr = NULL;
 2076     int hashval = 0;
 2077     uint32_t hash;
 2078 
 2079     if (!this || !key) {
 2080         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 2081                          "dict OR key (%s) is NULL", key);
 2082         ret = -EINVAL;
 2083         goto err;
 2084     }
 2085 
 2086     /*
 2087      * Using a size of 32 bytes to support max of 256
 2088      * flags in a single key. This should be suffcient.
 2089      */
 2090     GF_ASSERT(flag >= 0 && flag < DICT_MAX_FLAGS);
 2091 
 2092     hash = (uint32_t)XXH64(key, strlen(key), 0);
 2093     LOCK(&this->lock);
 2094     {
 2095         pair = dict_lookup_common(this, key, hash);
 2096 
 2097         if (pair) {
 2098             data = pair->value;
 2099             if (op == DICT_FLAG_SET)
 2100                 BIT_SET((unsigned char *)(data->data), flag);
 2101             else
 2102                 BIT_CLEAR((unsigned char *)(data->data), flag);
 2103         } else {
 2104             ptr = GF_CALLOC(1, DICT_MAX_FLAGS / 8, gf_common_mt_char);
 2105             if (!ptr) {
 2106                 gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY,
 2107                         "flag bit array", NULL);
 2108                 ret = -ENOMEM;
 2109                 goto err;
 2110             }
 2111 
 2112             data = data_from_dynptr(ptr, DICT_MAX_FLAGS / 8);
 2113 
 2114             if (!data) {
 2115                 gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, "data",
 2116                         NULL);
 2117                 GF_FREE(ptr);
 2118                 ret = -ENOMEM;
 2119                 goto err;
 2120             }
 2121 
 2122             if (op == DICT_FLAG_SET)
 2123                 BIT_SET((unsigned char *)(data->data), flag);
 2124             else
 2125                 BIT_CLEAR((unsigned char *)(data->data), flag);
 2126 
 2127             if (this->free_pair.key) { /* the free pair is in use */
 2128                 pair = mem_get0(THIS->ctx->dict_pair_pool);
 2129                 if (!pair) {
 2130                     gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY,
 2131                             "dict pair", NULL);
 2132                     ret = -ENOMEM;
 2133                     goto err;
 2134                 }
 2135             } else { /* use the free pair */
 2136                 pair = &this->free_pair;
 2137             }
 2138 
 2139             pair->key = (char *)GF_MALLOC(strlen(key) + 1, gf_common_mt_char);
 2140             if (!pair->key) {
 2141                 gf_smsg("dict", GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY,
 2142                         "dict pair", NULL);
 2143                 ret = -ENOMEM;
 2144                 goto err;
 2145             }
 2146             strcpy(pair->key, key);
 2147             pair->key_hash = hash;
 2148             pair->value = data_ref(data);
 2149 
 2150             hashval = hash % this->hash_size;
 2151             pair->hash_next = this->members[hashval];
 2152             this->members[hashval] = pair;
 2153 
 2154             pair->next = this->members_list;
 2155             pair->prev = NULL;
 2156             if (this->members_list)
 2157                 this->members_list->prev = pair;
 2158             this->members_list = pair;
 2159             this->count++;
 2160 
 2161             if (this->max_count < this->count)
 2162                 this->max_count = this->count;
 2163         }
 2164     }
 2165 
 2166     UNLOCK(&this->lock);
 2167     return 0;
 2168 
 2169 err:
 2170     if (key && this)
 2171         UNLOCK(&this->lock);
 2172 
 2173     if (pair) {
 2174         if (pair->key) {
 2175             GF_FREE(pair->key);
 2176             pair->key = NULL;
 2177         }
 2178         if (pair != &this->free_pair) {
 2179             mem_put(pair);
 2180         }
 2181     }
 2182 
 2183     if (data)
 2184         data_destroy(data);
 2185 
 2186     gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_DICT_SET_FAILED, "key=%s", key,
 2187             NULL);
 2188 
 2189     return ret;
 2190 }
 2191 
 2192 /*
 2193  * Todo:
 2194  * Add below primitives as needed:
 2195  * dict_check_flags(this, key, flag...): variadic function to check
 2196  *                                       multiple flags at a time.
 2197  * dict_set_flags(this, key, flag...): set multiple flags
 2198  * dict_clear_flags(this, key, flag...): reset multiple flags
 2199  */
 2200 
 2201 int
 2202 dict_set_flag(dict_t *this, char *key, int flag)
 2203 {
 2204     return _dict_modify_flag(this, key, flag, DICT_FLAG_SET);
 2205 }
 2206 
 2207 int
 2208 dict_clear_flag(dict_t *this, char *key, int flag)
 2209 {
 2210     return _dict_modify_flag(this, key, flag, DICT_FLAG_CLEAR);
 2211 }
 2212 
 2213 int
 2214 dict_get_double(dict_t *this, char *key, double *val)
 2215 {
 2216     data_t *data = NULL;
 2217     int ret = 0;
 2218 
 2219     if (!this || !key || !val) {
 2220         ret = -EINVAL;
 2221         goto err;
 2222     }
 2223 
 2224     ret = dict_get_with_ref(this, key, &data);
 2225     if (ret != 0) {
 2226         goto err;
 2227     }
 2228 
 2229     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_DOUBLE, key, -EINVAL);
 2230 
 2231     ret = data_to_double_ptr(data, val);
 2232 
 2233 err:
 2234     if (data)
 2235         data_unref(data);
 2236     return ret;
 2237 }
 2238 
 2239 int
 2240 dict_set_double(dict_t *this, char *key, double val)
 2241 {
 2242     data_t *data = data_from_double(val);
 2243     int ret = 0;
 2244 
 2245     if (!data) {
 2246         ret = -EINVAL;
 2247         goto err;
 2248     }
 2249 
 2250     ret = dict_set(this, key, data);
 2251     if (ret < 0)
 2252         data_destroy(data);
 2253 
 2254 err:
 2255     return ret;
 2256 }
 2257 
 2258 int
 2259 dict_set_static_ptr(dict_t *this, char *key, void *ptr)
 2260 {
 2261     data_t *data = data_from_ptr_common(ptr, _gf_true);
 2262     int ret = 0;
 2263 
 2264     if (!data) {
 2265         ret = -EINVAL;
 2266         goto err;
 2267     }
 2268 
 2269     ret = dict_set(this, key, data);
 2270     if (ret < 0)
 2271         data_destroy(data);
 2272 
 2273 err:
 2274     return ret;
 2275 }
 2276 
 2277 int
 2278 dict_set_dynptr(dict_t *this, char *key, void *ptr, size_t len)
 2279 {
 2280     data_t *data = data_from_dynptr(ptr, len);
 2281     int ret = 0;
 2282 
 2283     if (!data) {
 2284         ret = -EINVAL;
 2285         goto err;
 2286     }
 2287 
 2288     ret = dict_set(this, key, data);
 2289     if (ret < 0)
 2290         data_destroy(data);
 2291 
 2292 err:
 2293     return ret;
 2294 }
 2295 
 2296 int
 2297 dict_get_ptr(dict_t *this, char *key, void **ptr)
 2298 {
 2299     data_t *data = NULL;
 2300     int ret = 0;
 2301 
 2302     if (!this || !key || !ptr) {
 2303         ret = -EINVAL;
 2304         goto err;
 2305     }
 2306 
 2307     ret = dict_get_with_ref(this, key, &data);
 2308     if (ret != 0) {
 2309         goto err;
 2310     }
 2311 
 2312     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, key, -EINVAL);
 2313 
 2314     ret = data_to_ptr_common(data, ptr);
 2315     if (ret != 0) {
 2316         goto err;
 2317     }
 2318 
 2319 err:
 2320     if (data)
 2321         data_unref(data);
 2322 
 2323     return ret;
 2324 }
 2325 
 2326 int
 2327 dict_get_ptr_and_len(dict_t *this, char *key, void **ptr, int *len)
 2328 {
 2329     data_t *data = NULL;
 2330     int ret = 0;
 2331 
 2332     if (!this || !key || !ptr) {
 2333         ret = -EINVAL;
 2334         goto err;
 2335     }
 2336 
 2337     ret = dict_get_with_ref(this, key, &data);
 2338     if (ret != 0) {
 2339         goto err;
 2340     }
 2341 
 2342     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, key, -EINVAL);
 2343 
 2344     *len = data->len;
 2345 
 2346     ret = data_to_ptr_common(data, ptr);
 2347     if (ret != 0) {
 2348         goto err;
 2349     }
 2350 
 2351 err:
 2352     if (data)
 2353         data_unref(data);
 2354 
 2355     return ret;
 2356 }
 2357 
 2358 /* Get string - with known key length */
 2359 int
 2360 dict_get_strn(dict_t *this, char *key, const int keylen, char **str)
 2361 {
 2362     data_t *data = NULL;
 2363     int ret = -EINVAL;
 2364 
 2365     if (!this || !key || !str) {
 2366         goto err;
 2367     }
 2368     ret = dict_get_with_refn(this, key, keylen, &data);
 2369     if (ret < 0) {
 2370         goto err;
 2371     }
 2372 
 2373     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_STR, key, -EINVAL);
 2374 
 2375     *str = data->data;
 2376 
 2377 err:
 2378     if (data)
 2379         data_unref(data);
 2380 
 2381     return ret;
 2382 }
 2383 
 2384 int
 2385 dict_get_str(dict_t *this, char *key, char **str)
 2386 {
 2387     data_t *data = NULL;
 2388     int ret = -EINVAL;
 2389 
 2390     if (!this || !key || !str) {
 2391         goto err;
 2392     }
 2393     ret = dict_get_with_ref(this, key, &data);
 2394     if (ret < 0) {
 2395         goto err;
 2396     }
 2397 
 2398     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_STR, key, -EINVAL);
 2399 
 2400     *str = data->data;
 2401 
 2402 err:
 2403     if (data)
 2404         data_unref(data);
 2405 
 2406     return ret;
 2407 }
 2408 
 2409 int
 2410 dict_set_str(dict_t *this, char *key, char *str)
 2411 {
 2412     data_t *data = str_to_data(str);
 2413     int ret = 0;
 2414 
 2415     if (!data) {
 2416         ret = -EINVAL;
 2417         goto err;
 2418     }
 2419 
 2420     ret = dict_set(this, key, data);
 2421     if (ret < 0)
 2422         data_destroy(data);
 2423 
 2424 err:
 2425     return ret;
 2426 }
 2427 
 2428 /* Set string - with known key length */
 2429 int
 2430 dict_set_strn(dict_t *this, char *key, const int keylen, char *str)
 2431 {
 2432     data_t *data = NULL;
 2433     int ret = 0;
 2434 
 2435     data = str_to_data(str);
 2436     if (!data) {
 2437         ret = -EINVAL;
 2438         goto err;
 2439     }
 2440 
 2441     ret = dict_setn(this, key, keylen, data);
 2442     if (ret < 0)
 2443         data_destroy(data);
 2444 
 2445 err:
 2446     return ret;
 2447 }
 2448 
 2449 /* Set string - with known key length and known value length */
 2450 int
 2451 dict_set_nstrn(dict_t *this, char *key, const int keylen, char *str,
 2452                const int vallen)
 2453 {
 2454     data_t *data = strn_to_data(str, vallen);
 2455     int ret = 0;
 2456 
 2457     if (!data) {
 2458         ret = -EINVAL;
 2459         goto err;
 2460     }
 2461 
 2462     ret = dict_setn(this, key, keylen, data);
 2463     if (ret < 0)
 2464         data_destroy(data);
 2465 
 2466 err:
 2467     return ret;
 2468 }
 2469 
 2470 int
 2471 dict_set_dynstr_with_alloc(dict_t *this, char *key, const char *str)
 2472 {
 2473     char *alloc_str = gf_strdup(str);
 2474     int ret = -1;
 2475 
 2476     if (!alloc_str)
 2477         return ret;
 2478 
 2479     ret = dict_set_dynstr(this, key, alloc_str);
 2480     if (ret == -EINVAL)
 2481         GF_FREE(alloc_str);
 2482 
 2483     return ret;
 2484 }
 2485 
 2486 int
 2487 dict_set_dynstr(dict_t *this, char *key, char *str)
 2488 {
 2489     const int keylen = strlen(key);
 2490     return dict_set_dynstrn(this, key, keylen, str);
 2491 }
 2492 
 2493 int
 2494 dict_set_dynstrn(dict_t *this, char *key, const int keylen, char *str)
 2495 {
 2496     data_t *data = data_from_dynstr(str);
 2497     int ret = 0;
 2498 
 2499     if (!data) {
 2500         ret = -EINVAL;
 2501         goto err;
 2502     }
 2503 
 2504     ret = dict_setn(this, key, keylen, data);
 2505     if (ret < 0)
 2506         data_destroy(data);
 2507 
 2508 err:
 2509     return ret;
 2510 }
 2511 
 2512 /* This function is called only by the volgen for now.
 2513    Check how else you can handle it */
 2514 int
 2515 dict_set_option(dict_t *this, char *key, char *str)
 2516 {
 2517     data_t *data = data_from_dynstr(str);
 2518     int ret = 0;
 2519 
 2520     if (!data) {
 2521         ret = -EINVAL;
 2522         goto err;
 2523     }
 2524 
 2525     data->data_type = GF_DATA_TYPE_STR_OLD;
 2526     ret = dict_set(this, key, data);
 2527     if (ret < 0)
 2528         data_destroy(data);
 2529 err:
 2530     return ret;
 2531 }
 2532 
 2533 int
 2534 dict_add_dynstr_with_alloc(dict_t *this, char *key, char *str)
 2535 {
 2536     data_t *data = NULL;
 2537     int ret = 0;
 2538     char *alloc_str = gf_strdup(str);
 2539 
 2540     if (!alloc_str)
 2541         goto out;
 2542 
 2543     data = data_from_dynstr(alloc_str);
 2544     if (!data) {
 2545         GF_FREE(alloc_str);
 2546         ret = -EINVAL;
 2547         goto out;
 2548     }
 2549 
 2550     ret = dict_add(this, key, data);
 2551     if (ret < 0)
 2552         data_destroy(data);
 2553 
 2554 out:
 2555     return ret;
 2556 }
 2557 
 2558 int
 2559 dict_get_bin(dict_t *this, char *key, void **bin)
 2560 {
 2561     data_t *data = NULL;
 2562     int ret = -EINVAL;
 2563 
 2564     if (!this || !key || !bin) {
 2565         goto err;
 2566     }
 2567 
 2568     ret = dict_get_with_ref(this, key, &data);
 2569     if (ret < 0) {
 2570         goto err;
 2571     }
 2572 
 2573     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_PTR, key, ret);
 2574 
 2575     *bin = data->data;
 2576 
 2577 err:
 2578     if (data)
 2579         data_unref(data);
 2580 
 2581     return ret;
 2582 }
 2583 
 2584 /********************************************************************
 2585  *
 2586  * dict_set_bin_common:
 2587  *      This is the common function to set key and its value in
 2588  *      dictionary. Flag(is_static) should be set appropriately based
 2589  *      on the type of memory type used for value(*ptr). If flag is set
 2590  *      to false value(*ptr) will be freed using GF_FREE() on destroy.
 2591  *
 2592  *******************************************************************/
 2593 static int
 2594 dict_set_bin_common(dict_t *this, char *key, void *ptr, size_t size,
 2595                     gf_boolean_t is_static, gf_dict_data_type_t type)
 2596 {
 2597     data_t *data = NULL;
 2598     int ret = 0;
 2599 
 2600     if (!ptr || (size > DICT_KEY_VALUE_MAX_SIZE)) {
 2601         ret = -EINVAL;
 2602         goto err;
 2603     }
 2604 
 2605     data = bin_to_data(ptr, size);
 2606     if (!data) {
 2607         ret = -EINVAL;
 2608         goto err;
 2609     }
 2610 
 2611     data->is_static = is_static;
 2612     data->data_type = type;
 2613 
 2614     ret = dict_set(this, key, data);
 2615     if (ret < 0) {
 2616         /* don't free data->data, let callers handle it */
 2617         data->data = NULL;
 2618         data_destroy(data);
 2619     }
 2620 
 2621 err:
 2622     return ret;
 2623 }
 2624 
 2625 /********************************************************************
 2626  *
 2627  * dict_set_bin:
 2628  *      Set key and its value in the dictionary. This function should
 2629  *      be called if the value is stored in dynamic memory.
 2630  *
 2631  *******************************************************************/
 2632 int
 2633 dict_set_bin(dict_t *this, char *key, void *ptr, size_t size)
 2634 {
 2635     return dict_set_bin_common(this, key, ptr, size, _gf_false,
 2636                                GF_DATA_TYPE_PTR);
 2637 }
 2638 
 2639 /********************************************************************
 2640  *
 2641  * dict_set_static_bin:
 2642  *      Set key and its value in the dictionary. This function should
 2643  *      be called if the value is stored in static memory.
 2644  *
 2645  *******************************************************************/
 2646 int
 2647 dict_set_static_bin(dict_t *this, char *key, void *ptr, size_t size)
 2648 {
 2649     return dict_set_bin_common(this, key, ptr, size, _gf_true,
 2650                                GF_DATA_TYPE_PTR);
 2651 }
 2652 
 2653 /*  */
 2654 int
 2655 dict_set_gfuuid(dict_t *this, char *key, uuid_t gfid, bool is_static)
 2656 {
 2657     return dict_set_bin_common(this, key, gfid, sizeof(uuid_t), is_static,
 2658                                GF_DATA_TYPE_GFUUID);
 2659 }
 2660 
 2661 int
 2662 dict_get_gfuuid(dict_t *this, char *key, uuid_t *gfid)
 2663 {
 2664     data_t *data = NULL;
 2665     int ret = -EINVAL;
 2666 
 2667     if (!this || !key || !gfid) {
 2668         goto err;
 2669     }
 2670     ret = dict_get_with_ref(this, key, &data);
 2671     if (ret < 0) {
 2672         goto err;
 2673     }
 2674 
 2675     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_GFUUID, key, -EINVAL);
 2676 
 2677     memcpy(*gfid, data->data, min(data->len, sizeof(uuid_t)));
 2678 
 2679 err:
 2680     if (data)
 2681         data_unref(data);
 2682 
 2683     return ret;
 2684 }
 2685 
 2686 int
 2687 dict_set_mdata(dict_t *this, char *key, struct mdata_iatt *mdata,
 2688                bool is_static)
 2689 {
 2690     return dict_set_bin_common(this, key, mdata, sizeof(struct mdata_iatt),
 2691                                is_static, GF_DATA_TYPE_MDATA);
 2692 }
 2693 
 2694 int
 2695 dict_get_mdata(dict_t *this, char *key, struct mdata_iatt *mdata)
 2696 {
 2697     data_t *data = NULL;
 2698     int ret = -EINVAL;
 2699 
 2700     if (!this || !key || !mdata) {
 2701         goto err;
 2702     }
 2703     ret = dict_get_with_ref(this, key, &data);
 2704     if (ret < 0) {
 2705         goto err;
 2706     }
 2707 
 2708     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_MDATA, key, -EINVAL);
 2709     if (data->len < sizeof(struct mdata_iatt)) {
 2710         gf_smsg("glusterfs", GF_LOG_ERROR, ENOBUFS, LG_MSG_UNDERSIZED_BUF,
 2711                 "key=%s", key, NULL);
 2712         ret = -ENOBUFS;
 2713         goto err;
 2714     }
 2715 
 2716     memcpy(mdata, data->data, min(data->len, sizeof(struct mdata_iatt)));
 2717 
 2718 err:
 2719     if (data)
 2720         data_unref(data);
 2721 
 2722     return ret;
 2723 }
 2724 
 2725 int
 2726 dict_set_iatt(dict_t *this, char *key, struct iatt *iatt, bool is_static)
 2727 {
 2728     return dict_set_bin_common(this, key, iatt, sizeof(struct iatt), is_static,
 2729                                GF_DATA_TYPE_IATT);
 2730 }
 2731 
 2732 int
 2733 dict_get_iatt(dict_t *this, char *key, struct iatt *iatt)
 2734 {
 2735     data_t *data = NULL;
 2736     int ret = -EINVAL;
 2737 
 2738     if (!this || !key || !iatt) {
 2739         goto err;
 2740     }
 2741     ret = dict_get_with_ref(this, key, &data);
 2742     if (ret < 0) {
 2743         goto err;
 2744     }
 2745 
 2746     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_IATT, key, -EINVAL);
 2747 
 2748     memcpy(iatt, data->data, min(data->len, sizeof(struct iatt)));
 2749 
 2750 err:
 2751     if (data)
 2752         data_unref(data);
 2753 
 2754     return ret;
 2755 }
 2756 
 2757 /**
 2758  * dict_get_str_boolean - get a boolean value based on string representation.
 2759  *
 2760  * @this        : dictionary
 2761  * @key         : dictionary key queried
 2762  * @default_val : default value if key not found
 2763  *
 2764  * @return      : @default_val if key not found
 2765  *              : boolean interpretation of @this[@key] if it makes sense
 2766  *                (ie., "on", "true", "enable" ...)
 2767  *              : -1 if error occurs or @this[@key] doesn't make sens as
 2768  *                  boolean
 2769  *
 2770  *   So if you query a boolean option, then via @default_val you can choose
 2771  *   between following patterns:
 2772  *
 2773  *   - fall back to _gf_false if @key is not set  [@default_val = 0]
 2774  *   - fall back to _gf_true if @key is not set   [@default_val = 1]
 2775  *   - regard as failure if @key is not set       [@default_val = -1]
 2776  *   - handle specially (not as error) if @key is not set
 2777  *                                                [@default_val = anything else]
 2778  */
 2779 
 2780 int
 2781 dict_get_str_boolean(dict_t *this, char *key, int default_val)
 2782 {
 2783     data_t *data = NULL;
 2784     gf_boolean_t boo = _gf_false;
 2785     int ret = 0;
 2786 
 2787     ret = dict_get_with_ref(this, key, &data);
 2788     if (ret < 0) {
 2789         if (ret == -ENOENT)
 2790             ret = default_val;
 2791         else
 2792             ret = -1;
 2793         goto err;
 2794     }
 2795 
 2796     VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_INT, key, -EINVAL);
 2797 
 2798     ret = gf_strn2boolean(data->data, data->len - 1, &boo);
 2799     if (ret == -1)
 2800         goto err;
 2801 
 2802     ret = boo;
 2803 
 2804 err:
 2805     if (data)
 2806         data_unref(data);
 2807 
 2808     return ret;
 2809 }
 2810 
 2811 int
 2812 dict_rename_key(dict_t *this, char *key, char *replace_key)
 2813 {
 2814     data_pair_t *pair = NULL;
 2815     int ret = -EINVAL;
 2816     uint32_t hash;
 2817     uint32_t replacekey_hash;
 2818     int replacekey_len;
 2819 
 2820     /* replacing a key by itself is a NO-OP */
 2821     if (strcmp(key, replace_key) == 0)
 2822         return 0;
 2823 
 2824     if (!this) {
 2825         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 2826                          "dict is NULL");
 2827         return ret;
 2828     }
 2829 
 2830     hash = (uint32_t)XXH64(key, strlen(key), 0);
 2831     replacekey_len = strlen(replace_key);
 2832     replacekey_hash = (uint32_t)XXH64(replace_key, replacekey_len, 0);
 2833 
 2834     LOCK(&this->lock);
 2835     {
 2836         /* no need to data_ref(pair->value), dict_set_lk() does it */
 2837         pair = dict_lookup_common(this, key, hash);
 2838         if (!pair)
 2839             ret = -ENODATA;
 2840         else
 2841             ret = dict_set_lk(this, replace_key, replacekey_len, pair->value,
 2842                               replacekey_hash, 1);
 2843     }
 2844     UNLOCK(&this->lock);
 2845 
 2846     if (!ret)
 2847         /* only delete the key on success */
 2848         dict_del(this, key);
 2849 
 2850     return ret;
 2851 }
 2852 
 2853 /**
 2854  * Serialization format:
 2855  *  -------- --------  --------  ----------- -------------
 2856  * |  count | key len | val len | key     \0| value
 2857  *  ---------------------------------------- -------------
 2858  *     4        4         4       <key len>   <value len>
 2859  */
 2860 
 2861 /**
 2862  * dict_serialized_length_lk - return the length of serialized dict. This
 2863  *                             procedure has to be called with this->lock held.
 2864  *
 2865  * @this  : dict to be serialized
 2866  * @return: success: len
 2867  *        : failure: -errno
 2868  */
 2869 
 2870 int
 2871 dict_serialized_length_lk(dict_t *this)
 2872 {
 2873     int ret = -EINVAL;
 2874     int count = this->count;
 2875     int len = DICT_HDR_LEN;
 2876     data_pair_t *pair = this->members_list;
 2877 
 2878     if (count < 0) {
 2879         gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_COUNT_LESS_THAN_ZERO,
 2880                 "count=%d", count, NULL);
 2881         goto out;
 2882     }
 2883 
 2884     while (count) {
 2885         if (!pair) {
 2886             gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_PAIRS_LESS_THAN_COUNT,
 2887                     NULL);
 2888             goto out;
 2889         }
 2890 
 2891         len += DICT_DATA_HDR_KEY_LEN + DICT_DATA_HDR_VAL_LEN;
 2892 
 2893         if (!pair->key) {
 2894             gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_NULL_PTR, NULL);
 2895             goto out;
 2896         }
 2897 
 2898         len += strlen(pair->key) + 1 /* for '\0' */;
 2899 
 2900         if (!pair->value) {
 2901             gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_NULL_PTR, NULL);
 2902             goto out;
 2903         }
 2904 
 2905         if (pair->value->len < 0) {
 2906             gf_smsg("dict", GF_LOG_ERROR, EINVAL,
 2907                     LG_MSG_VALUE_LENGTH_LESS_THAN_ZERO, "len=%d",
 2908                     pair->value->len, NULL);
 2909             goto out;
 2910         }
 2911 
 2912         len += pair->value->len;
 2913 
 2914         pair = pair->next;
 2915         count--;
 2916     }
 2917 
 2918     ret = len;
 2919 out:
 2920     return ret;
 2921 }
 2922 
 2923 /**
 2924  * dict_serialize_lk - serialize a dictionary into a buffer. This procedure has
 2925  *                     to be called with this->lock held.
 2926  *
 2927  * @this: dict to serialize
 2928  * @buf:  buffer to serialize into. This must be
 2929  *        at least dict_serialized_length (this) large
 2930  *
 2931  * @return: success: 0
 2932  *          failure: -errno
 2933  */
 2934 
 2935 static int
 2936 dict_serialize_lk(dict_t *this, char *buf)
 2937 {
 2938     int ret = -1;
 2939     data_pair_t *pair = this->members_list;
 2940     int32_t count = this->count;
 2941     int32_t keylen = 0;
 2942     int32_t netword = 0;
 2943 
 2944     if (!buf) {
 2945         gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, NULL);
 2946         goto out;
 2947     }
 2948 
 2949     if (count < 0) {
 2950         gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_COUNT_LESS_THAN_ZERO,
 2951                 "count=%d", count, NULL);
 2952         goto out;
 2953     }
 2954 
 2955     netword = hton32(count);
 2956     memcpy(buf, &netword, sizeof(netword));
 2957     buf += DICT_HDR_LEN;
 2958 
 2959     while (count) {
 2960         if (!pair) {
 2961             gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_PAIRS_LESS_THAN_COUNT,
 2962                     NULL);
 2963             goto out;
 2964         }
 2965 
 2966         if (!pair->key) {
 2967             gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_PTR, NULL);
 2968             goto out;
 2969         }
 2970 
 2971         keylen = strlen(pair->key);
 2972         netword = hton32(keylen);
 2973         memcpy(buf, &netword, sizeof(netword));
 2974         buf += DICT_DATA_HDR_KEY_LEN;
 2975 
 2976         if (!pair->value) {
 2977             gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_PTR, NULL);
 2978             goto out;
 2979         }
 2980 
 2981         netword = hton32(pair->value->len);
 2982         memcpy(buf, &netword, sizeof(netword));
 2983         buf += DICT_DATA_HDR_VAL_LEN;
 2984 
 2985         memcpy(buf, pair->key, keylen);
 2986         buf += keylen;
 2987         *buf++ = '\0';
 2988 
 2989         if (pair->value->data) {
 2990             memcpy(buf, pair->value->data, pair->value->len);
 2991             buf += pair->value->len;
 2992         }
 2993 
 2994         pair = pair->next;
 2995         count--;
 2996     }
 2997 
 2998     ret = 0;
 2999 out:
 3000     return ret;
 3001 }
 3002 
 3003 /**
 3004  * dict_serialized_length - return the length of serialized dict
 3005  *
 3006  * @this:   dict to be serialized
 3007  * @return: success: len
 3008  *        : failure: -errno
 3009  */
 3010 
 3011 int
 3012 dict_serialized_length(dict_t *this)
 3013 {
 3014     int ret = -EINVAL;
 3015 
 3016     if (!this) {
 3017         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 3018                          "dict is null!");
 3019         goto out;
 3020     }
 3021 
 3022     LOCK(&this->lock);
 3023     {
 3024         ret = dict_serialized_length_lk(this);
 3025     }
 3026     UNLOCK(&this->lock);
 3027 
 3028 out:
 3029     return ret;
 3030 }
 3031 
 3032 /**
 3033  * dict_serialize - serialize a dictionary into a buffer
 3034  *
 3035  * @this: dict to serialize
 3036  * @buf:  buffer to serialize into. This must be
 3037  *        at least dict_serialized_length (this) large
 3038  *
 3039  * @return: success: 0
 3040  *          failure: -errno
 3041  */
 3042 
 3043 int
 3044 dict_serialize(dict_t *this, char *buf)
 3045 {
 3046     int ret = -1;
 3047 
 3048     if (!this || !buf) {
 3049         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 3050                          "dict is null!");
 3051         goto out;
 3052     }
 3053 
 3054     LOCK(&this->lock);
 3055     {
 3056         ret = dict_serialize_lk(this, buf);
 3057     }
 3058     UNLOCK(&this->lock);
 3059 out:
 3060     return ret;
 3061 }
 3062 
 3063 /**
 3064  * dict_unserialize - unserialize a buffer into a dict
 3065  *
 3066  * @buf:  buf containing serialized dict
 3067  * @size: size of the @buf
 3068  * @fill: dict to fill in
 3069  *
 3070  * @return: success: 0
 3071  *          failure: -errno
 3072  */
 3073 
 3074 int32_t
 3075 dict_unserialize(char *orig_buf, int32_t size, dict_t **fill)
 3076 {
 3077     char *buf = orig_buf;
 3078     int ret = -1;
 3079     int32_t count = 0;
 3080     int i = 0;
 3081 
 3082     data_t *value = NULL;
 3083     char *key = NULL;
 3084     int32_t keylen = 0;
 3085     int32_t vallen = 0;
 3086     int32_t hostord = 0;
 3087 
 3088     if (!buf) {
 3089         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 3090                          "buf is null!");
 3091         goto out;
 3092     }
 3093 
 3094     if (size == 0) {
 3095         gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
 3096                          "size is 0!");
 3097         goto out;
 3098     }
 3099 
 3100     if (!fill) {
 3101         gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
 3102                          "fill is null!");
 3103         goto out;
 3104     }
 3105 
 3106     if (!*fill) {
 3107         gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
 3108                          "*fill is null!");
 3109         goto out;
 3110     }
 3111 
 3112     if ((buf + DICT_HDR_LEN) > (orig_buf + size)) {
 3113         gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
 3114                          "undersized buffer "
 3115                          "passed. available (%lu) < required (%lu)",
 3116                          (long)(orig_buf + size), (long)(buf + DICT_HDR_LEN));
 3117         goto out;
 3118     }
 3119 
 3120     memcpy(&hostord, buf, sizeof(hostord));
 3121     count = ntoh32(hostord);
 3122     buf += DICT_HDR_LEN;
 3123 
 3124     if (count < 0) {
 3125         gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_COUNT_LESS_THAN_ZERO,
 3126                 "count=%d", count, NULL);
 3127         goto out;
 3128     }
 3129 
 3130     /* count will be set by the dict_set's below */
 3131     (*fill)->count = 0;
 3132 
 3133     for (i = 0; i < count; i++) {
 3134         if ((buf + DICT_DATA_HDR_KEY_LEN) > (orig_buf + size)) {
 3135             gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
 3136                              "undersized "
 3137                              "buffer passed. available (%lu) < "
 3138                              "required (%lu)",
 3139                              (long)(orig_buf + size),
 3140                              (long)(buf + DICT_DATA_HDR_KEY_LEN));
 3141             goto out;
 3142         }
 3143         memcpy(&hostord, buf, sizeof(hostord));
 3144         keylen = ntoh32(hostord);
 3145         buf += DICT_DATA_HDR_KEY_LEN;
 3146 
 3147         if ((buf + DICT_DATA_HDR_VAL_LEN) > (orig_buf + size)) {
 3148             gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
 3149                              "undersized "
 3150                              "buffer passed. available (%lu) < "
 3151                              "required (%lu)",
 3152                              (long)(orig_buf + size),
 3153                              (long)(buf + DICT_DATA_HDR_VAL_LEN));
 3154             goto out;
 3155         }
 3156         memcpy(&hostord, buf, sizeof(hostord));
 3157         vallen = ntoh32(hostord);
 3158         buf += DICT_DATA_HDR_VAL_LEN;
 3159 
 3160         if ((keylen < 0) || (vallen < 0)) {
 3161             gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
 3162                              "undersized length passed "
 3163                              "key:%d val:%d",
 3164                              keylen, vallen);
 3165             goto out;
 3166         }
 3167         if ((buf + keylen) > (orig_buf + size)) {
 3168             gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
 3169                              "undersized buffer passed. "
 3170                              "available (%lu) < required (%lu)",
 3171                              (long)(orig_buf + size), (long)(buf + keylen));
 3172             goto out;
 3173         }
 3174         key = buf;
 3175         buf += keylen + 1; /* for '\0' */
 3176 
 3177         if ((buf + vallen) > (orig_buf + size)) {
 3178             gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
 3179                              "undersized buffer passed. "
 3180                              "available (%lu) < required (%lu)",
 3181                              (long)(orig_buf + size), (long)(buf + vallen));
 3182             goto out;
 3183         }
 3184         value = get_new_data();
 3185 
 3186         if (!value) {
 3187             ret = -1;
 3188             goto out;
 3189         }
 3190         value->len = vallen;
 3191         value->data = gf_memdup(buf, vallen);
 3192         value->data_type = GF_DATA_TYPE_STR_OLD;
 3193         value->is_static = _gf_false;
 3194         buf += vallen;
 3195 
 3196         ret = dict_addn(*fill, key, keylen, value);
 3197         if (ret < 0)
 3198             goto out;
 3199     }
 3200 
 3201     ret = 0;
 3202 out:
 3203     return ret;
 3204 }
 3205 
 3206 /**
 3207  * dict_allocate_and_serialize - serialize a dictionary into an allocated buffer
 3208  *
 3209  * @this: dict to serialize
 3210  * @buf:  pointer to pointer to character. The allocated buffer is stored in
 3211  *        this pointer. The buffer has to be freed by the caller.
 3212  *
 3213  * @return: success: 0
 3214  *          failure: -errno
 3215  */
 3216 
 3217 int32_t
 3218 dict_allocate_and_serialize(dict_t *this, char **buf, u_int *length)
 3219 {
 3220     int ret = -EINVAL;
 3221     ssize_t len = 0;
 3222 
 3223     if (!this || !buf) {
 3224         gf_msg_debug("dict", 0, "dict OR buf is NULL");
 3225         goto out;
 3226     }
 3227 
 3228     LOCK(&this->lock);
 3229     {
 3230         len = dict_serialized_length_lk(this);
 3231         if (len < 0) {
 3232             ret = len;
 3233             goto unlock;
 3234         }
 3235 
 3236         *buf = GF_MALLOC(len, gf_common_mt_char);
 3237         if (*buf == NULL) {
 3238             ret = -ENOMEM;
 3239             goto unlock;
 3240         }
 3241 
 3242         ret = dict_serialize_lk(this, *buf);
 3243         if (ret < 0) {
 3244             GF_FREE(*buf);
 3245             *buf = NULL;
 3246             goto unlock;
 3247         }
 3248 
 3249         if (length != NULL) {
 3250             *length = len;
 3251         }
 3252     }
 3253 unlock:
 3254     UNLOCK(&this->lock);
 3255 out:
 3256     return ret;
 3257 }
 3258 
 3259 /**
 3260  * dict_serialize_value_with_delim_lk: serialize the values in the dictionary
 3261  * into a buffer separated by delimiter (except the last)
 3262  *
 3263  * @this      : dictionary to serialize
 3264  * @buf       : the buffer to store the serialized data
 3265  * @serz_len  : the length of the serialized data (excluding the last delimiter)
 3266  * @delimiter : the delimiter to separate the values
 3267  *
 3268  * @return    : 0 -> success
 3269  *            : -errno -> failure
 3270  */
 3271 int
 3272 dict_serialize_value_with_delim_lk(dict_t *this, char *buf, int32_t *serz_len,
 3273                                    char delimiter)
 3274 {
 3275     int ret = -1;
 3276     int32_t count = this->count;
 3277     int32_t vallen = 0;
 3278     int32_t total_len = 0;
 3279     data_pair_t *pair = this->members_list;
 3280 
 3281     if (!buf) {
 3282         gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, NULL);
 3283         goto out;
 3284     }
 3285 
 3286     if (count < 0) {
 3287         gf_smsg("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "count=%d",
 3288                 count, NULL);
 3289         goto out;
 3290     }
 3291 
 3292     while (count) {
 3293         if (!pair) {
 3294             gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_PAIRS_LESS_THAN_COUNT,
 3295                     NULL);
 3296             goto out;
 3297         }
 3298 
 3299         if (!pair->key || !pair->value) {
 3300             gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_KEY_OR_VALUE_NULL, NULL);
 3301             goto out;
 3302         }
 3303 
 3304         if (!pair->value->data) {
 3305             gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_NULL_VALUE_IN_DICT, NULL);
 3306             goto out;
 3307         }
 3308 
 3309         vallen = pair->value->len - 1;  // length includes \0
 3310         memcpy(buf, pair->value->data, vallen);
 3311         buf += vallen;
 3312         *buf++ = delimiter;
 3313 
 3314         total_len += (vallen + 1);
 3315 
 3316         pair = pair->next;
 3317         count--;
 3318     }
 3319 
 3320     *--buf = '\0';  // remove the last delimiter
 3321     total_len--;    // adjust the length
 3322     ret = 0;
 3323 
 3324     if (serz_len)
 3325         *serz_len = total_len;
 3326 
 3327 out:
 3328     return ret;
 3329 }
 3330 
 3331 int
 3332 dict_serialize_value_with_delim(dict_t *this, char *buf, int32_t *serz_len,
 3333                                 char delimiter)
 3334 {
 3335     int ret = -1;
 3336 
 3337     if (!this || !buf) {
 3338         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 3339                          "dict is null!");
 3340         goto out;
 3341     }
 3342 
 3343     LOCK(&this->lock);
 3344     {
 3345         ret = dict_serialize_value_with_delim_lk(this, buf, serz_len,
 3346                                                  delimiter);
 3347     }
 3348     UNLOCK(&this->lock);
 3349 out:
 3350     return ret;
 3351 }
 3352 
 3353 int
 3354 dict_dump_to_str(dict_t *dict, char *dump, int dumpsize, char *format)
 3355 {
 3356     int ret = 0;
 3357     int dumplen = 0;
 3358     data_pair_t *trav = NULL;
 3359 
 3360     if (!dict)
 3361         return 0;
 3362 
 3363     for (trav = dict->members_list; trav; trav = trav->next) {
 3364         ret = snprintf(&dump[dumplen], dumpsize - dumplen, format, trav->key,
 3365                        trav->value->data);
 3366         if ((ret == -1) || !ret)
 3367             return ret;
 3368 
 3369         dumplen += ret;
 3370     }
 3371     return 0;
 3372 }
 3373 
 3374 void
 3375 dict_dump_to_log(dict_t *dict)
 3376 {
 3377     int ret = -1;
 3378     char *dump = NULL;
 3379     const int dump_size = 64 * 1024;
 3380     char *format = "(%s:%s)";
 3381 
 3382     if (!dict) {
 3383         gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 3384                          "dict is NULL");
 3385         goto out;
 3386     }
 3387 
 3388     dump = GF_MALLOC(dump_size, gf_common_mt_char);
 3389     if (!dump) {
 3390         gf_msg_callingfn("dict", GF_LOG_WARNING, ENOMEM, LG_MSG_NO_MEMORY,
 3391                          "dump buffer is NULL");
 3392         goto out;
 3393     }
 3394 
 3395     ret = dict_dump_to_str(dict, dump, dump_size, format);
 3396     if (ret) {
 3397         gf_smsg("dict", GF_LOG_WARNING, 0, LG_MSG_FAILED_TO_LOG_DICT, NULL);
 3398         goto out;
 3399     }
 3400     gf_smsg("dict", GF_LOG_INFO, 0, LG_MSG_DICT_ERROR, "dict=%p", dict,
 3401             "dump=%s", dump, NULL);
 3402 out:
 3403     GF_FREE(dump);
 3404 
 3405     return;
 3406 }
 3407 
 3408 void
 3409 dict_dump_to_statedump(dict_t *dict, char *dict_name, char *domain)
 3410 {
 3411     int ret = -1;
 3412     char *dump = NULL;
 3413     const int dump_size = 64 * 1024;
 3414     char key[4096] = {
 3415         0,
 3416     };
 3417     char *format = "\n\t%s:%s";
 3418 
 3419     if (!dict) {
 3420         gf_msg_callingfn(domain, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 3421                          "dict is NULL");
 3422         goto out;
 3423     }
 3424 
 3425     dump = GF_MALLOC(dump_size, gf_common_mt_char);
 3426     if (!dump) {
 3427         gf_msg_callingfn(domain, GF_LOG_WARNING, ENOMEM, LG_MSG_NO_MEMORY,
 3428                          "dump buffer is NULL");
 3429         goto out;
 3430     }
 3431 
 3432     ret = dict_dump_to_str(dict, dump, dump_size, format);
 3433     if (ret) {
 3434         gf_smsg(domain, GF_LOG_WARNING, 0, LG_MSG_FAILED_TO_LOG_DICT, "name=%s",
 3435                 dict_name, NULL);
 3436         goto out;
 3437     }
 3438     gf_proc_dump_build_key(key, domain, "%s", dict_name);
 3439     gf_proc_dump_write(key, "%s", dump);
 3440 
 3441 out:
 3442     GF_FREE(dump);
 3443 
 3444     return;
 3445 }
 3446 
 3447 dict_t *
 3448 dict_for_key_value(const char *name, const char *value, size_t size,
 3449                    gf_boolean_t is_static)
 3450 {
 3451     dict_t *xattr = dict_new();
 3452     int ret = 0;
 3453 
 3454     if (!xattr)
 3455         return NULL;
 3456 
 3457     if (is_static)
 3458         ret = dict_set_static_bin(xattr, (char *)name, (void *)value, size);
 3459     else
 3460         ret = dict_set_bin(xattr, (char *)name, (void *)value, size);
 3461 
 3462     if (ret) {
 3463         dict_destroy(xattr);
 3464         xattr = NULL;
 3465     }
 3466 
 3467     return xattr;
 3468 }
 3469 
 3470 /*
 3471  * "strings" should be NULL terminated strings array.
 3472  */
 3473 int
 3474 dict_has_key_from_array(dict_t *dict, char **strings, gf_boolean_t *result)
 3475 {
 3476     int i = 0;
 3477     uint32_t hash = 0;
 3478 
 3479     if (!dict || !strings || !result)
 3480         return -EINVAL;
 3481 
 3482     LOCK(&dict->lock);
 3483     {
 3484         for (i = 0; strings[i]; i++) {
 3485             hash = (uint32_t)XXH64(strings[i], strlen(strings[i]), 0);
 3486             if (dict_lookup_common(dict, strings[i], hash)) {
 3487                 *result = _gf_true;
 3488                 goto unlock;
 3489             }
 3490         }
 3491         *result = _gf_false;
 3492     }
 3493 unlock:
 3494     UNLOCK(&dict->lock);
 3495     return 0;
 3496 }