diff options
| author | Raghavendra G <raghavendra@zresearch.com> | 2009-05-15 03:55:20 -0700 | 
|---|---|---|
| committer | Anand V. Avati <avati@amp.gluster.com> | 2009-05-16 16:40:18 +0530 | 
| commit | 9669c70c901474dc21ef08e49478b5f5dead8f64 (patch) | |
| tree | 9040bceccf4c3aaec5966655900f7fac11de3646 /libglusterfs | |
| parent | dec2674685da30d6cef157748bcf52454ec97208 (diff) | |
dict.c: Add dict_allocate_and_serialize
- this procedure atomically allocates a buffer and serializes dict into it.
  - this procedure helps avoid memory corruptions due to race conditions where
    in new members are added into dict between allocating a buffer for
    serializing and actually serializing buffer into it.
Signed-off-by: Anand V. Avati <avati@amp.gluster.com>
Diffstat (limited to 'libglusterfs')
| -rw-r--r-- | libglusterfs/src/dict.c | 227 | ||||
| -rw-r--r-- | libglusterfs/src/dict.h | 3 | 
2 files changed, 230 insertions, 0 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index 22e350e0e9a..b4c75d79f89 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -2050,6 +2050,173 @@ err:  #define DICT_DATA_HDR_VAL_LEN      4  /** + * _dict_serialized_length - return the length of serialized dict. This + *                           procedure has to be called with this->lock held. + * + * @this  : dict to be serialized + * @return: success: len + *        : failure: -errno + */ + +int +_dict_serialized_length (dict_t *this) +{ +	int ret            = -EINVAL; +	int count          = 0; +	int len            = 0; +	int i              = 0; +	data_pair_t * pair = NULL; + +	len = DICT_HDR_LEN; +	count = this->count; + +	if (count < 0) { +		gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count); +		goto out; +	} + +	pair = this->members_list; + +	while (count) { +		if (!pair) { +			gf_log ("dict", GF_LOG_ERROR,  +				"less than count data pairs found!"); +			goto out; +		} + +		len += DICT_DATA_HDR_KEY_LEN + DICT_DATA_HDR_VAL_LEN; + +		if (!pair->key) { +			gf_log ("dict", GF_LOG_ERROR, "pair->key is null!"); +			goto out; +		} + +		len += strlen (pair->key) + 1  /* for '\0' */; + +		if (!pair->value) { +			gf_log ("dict", GF_LOG_ERROR, +				"pair->value is null!"); +			goto out; +		} + +		if (pair->value->vec) { +			for (i = 0; i < pair->value->len; i++) { +				if (pair->value->vec[i].iov_len < 0) { +					gf_log ("dict", GF_LOG_ERROR, +						"iov_len (%"GF_PRI_SIZET") < 0!", +						pair->value->vec[i].iov_len); +					goto out; +				} + +				len += pair->value->vec[i].iov_len; +			} +		} else { +			if (pair->value->len < 0) { +				gf_log ("dict", GF_LOG_ERROR, +					"value->len (%d) < 0", +					pair->value->len); +				goto out; +			} + +			len += pair->value->len; +		} + +		pair = pair->next; +		count--; +	} +	 +	ret = len; +out: +	return ret; +} + +/** + * _dict_serialize - serialize a dictionary into a buffer. This procedure has  + *                   to be called with this->lock held. + * + * @this: dict to serialize + * @buf:  buffer to serialize into. This must be  + *        atleast dict_serialized_length (this) large + * + * @return: success: 0 + *          failure: -errno + */ + +int +_dict_serialize (dict_t *this, char *buf) +{ +	int           ret    = -1; +	data_pair_t * pair   = NULL; +	int32_t       count  = 0; +	int32_t       keylen = 0; +	int32_t       vallen = 0; +	 +	if (!buf) { +		gf_log ("dict", GF_LOG_ERROR, +			"buf is null!"); +		goto out; +	} +	 +	count = this->count; +	if (count < 0) { +		gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count); +		goto out; +	} + +	*(int32_t *) buf = hton32 (count); +	buf += DICT_HDR_LEN; +	pair = this->members_list; + +	while (count) { +		if (!pair) { +			gf_log ("dict", GF_LOG_ERROR, +				"less than count data pairs found!"); +			goto out; +		} + +		if (!pair->key) { +			gf_log ("dict", GF_LOG_ERROR, +				"pair->key is null!"); +			goto out; +		} + +		keylen  = strlen (pair->key); +		*(int32_t *) buf = hton32 (keylen); +		buf += DICT_DATA_HDR_KEY_LEN; + +		if (!pair->value) { +			gf_log ("dict", GF_LOG_ERROR, +				"pair->value is null!"); +			goto out; +		} + +		vallen  = pair->value->len; +		*(int32_t *) buf = hton32 (vallen); +		buf += DICT_DATA_HDR_VAL_LEN; + +		memcpy (buf, pair->key, keylen); +		buf += keylen; +		*buf++ = '\0'; + +		if (!pair->value->data) { +			gf_log ("dict", GF_LOG_ERROR, +				"pair->value->data is null!"); +			goto out; +		} +		memcpy (buf, pair->value->data, vallen); +		buf += vallen; + +		pair = pair->next; +		count--; +	} + +	ret = 0; +out: +	return ret; +} + + +/**   * dict_serialized_length - return the length of serialized dict   *   * @this:   dict to be serialized @@ -2337,3 +2504,63 @@ out:  	return ret;  } + +/** + * dict_allocate_and_serialize - serialize a dictionary into an allocated buffer + * + * @this: dict to serialize + * @buf:  pointer to pointer to character. The allocated buffer is stored in + *        this pointer. The buffer has to be freed by the caller.  + * + * @return: success: 0 + *          failure: -errno + */ + +int32_t +dict_allocate_and_serialize (dict_t *this, char **buf, size_t *length) +{ +	int           ret    = -EINVAL; +        ssize_t       len = 0;  + +	if (!this) { +		gf_log ("dict", GF_LOG_DEBUG, +			"NULL passed as this pointer"); +		goto out; +	} +	if (!buf) { +		gf_log ("dict", GF_LOG_DEBUG, +			"NULL passed as buf"); +		goto out; +	} +	 +        LOCK (&this->lock); +        {  +                len = _dict_serialized_length (this); +                if (len < 0) { +                        ret = len; +                        goto unlock; +                } + +                *buf = CALLOC (1, len); +                if (*buf == NULL) { +                        ret = -ENOMEM; +                        gf_log ("dict", GF_LOG_ERROR, "out of memory"); +                        goto unlock; +                } + +                ret = _dict_serialize (this, *buf); +                if (ret < 0) { +                        FREE (*buf); +                        *buf = NULL; +                        goto unlock; +                } + +                if (length != NULL) { +                        *length = len; +                } +        } +unlock: +        UNLOCK (&this->lock); +out: +	return ret; +} diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index 23e0f8368f7..e2d87166ae8 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -76,6 +76,9 @@ int32_t dict_serialized_length (dict_t *dict);  int32_t dict_serialize (dict_t *dict, char *buf);  int32_t dict_unserialize (char *buf, int32_t size, dict_t **fill); +int32_t +dict_allocate_and_serialize (dict_t *this, char **buf, size_t *length); +  int32_t dict_iovec_len (dict_t *dict);  int32_t dict_to_iovec (dict_t *dict, struct iovec *vec, int32_t count);  | 
