diff options
Diffstat (limited to 'libglusterfs/src/dict.c')
| -rw-r--r-- | libglusterfs/src/dict.c | 2243 | 
1 files changed, 2243 insertions, 0 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c new file mode 100644 index 00000000000..eb181f191c3 --- /dev/null +++ b/libglusterfs/src/dict.c @@ -0,0 +1,2243 @@ +/* +  Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <inttypes.h> + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "dict.h" +#include "hashfn.h" +#include "logging.h" +#include "compat.h" +#include "byte-order.h" + +data_pair_t * +get_new_data_pair () +{ +	data_pair_t *data_pair_ptr = NULL; +   +	data_pair_ptr = (data_pair_t *) CALLOC (1, sizeof (data_pair_t)); +	ERR_ABORT (data_pair_ptr); +   +	return data_pair_ptr; +} + +data_t * +get_new_data () +{ +	data_t *data = NULL; + +	data = (data_t *) CALLOC (1, sizeof (data_t)); +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"calloc () returned NULL"); +		return NULL; +	} + +	LOCK_INIT (&data->lock); +	return data; +} + +dict_t * +get_new_dict_full (int size_hint) +{ +	dict_t *dict = CALLOC (1, sizeof (dict_t)); + +	if (!dict) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"calloc () returned NULL"); +		return NULL; +	} + +	dict->hash_size = size_hint; +	dict->members = CALLOC (size_hint, sizeof (data_pair_t *)); + +	if (!dict->members) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"calloc () returned NULL"); +		return NULL; +	} + +	LOCK_INIT (&dict->lock); + +	return dict; +} + +dict_t * +get_new_dict (void) +{ +	return get_new_dict_full (1); +} + +dict_t * +dict_new (void) +{ +	dict_t *dict = NULL; +	 +	dict = get_new_dict_full(1); +	 +	if (dict) +		dict_ref (dict); +	 +	return dict; +} + + +int32_t  +is_data_equal (data_t *one, +	       data_t *two) +{ +	if (!one || !two || !one->data || !two->data) +		return 1; + +	if (one == two) +		return 1; + +	if (one->len != two->len) +		return 0; + +	if (one->data == two->data) +		return 1; + +	if (memcmp (one->data, two->data, one->len) == 0) +		return 1; + +	return 0; +} + +void +data_destroy (data_t *data) +{ +	if (data) { +		LOCK_DESTROY (&data->lock); + +		if (!data->is_static) { +			if (data->data) +				FREE (data->data); +			if (data->vec) +				FREE (data->vec); +		} + +		data->len = 0xbabababa; +		if (!data->is_const) +			FREE (data); +	} +} + +data_t * +data_copy (data_t *old) +{ +	if (!old) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@old is NULL"); +		return NULL; +	} + +	data_t *newdata = (data_t *) CALLOC (1, sizeof (*newdata)); + +	if (!newdata) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@old is NULL"); +		return NULL; +	} + +	if (old) { +		newdata->len = old->len; +		if (old->data) +			newdata->data = memdup (old->data, old->len); +		if (old->vec) +			newdata->vec = memdup (old->vec, old->len * (sizeof (void *) + +								     sizeof (size_t))); +		if (!old->data && !old->vec) { +			gf_log ("dict", GF_LOG_CRITICAL, +				"@newdata->data || @newdata->vec got NULL from CALLOC()"); +			return NULL; +		} +	} + +	return newdata; +} + +static data_pair_t * +_dict_lookup (dict_t *this, char *key) +{ +	if (!this || !key) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@this=%p @key=%p", this, key); +		return NULL; +	} + +	int hashval = SuperFastHash (key, strlen (key)) % this->hash_size; +	data_pair_t *pair; +    +	for (pair = this->members[hashval]; pair != NULL; pair = pair->hash_next) { +		if (pair->key && !strcmp (pair->key, key)) +			return pair; +	} +   +	return NULL; +} + + +static int32_t +_dict_set (dict_t *this,  +	   char *key,  +	   data_t *value) +{ +	int hashval; +	data_pair_t *pair; +	char key_free = 0; +	int tmp = 0; + +	if (!key) { +		asprintf (&key, "ref:%p", value); +		key_free = 1; +	} + +	tmp = SuperFastHash (key, strlen (key)); +	hashval = (tmp % this->hash_size); +	pair = _dict_lookup (this, key); + +	if (pair) { +		data_t *unref_data = pair->value; +		pair->value = data_ref (value); +		data_unref (unref_data); +		if (key_free) +			FREE (key); +		/* Indicates duplicate key */ +		return 0; +	} +	pair = (data_pair_t *) CALLOC (1, sizeof (*pair)); +	if (!pair) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@pair - NULL returned by CALLOC"); +		return -1; +	} + +	pair->key = (char *) CALLOC (1, strlen (key) + 1); +	if (!pair->key) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@pair->key - NULL returned by CALLOC"); +		return -1; +	} + +	strcpy (pair->key, key); +	pair->value = data_ref (value); +  +	pair->hash_next = this->members[hashval]; +	this->members[hashval] = pair; +  +	pair->next = this->members_list; +	pair->prev = NULL; +	if (this->members_list) +		this->members_list->prev = pair; +	this->members_list = pair; +	this->count++; +   +	if (key_free) +		FREE (key); +	return 0; +} + +int32_t +dict_set (dict_t *this, +	  char *key, +	  data_t *value) +{ +	int32_t ret; + +	if (!this || !value) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@this=%p @value=%p", this, value); +		return -1; +	} + +	LOCK (&this->lock); + +	ret = _dict_set (this, key, value); + +	UNLOCK (&this->lock); + +	return ret; +} + + +data_t * +dict_get (dict_t *this, +  	  char *key) +{ +	data_pair_t *pair; + +	if (!this || !key) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p @key=%p", this, key); +		return NULL; +	} + +	LOCK (&this->lock); + +	pair = _dict_lookup (this, key); + +	UNLOCK (&this->lock); + +	if (pair) +		return pair->value; +   +	return NULL; +} + +void +dict_del (dict_t *this, +  	  char *key) +{ +	if (!this || !key) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p @key=%p", this, key); +		return; +	} + +	LOCK (&this->lock); + +	int hashval = SuperFastHash (key, strlen (key)) % this->hash_size; +	data_pair_t *pair = this->members[hashval]; +	data_pair_t *prev = NULL; +   +	while (pair) { +		if (strcmp (pair->key, key) == 0) { +			if (prev) +				prev->hash_next = pair->hash_next; +			else +				this->members[hashval] = pair->hash_next; +   +			data_unref (pair->value); +   +			if (pair->prev) +				pair->prev->next = pair->next; +			else +				this->members_list = pair->next; + +			if (pair->next) +				pair->next->prev = pair->prev; +   +			FREE (pair->key); +			FREE (pair); +			this->count--; +			break; +		} +  +		prev = pair; +		pair = pair->hash_next; +	} + +	UNLOCK (&this->lock); + +	return; +} + +void +dict_destroy (dict_t *this) +{ +	if (!this) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p", this); +		return; +	} + +	data_pair_t *pair = this->members_list; +	data_pair_t *prev = this->members_list; + +	LOCK_DESTROY (&this->lock); + +	while (prev) { +		pair = pair->next; +		data_unref (prev->value); +		FREE (prev->key); +		FREE (prev); +		prev = pair; +	} + +	FREE (this->members); + +	if (this->extra_free) +		FREE (this->extra_free); + +	if (!this->is_static) +		FREE (this); + +	return; +} + +void +dict_unref (dict_t *this) +{ +	int32_t ref; + +	if (!this) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p", this); +		return; +	} + +	LOCK (&this->lock); + +	this->refcount--; +	ref = this->refcount; + +	UNLOCK (&this->lock); + +	if (!ref) +		dict_destroy (this); +} + +dict_t * +dict_ref (dict_t *this) +{ +	if (!this) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p", this); +		return NULL; +	} + +	LOCK (&this->lock); + +	this->refcount++; + +	UNLOCK (&this->lock); + +	return this; +} + +void +data_unref (data_t *this) +{ +	int32_t ref; + +	if (!this) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p", this); +		return; +	} + +	LOCK (&this->lock); + +	this->refcount--; +	ref = this->refcount; + +	UNLOCK (&this->lock); + +	if (!ref) +		data_destroy (this); +} + +data_t * +data_ref (data_t *this) +{ +	if (!this) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p", this); +		return NULL; +	} + +	LOCK (&this->lock); + +	this->refcount++; + +	UNLOCK (&this->lock); + +	return this; +} + +/* +  Serialization format: +  ---- +  Count:8 +  Key_len:8:Value_len:8 +  Key +  Value +  . +  . +  . +*/ + +int32_t  +dict_serialized_length_old (dict_t *this) +{ + +	if (!this) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p", this); +		return -1; +	} + +	int32_t len = 9; /* count + \n */ +	int32_t count = this->count; +	data_pair_t *pair = this->members_list; + +	while (count) { +		len += 18; +		len += strlen (pair->key) + 1; +		if (pair->value->vec) { +			int i; +			for (i=0; i<pair->value->len; i++) { +				len += pair->value->vec[i].iov_len; +			} +		} else { +			len += pair->value->len; +		} +		pair = pair->next; +		count--; +	} + +	return len; +} + +int32_t  +dict_serialize_old (dict_t *this, char *buf) +{ +	if (!this || !buf) { +		gf_log ("dict", GF_LOG_DEBUG, +			"@this=%p @buf=%p", this, buf); +		return -1; +	} + +	data_pair_t *pair = this->members_list; +	int32_t count = this->count; +	uint64_t dcount = this->count; + +	// FIXME: magic numbers + +	sprintf (buf, "%08"PRIx64"\n", dcount); +	buf += 9; +	while (count) { +		uint64_t keylen = strlen (pair->key) + 1; +		uint64_t vallen = pair->value->len; + +		sprintf (buf, "%08"PRIx64":%08"PRIx64"\n", keylen, vallen); +		buf += 18; +		memcpy (buf, pair->key, keylen); +		buf += keylen; +		memcpy (buf, pair->value->data, pair->value->len); +		buf += pair->value->len; +		pair = pair->next; +		count--; +	} +	return (0); +} + + +dict_t * +dict_unserialize_old (char *buf, int32_t size, dict_t **fill) +{ +	int32_t ret = 0; +	int32_t cnt = 0; + +	if (!buf || fill == NULL || !*fill) { +		gf_log ("dict", GF_LOG_ERROR, +			"@buf=%p @fill=%p @*fill=%p", buf, fill, *fill); +		return NULL; +	} + +	uint64_t count; +	ret = sscanf (buf, "%"SCNx64"\n", &count); +	(*fill)->count = 0; + +	if (!ret){ +		gf_log ("dict", +			GF_LOG_ERROR, +			"sscanf on buf failed"); +		goto err; +	} +	buf += 9; +   +	if (count == 0) { +		gf_log ("dict", +			GF_LOG_ERROR, +			"count == 0"); +		goto err; +	} + +	for (cnt = 0; cnt < count; cnt++) { +		data_t *value = NULL; +		char *key = NULL; +		uint64_t key_len, value_len; +     +		ret = sscanf (buf, "%"SCNx64":%"SCNx64"\n", &key_len, &value_len); +		if (ret != 2) { +			gf_log ("dict", +				GF_LOG_ERROR, +				"sscanf for key_len and value_len failed"); +			goto err; +		} +		buf += 18; + +		key = buf; +		buf += key_len; +     +		value = get_new_data (); +		value->len = value_len; +		value->data = buf; +		value->is_static = 1; +		buf += value_len; + +		dict_set (*fill, key, value); +	} + +	goto ret; + +err: +	FREE (*fill); +	*fill = NULL;  + +ret: +	return *fill; +} + + +int32_t +dict_iovec_len (dict_t *this) +{ +	if (!this) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@this=%p", this); +		return -1; +	} + +	int32_t len = 0; +	data_pair_t *pair = this->members_list; + +	len++; /* initial header */ +	while (pair) { +		len++; /* pair header */ +		len++; /* key */ + +		if (pair->value->vec) +			len += pair->value->len; +		else +			len++; +		pair = pair->next; +	} + +	return len; +} + +int32_t +dict_to_iovec (dict_t *this, +	       struct iovec *vec, +	       int32_t count) +{ +	if (!this || !vec) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@this=%p @vec=%p", this, vec); +		return -1; +	} + +	int32_t i = 0; +	data_pair_t *pair = this->members_list; + +	vec[0].iov_len = 9; +	if (vec[0].iov_base) +		sprintf (vec[0].iov_base, +			 "%08"PRIx64"\n", +			 (int64_t)this->count); +	i++; + +	while (pair) { +		int64_t keylen = strlen (pair->key) + 1; +		int64_t vallen = 0; + +		if (pair->value->vec) { +			int i; + +			for (i=0; i<pair->value->len; i++) { +				vallen += pair->value->vec[i].iov_len; +			} +		} else { +			vallen = pair->value->len; +		} + +		vec[i].iov_len = 18; +		if (vec[i].iov_base) +			sprintf (vec[i].iov_base, +				 "%08"PRIx64":%08"PRIx64"\n", +				 keylen, +				 vallen); +		i++; + +		vec[i].iov_len = keylen; +		vec[i].iov_base = pair->key; +		i++; + +		if (pair->value->vec) { +			int k; + +			for (k=0; k<pair->value->len; k++) { +				vec[i].iov_len = pair->value->vec[k].iov_len; +				vec[i].iov_base = pair->value->vec[k].iov_base; +				i++; +			} +		} else { +			vec[i].iov_len = pair->value->len; +			vec[i].iov_base = pair->value->data; +			i++; +		} + +		pair = pair->next; +	} + +	return 0; +} + +data_t * +int_to_data (int64_t value) +{ +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} + +	asprintf (&data->data, "%"PRId64, value); +	data->len = strlen (data->data) + 1; + +	return data; +} + +data_t * +data_from_int64 (int64_t value) +{ +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	asprintf (&data->data, "%"PRId64, value); +	data->len = strlen (data->data) + 1; + +	return data; +} + +data_t * +data_from_int32 (int32_t value) +{ +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	asprintf (&data->data, "%"PRId32, value); +	data->len = strlen (data->data) + 1; + +	return data; +} + +data_t * +data_from_int16 (int16_t value) +{ + +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	asprintf (&data->data, "%"PRId16, value); +	data->len = strlen (data->data) + 1; + +	return data; +} + +data_t * +data_from_int8 (int8_t value) +{ + +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	asprintf (&data->data, "%d", value); +	data->len = strlen (data->data) + 1; + +	return data; +} + +data_t * +data_from_uint64 (uint64_t value) +{ +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	asprintf (&data->data, "%"PRIu64, value); +	data->len = strlen (data->data) + 1; + +	return data; +} + + +data_t * +data_from_uint32 (uint32_t value) +{ +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	asprintf (&data->data, "%"PRIu32, value); +	data->len = strlen (data->data) + 1; + +	return data; +} + + +data_t * +data_from_uint16 (uint16_t value) +{ +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	asprintf (&data->data, "%"PRIu16, value); +	data->len = strlen (data->data) + 1; + +	return data; +} + + +data_t * +data_from_ptr (void *value) +{ +	if (!value) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@value=%p", value); +		return NULL; +	} + +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} + +	data->data = value; +	return data; +} + +data_t * +data_from_static_ptr (void *value) +{ +/* +  this is valid to set 0 as value.. + +	if (!value) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@value=%p", value); +		return NULL; +	} +*/ +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} + +	data->is_static = 1; +	data->data = value; + +	return data; +} + +data_t * +str_to_data (char *value) +{ +	if (!value) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@value=%p", value); +		return NULL; +	} +	data_t *data = get_new_data (); + +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data - NULL returned by CALLOC"); +		return NULL; +	} +	data->len = strlen (value) + 1; + +	data->data = value; +	data->is_static = 1; + +	return data; +} + +data_t * +data_from_dynstr (char *value) +{ +	if (!value) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@value=%p", value); +		return NULL; +	} + +	data_t *data = get_new_data (); + +	data->len = strlen (value) + 1; +	data->data = value; + +	return data; +} + +data_t * +data_from_dynptr (void *value, int32_t len) +{ +	data_t *data = get_new_data (); + +	data->len = len; +	data->data = value; + +	return data; +} + +data_t * +bin_to_data (void *value, int32_t len) +{ +	if (!value) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@value=%p", value); +		return NULL; +	} + +	data_t *data = get_new_data (); + +	data->is_static = 1; +	data->len = len; +	data->data = value; + +	return data; +} + +int64_t +data_to_int64 (data_t *data) +{ +	if (!data) +		return -1; + +	char *str = alloca (data->len + 1); +	ERR_ABORT (str); +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; +	return (int64_t) strtoull (str, NULL, 0); +} + +int32_t +data_to_int32 (data_t *data) +{ +	if (!data) +		return -1; + +	char *str = alloca (data->len + 1); +	ERR_ABORT (str); +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	return strtoul (str, NULL, 0); +} + +int16_t +data_to_int16 (data_t *data) +{ +	if (!data) +		return -1; + +	char *str = alloca (data->len + 1); +	ERR_ABORT (str); +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	return strtol (str, NULL, 0); +} + + +int8_t +data_to_int8 (data_t *data) +{ +	if (!data) +		return -1; + +	char *str = alloca (data->len + 1); +	ERR_ABORT (str); +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	return (int8_t)strtol (str, NULL, 0); +} + + +uint64_t +data_to_uint64 (data_t *data) +{ +	if (!data) +		return -1; +	char *str = alloca (data->len + 1); +	ERR_ABORT (str); +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	return strtoll (str, NULL, 0); +} + +uint32_t +data_to_uint32 (data_t *data) +{ +	if (!data) +		return -1; + +	char *str = alloca (data->len + 1); +	ERR_ABORT (str); +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	return strtol (str, NULL, 0); +} + +uint16_t +data_to_uint16 (data_t *data) +{ +	if (!data) +		return -1; + +	char *str = alloca (data->len + 1); +	ERR_ABORT (str); +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	return strtol (str, NULL, 0); +} + +char * +data_to_str (data_t *data) +{ +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data=%p", data); +		return NULL; +	} +	return data->data; +} + +void * +data_to_ptr (data_t *data) +{ +	if (!data) { +		return NULL; +	} +	return data->data; +} + +void * +data_to_bin (data_t *data) +{ +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data=%p", data); +		return NULL; +	} +	return data->data; +} + +void +dict_foreach (dict_t *dict, +	      void (*fn)(dict_t *this, +			 char *key, +			 data_t *value, +			 void *data), +	      void *data) +{ +	if (!data) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data=%p", data); +		return; +	} + +	data_pair_t *pairs = dict->members_list; + +	while (pairs) { +		fn (dict, pairs->key, pairs->value, data); +		pairs = pairs->next; +	} +} + + +static void +_copy (dict_t *unused, +       char *key, +       data_t *value, +       void *newdict) +{ +	dict_set ((dict_t *)newdict, key, (value)); +} + + +dict_t * +dict_copy (dict_t *dict, +	   dict_t *new) +{ +	if (!dict) { +		gf_log ("dict", GF_LOG_CRITICAL, +			"@data=%p", dict); +		return NULL; +	} + +	if (!new) +		new = get_new_dict_full (dict->hash_size); + +	dict_foreach (dict, _copy, new); + +	return new; +} + +dict_t * +dict_copy_with_ref (dict_t *dict, +		    dict_t *new) +{ +	dict_t *local_new = NULL; + +	GF_VALIDATE_OR_GOTO("dict", dict, fail); + +	if (new == NULL) { +		local_new = dict_new (); +		GF_VALIDATE_OR_GOTO("dict", local_new, fail); +		new = local_new; +	} + +	dict_foreach (dict, _copy, new); +fail: +	return new; +} + +/* + * !!!!!!! CLEANED UP CODE !!!!!!! + */ + +/** + * Common cleaned up interface: + *  + * Return value:  0   success + *               -val error, val = errno + */ + + +static int +dict_get_with_ref (dict_t *this, char *key, data_t **data) +{ +	data_pair_t * pair = NULL; +	int           ret  = -ENOENT; + +	if (!this || !key || !data) { +		ret = -EINVAL; +		goto err; +	} + +	LOCK (&this->lock); +	{ +		pair = _dict_lookup (this, key); +	} +	UNLOCK (&this->lock); + +	if (pair) { +		ret = 0; +		*data = data_ref (pair->value); +	} + +err:   +	return ret; +} + +static int +_data_to_ptr (data_t *data, void **val) +{ +	int ret = 0; + +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	*val = data->data; +err: +	return ret; +} + + +static int +_data_to_int8 (data_t *data, int8_t *val) +{ +	int    ret = 0; +	char * str = NULL; + +	if (!data || !val) { +		ret = -EINVAL; +		goto err; +	} + +	str = alloca (data->len + 1); +	if (!str) { +		ret = -ENOMEM; +		goto err; +	} +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	errno = 0; +	*val = strtol (str, NULL, 0); +	if (errno != 0) +		ret = -errno; + +err: +	return ret; +} + +static int +_data_to_int16 (data_t *data, int16_t *val) +{ +	int    ret = 0; +	char * str = NULL; + +	if (!data || !val) { +		ret = -EINVAL; +		goto err; +	} + +	str = alloca (data->len + 1); +	if (!str) { +		ret = -ENOMEM; +		goto err; +	} +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	errno = 0; +	*val = strtol (str, NULL, 0); +	if (errno != 0) +		ret = -errno; + +err: +	return ret; +} + +static int +_data_to_int32 (data_t *data, int32_t *val) +{ +	int    ret = 0; +	char * str = NULL; + +	if (!data || !val) { +		ret = -EINVAL; +		goto err; +	} + +	str = alloca (data->len + 1); +	if (!str) { +		ret = -ENOMEM; +		goto err; +	} +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	errno = 0; +	*val = strtol (str, NULL, 0); +	if (errno != 0) +		ret = -errno; + +err: +	return ret; +} + +static int +_data_to_int64 (data_t *data, int64_t *val) +{ +	int    ret = 0; +	char * str = NULL; + +	if (!data || !val) { +		ret = -EINVAL; +		goto err; +	} + +	str = alloca (data->len + 1); +	if (!str) { +		ret = -ENOMEM; +		goto err; +	} +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	errno = 0; +	*val = strtoll (str, NULL, 0); +	if (errno != 0) +		ret = -errno; + +err: +	return ret; +} + +static int +_data_to_uint16 (data_t *data, uint16_t *val) +{ +	int    ret = 0; +	char * str = NULL; + +	if (!data || !val) { +		ret = -EINVAL; +		goto err; +	} + +	str = alloca (data->len + 1); +	if (!str) { +		ret = -ENOMEM; +		goto err; +	} +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	errno = 0; +	*val = strtoul (str, NULL, 0); +	if (errno != 0) +		ret = -errno; + +err: +	return ret; +} + +static int +_data_to_uint32 (data_t *data, uint32_t *val) +{ +	int    ret = 0; +	char * str = NULL; + +	if (!data || !val) { +		ret = -EINVAL; +		goto err; +	} + +	str = alloca (data->len + 1); +	if (!str) { +		ret = -ENOMEM; +		goto err; +	} +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	errno = 0; +	*val = strtoul (str, NULL, 0); +	if (errno != 0) +		ret = -errno; + +err: +	return ret; +} + +static int +_data_to_uint64 (data_t *data, uint64_t *val) +{ +	int    ret = 0; +	char * str = NULL; + +	if (!data || !val) { +		ret = -EINVAL; +		goto err; +	} + +	str = alloca (data->len + 1); +	if (!str) { +		ret = -ENOMEM; +		goto err; +	} +	memcpy (str, data->data, data->len); +	str[data->len] = '\0'; + +	errno = 0; +	*val = strtoull (str, NULL, 0); +	if (errno != 0) +		ret = -errno; + +err: +	return ret; +} + +int +dict_get_int8 (dict_t *this, char *key, int8_t *val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !val) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_int8 (data, val); +     +err: +	if (data) +		data_unref (data); +	return ret; +} + + +int +dict_set_int8 (dict_t *this, char *key, int8_t val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_int8 (val); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_get_int16 (dict_t *this, char *key, int16_t *val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !val) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_int16 (data, val); +     +err: +	if (data) +		data_unref (data); +	return ret; +} + + +int +dict_set_int16 (dict_t *this, char *key, int16_t val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_int16 (val); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_get_int32 (dict_t *this, char *key, int32_t *val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !val) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_int32 (data, val); +     +err: +	if (data) +		data_unref (data); +	return ret; +} + + +int +dict_set_int32 (dict_t *this, char *key, int32_t val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_int32 (val); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_get_int64 (dict_t *this, char *key, int64_t *val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !val) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_int64 (data, val); +     +err: +	if (data) +		data_unref (data); +	return ret; +} + + +int +dict_set_int64 (dict_t *this, char *key, int64_t val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_int64 (val); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_get_uint16 (dict_t *this, char *key, uint16_t *val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !val) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_uint16 (data, val); +     +err: +	if (data) +		data_unref (data); +	return ret; +} + + +int +dict_set_uint16 (dict_t *this, char *key, uint16_t val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_uint16 (val); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_get_uint32 (dict_t *this, char *key, uint32_t *val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !val) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_uint32 (data, val); +     +err: +	if (data) +		data_unref (data); +	return ret; +} + + +int +dict_set_uint32 (dict_t *this, char *key, uint32_t val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_uint32 (val); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_get_uint64 (dict_t *this, char *key, uint64_t *val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !val) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_uint64 (data, val); +     +err: +	if (data) +		data_unref (data); +	return ret; +} + + +int +dict_set_uint64 (dict_t *this, char *key, uint64_t val) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_uint64 (val); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_set_static_ptr (dict_t *this, char *key, void *ptr) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_static_ptr (ptr); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_set_dynptr (dict_t *this, char *key, void *ptr, size_t len) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_dynptr (ptr, len); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_get_ptr (dict_t *this, char *key, void **ptr) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!this || !key || !ptr) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret != 0) { +		goto err; +	} + +	ret = _data_to_ptr (data, ptr); +	if (ret != 0) { +		goto err; +	} + +err:  +	if (data) +		data_unref (data); + +	return ret; +} + +int +dict_set_ptr (dict_t *this, char *key, void *ptr) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_ptr (ptr); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + + +int +dict_get_str (dict_t *this, char *key, char **str) +{ +	data_t * data = NULL; +	int      ret  = -EINVAL; + +	if (!this || !key || !str) { +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret < 0) { +		goto err; +	} + +	if (!data || !data->data) { +		goto err; +	} +	*str = data->data; + +err:  +	if (data) +		data_unref (data); + +	return ret; +} + +int +dict_set_str (dict_t *this, char *key, char *str) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = str_to_data (str); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +int +dict_set_dynstr (dict_t *this, char *key, char *str) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	data = data_from_dynstr (str); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + + +int +dict_get_bin (dict_t *this, char *key, void **bin) +{ +	data_t * data = NULL; +	int      ret  = -EINVAL; + +	if (!this || !key || !bin) { +		goto err; +	} + +	ret = dict_get_with_ref (this, key, &data); +	if (ret < 0) { +		goto err; +	} + +	if (!data || !data->data) { +		goto err; +	} +	*bin = data->data; + +err:  +	if (data) +		data_unref (data); + +	return ret; +} + + +int +dict_set_bin (dict_t *this, char *key, void *ptr, size_t size) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!ptr || (size < 0)) { +		ret = -EINVAL; +		goto err; +	} + +	data = bin_to_data (ptr, size); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	data->data = ptr; +	data->len  = size; +	data->is_static = 0; + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + + +int +dict_set_static_bin (dict_t *this, char *key, void *ptr, size_t size) +{ +	data_t * data = NULL; +	int      ret  = 0; + +	if (!ptr || (size < 0)) { +		ret = -EINVAL; +		goto err; +	} + +	data = bin_to_data (ptr, size); +	if (!data) { +		ret = -EINVAL; +		goto err; +	} + +	data->data = ptr; +	data->len  = size; +	data->is_static = 1; + +	ret = dict_set (this, key, data); + +err: +	return ret; +} + +/** + * Serialization format: + *  -------- --------  --------  ----------- ------------- + * |  count | key len | val len | key     \0| value + *  ---------------------------------------- ------------- + *     4        4         4       <key len>   <value len> + */ + +#define DICT_HDR_LEN               4 +#define DICT_DATA_HDR_KEY_LEN      4 +#define DICT_DATA_HDR_VAL_LEN      4 + +/** + * dict_serialized_length - return the length of serialized dict + * + * @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; + +	if (!this) { +		gf_log ("dict", GF_LOG_ERROR, "this is null!"); +		goto out; +	} +	 +	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: 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 (!this) { +		gf_log ("dict", GF_LOG_ERROR, +			"this is null!"); +		goto out; +	} +	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_unserialize - unserialize a buffer into a dict + * + * @buf:  buf containing serialized dict + * @size: size of the @buf + * @fill: dict to fill in + *  + * @return: success: 0 + *          failure: -errno + */ + +int32_t +dict_unserialize (char *orig_buf, int32_t size, dict_t **fill) +{ +	char   *buf = NULL; +	int     ret   = -1; +	int32_t count = 0; +	int     i     = 0; + +	data_t * value   = NULL; +	char   * key     = NULL; +	int32_t  keylen  = 0; +	int32_t  vallen  = 0; + + +	buf = orig_buf; + +	if (!buf) { +		gf_log ("dict", GF_LOG_ERROR, +			"buf is null!"); +		goto out; +	} + +	if (size == 0) { +		gf_log ("dict", GF_LOG_ERROR, +			"size is 0!"); +		goto out; +	} + +	if (!fill) { +		gf_log ("dict", GF_LOG_ERROR, +			"fill is null!"); +		goto out; +	} + +	if (!*fill) { +		gf_log ("dict", GF_LOG_ERROR, +			"*fill is null!"); +		goto out; +	} + +	if ((buf + DICT_HDR_LEN) > (orig_buf + size)) { +		gf_log ("dict", GF_LOG_ERROR, +			"undersized buffer passsed"); +		goto out; +	} + +	count = ntoh32 (*(int32_t *) buf); +	buf += DICT_HDR_LEN; + +	if (count < 0) { +		gf_log ("dict", GF_LOG_ERROR, +			"count (%d) <= 0", count); +		goto out; +	} + +	/* count will be set by the dict_set's below */ +	(*fill)->count = 0; + +	for (i = 0; i < count; i++) { +		if ((buf + DICT_DATA_HDR_KEY_LEN) > (orig_buf + size)) { +			gf_log ("dict", GF_LOG_ERROR, +				"undersized buffer passsed"); +			goto out; +		} +		keylen = ntoh32 (*(int32_t *) buf); +		buf += DICT_DATA_HDR_KEY_LEN; + +		if ((buf + DICT_DATA_HDR_VAL_LEN) > (orig_buf + size)) { +			gf_log ("dict", GF_LOG_ERROR, +				"undersized buffer passsed"); +			goto out; +		} +		vallen = ntoh32 (*(int32_t *) buf); +		buf += DICT_DATA_HDR_VAL_LEN; + +		if ((buf + keylen) > (orig_buf + size)) { +			gf_log ("dict", GF_LOG_ERROR, +				"undersized buffer passsed"); +			goto out; +		} +		key = buf; +		buf += keylen + 1;  /* for '\0' */ + +		if ((buf + vallen) > (orig_buf + size)) { +			gf_log ("dict", GF_LOG_ERROR, +				"undersized buffer passsed"); +			goto out; +		} +		value = get_new_data (); +		value->len  = vallen; +		value->data = buf; +		value->is_static = 1; +		buf += vallen; + +		dict_set (*fill, key, value); +	} + +	ret = 0; +out: +	return ret; +} +  | 
