Re: [PATCH 01/14] Add icmap

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Reviewed-by: Steven Dake <sdake@xxxxxxxxxx>

Regards
-steve

On 12/14/2011 08:41 AM, Jan Friesse wrote:
> Icmap is replacement for objdb, based on libqb map (trie).
> 
> Signed-off-by: Jan Friesse <jfriesse@xxxxxxxxxx>
> ---
>  exec/Makefile.am                |   28 +-
>  exec/icmap.c                    |  892 +++++++++++++++++++++++++++++++++++++++
>  include/Makefile.am             |    2 +-
>  include/corosync/engine/icmap.h |  262 ++++++++++++
>  4 files changed, 1179 insertions(+), 5 deletions(-)
>  create mode 100644 exec/icmap.c
>  create mode 100644 include/corosync/engine/icmap.h
> 
> diff --git a/exec/Makefile.am b/exec/Makefile.am
> index 8514afa..2cc368e 100644
> --- a/exec/Makefile.am
> +++ b/exec/Makefile.am
> @@ -43,25 +43,28 @@ TOTEM_SRC		+= totemiba.c
>  endif
>  
>  LOGSYS_SRC		= logsys.c
> +ICMAP_SRC		= icmap.c
>  LCRSO_SRC		= objdb.c vsf_ykd.c coroparse.c vsf_quorum.c
>  LCRSO_OBJS		= $(LCRSO_SRC:%.c=%.o)
>  LCRSO			= $(LCRSO_SRC:%.c=%.lcrso)
>  
> -lib_LIBRARIES		= libtotem_pg.a liblogsys.a
> +lib_LIBRARIES		= libtotem_pg.a liblogsys.a libicmap.a
>  sbin_PROGRAMS		= corosync
>  
>  libtotem_pg_a_SOURCES	= $(TOTEM_SRC)
>  liblogsys_a_SOURCES	= $(LOGSYS_SRC)
> +libicmap_a_SOURCES	= $(ICMAP_SRC)
>  
>  corosync_SOURCES 	= main.c ipc_glue.c util.c sync.c apidef.c service.c \
>  			  timer.c totemconfig.c mainconfig.c quorum.c schedwrk.c \
>  			  ../lcr/lcr_ifact.c evil.c syncv2.c
> -corosync_LDADD	  	= -ltotem_pg -llogsys $(LIBQB_LIBS) $(statgrab_LIBS)
> -corosync_DEPENDENCIES	= libtotem_pg.so.$(SONAME) liblogsys.so.$(SONAME)
> +corosync_LDADD	  	= -ltotem_pg -llogsys -licmap $(LIBQB_LIBS) $(statgrab_LIBS)
> +corosync_DEPENDENCIES	= libtotem_pg.so.$(SONAME) liblogsys.so.$(SONAME) libicmap.so.$(SONAME)
>  corosync_LDFLAGS	= $(OS_DYFLAGS) -L./
>  
>  TOTEM_OBJS		= $(TOTEM_SRC:%.c=%.o)
>  LOGSYS_OBJS		= $(LOGSYS_SRC:%.c=%.o)
> +ICMAP_OBJS		= $(ICMAP_SRC:%.c=%.o)
>  
>  SHARED_LIBS		= $(lib_LIBRARIES:%.a=%.so.$(SONAME))
>  SHARED_LIBS_SO		= $(SHARED_LIBS:%.so.$(SONAME)=%.so)
> @@ -77,7 +80,7 @@ EXTRA_DIST		= $(LCRSO_SRC)
>  
>  if BUILD_DARWIN
>  %.lcrso: %.o
> -	$(CC) $(LDFLAGS) $(CFLAGS) -L$(top_builddir)/exec -llogsys -bundle -bind_at_load -bundle_loader ./corosync $^ -o $@
> +	$(CC) $(LDFLAGS) $(CFLAGS) -L$(top_builddir)/exec -llogsys -licmap -bundle -bind_at_load -bundle_loader ./corosync $^ -o $@
>  
>  libtotem_pg.so.$(SONAME): $(TOTEM_OBJS)
>  	$(CC) $(LDFLAGS) $(DARWIN_OPTS) $(TOTEM_OBJS) -o $@ -lpthread
> @@ -89,6 +92,11 @@ liblogsys.so.$(SONAME): $(LOGSYS_OBJS)
>  	ln -sf liblogsys.so.$(SONAME) liblogsys.so
>  	ln -sf liblogsys.so.$(SONAME) liblogsys.so.$(SOMAJOR)
>  
> +libicmap.so.$(SONAME): $(ICMAP_OBJS)
> +	$(CC) $(LDFLAGS) $(DARWIN_OPTS) $(ICMAP_OBJS) -o $@ -lpthread
> +	ln -sf libicmap.so.$(SONAME) libicmap.so
> +	ln -sf libicmap.so.$(SONAME) libicmap.so.$(SOMAJOR)
> +
>  else
>  
>  if BUILD_SOLARIS
> @@ -105,6 +113,11 @@ liblogsys.so.$(SONAME): $(LOGSYS_OBJS)
>  	ln -sf liblogsys.so.$(SONAME) liblogsys.so
>  	ln -sf liblogsys.so.$(SONAME) liblogsys.so.$(SOMAJOR)
>  
> +libicmap.so.$(SONAME): $(ICMAP_OBJS)
> +	$(LD) $(LDFLAGS) -G $(ICMAP_OBJS) -o $@ -lpthread
> +	ln -sf libicmap.so.$(SONAME) libicmap.so
> +	ln -sf libicmap.so.$(SONAME) libicmap.so.$(SOMAJOR)
> +
>  else
>  
>  %.lcrso: %.o
> @@ -124,6 +137,13 @@ liblogsys.so.$(SONAME): $(LOGSYS_OBJS)
>  	ln -sf liblogsys.so.$(SONAME) liblogsys.so
>  	ln -sf liblogsys.so.$(SONAME) liblogsys.so.$(SOMAJOR)
>  
> +libicmap.so.$(SONAME): $(ICMAP_OBJS)
> +	$(CC) -shared -o $@ \
> +		-Wl,-soname=libicmap.so.$(SOMAJOR) \
> +		$(LDFLAGS) $^ -lpthread
> +	ln -sf libicmap.so.$(SONAME) libicmap.so
> +	ln -sf libicmap.so.$(SONAME) libicmap.so.$(SOMAJOR)
> +
>  endif
>  
>  endif
> diff --git a/exec/icmap.c b/exec/icmap.c
> new file mode 100644
> index 0000000..14390d4
> --- /dev/null
> +++ b/exec/icmap.c
> @@ -0,0 +1,892 @@
> +/*
> + * Copyright (c) 2011 Red Hat, Inc.
> + *
> + * All rights reserved.
> + *
> + * Author: Jan Friesse (jfriesse@xxxxxxxxxx)
> + *
> + * This software licensed under BSD license, the text of which follows:
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *
> + * - Redistributions of source code must retain the above copyright notice,
> + *   this list of conditions and the following disclaimer.
> + * - Redistributions in binary form must reproduce the above copyright notice,
> + *   this list of conditions and the following disclaimer in the documentation
> + *   and/or other materials provided with the distribution.
> + * - Neither the name of the Red Hat, Inc. nor the names of its
> + *   contributors may be used to endorse or promote products derived from this
> + *   software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> + * THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <config.h>
> +
> +#include <string.h>
> +#include <stdio.h>
> +
> +#include <corosync/corotypes.h>
> +
> +#include <qb/qbdefs.h>
> +#include <corosync/list.h>
> +#include <corosync/engine/icmap.h>
> +
> +#define ICMAP_MAX_VALUE_LEN	(16*1024)
> +
> +struct icmap_item {
> +	char *key_name;
> +	icmap_value_types_t type;
> +	size_t value_len;
> +	char value[];
> +};
> +
> +static qb_map_t *icmap_map;
> +
> +struct icmap_track {
> +	char *key_name;
> +	int32_t track_type;
> +	icmap_notify_fn_t notify_fn;
> +	void *user_data;
> +};
> +
> +struct icmap_ro_access_item {
> +	char *key_name;
> +	int prefix;
> +	struct list_head list;
> +};
> +
> +DECLARE_LIST_INIT(icmap_ro_access_item_list_head);
> +
> +/*
> + * Static functions declarations
> + */
> +
> +/*
> + * Check if key_name is valid icmap key name. Returns 0 on success, and -1 on fail
> + */
> +static int icmap_check_key_name(const char *key_name);
> +
> +/*
> + * Check that value with given type has correct length value_len. Returns 0 on success,
> + * and -1 on fail
> + */
> +static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type);
> +
> +/*
> + * Returns length of value of given type, or 0 for string and binary data type
> + */
> +static size_t icmap_get_valuetype_len(icmap_value_types_t type);
> +
> +/*
> + * Converts track type of icmap to qb
> + */
> +static int32_t icmap_tt_to_qbtt(int32_t track_type);
> +
> +/*
> + * Convert track type of qb to icmap
> + */
> +static int32_t icmap_qbtt_to_tt(int32_t track_type);
> +
> +/*
> + * Checks if item has same value as value with value_len and given type. Returns 0 if not, otherwise !0.
> + */
> +static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type);
> +
> +/*
> + * Checks if given character is valid in key name. Returns 0 if not, otherwise !0.
> + */
> +static int icmap_is_valid_name_char(char c);
> +
> +/*
> + * Helper for getting integer and float value with given type for key key_name and store it in value.
> + */
> +static cs_error_t icmap_get_int(
> +	const char *key_name,
> +	void *value,
> +	icmap_value_types_t type);
> +
> +/*
> + * Function implementation
> + */
> +static int32_t icmap_tt_to_qbtt(int32_t track_type)
> +{
> +	int32_t res = 0;
> +
> +	if (track_type & ICMAP_TRACK_DELETE) {
> +		res |= QB_MAP_NOTIFY_DELETED;
> +	}
> +
> +	if (track_type & ICMAP_TRACK_MODIFY) {
> +		res |= QB_MAP_NOTIFY_REPLACED;
> +	}
> +
> +	if (track_type & ICMAP_TRACK_ADD) {
> +		res |= QB_MAP_NOTIFY_INSERTED;
> +	}
> +
> +	if (track_type & ICMAP_TRACK_PREFIX) {
> +		res |= QB_MAP_NOTIFY_RECURSIVE;
> +	}
> +
> +	return (track_type);
> +}
> +
> +static int32_t icmap_qbtt_to_tt(int32_t track_type)
> +{
> +	int32_t res = 0;
> +
> +	if (track_type & QB_MAP_NOTIFY_DELETED) {
> +		res |= ICMAP_TRACK_DELETE;
> +	}
> +
> +	if (track_type & QB_MAP_NOTIFY_REPLACED) {
> +		res |= ICMAP_TRACK_MODIFY;
> +	}
> +
> +	if (track_type & QB_MAP_NOTIFY_INSERTED) {
> +		res |= ICMAP_TRACK_ADD;
> +	}
> +
> +	if (track_type & QB_MAP_NOTIFY_RECURSIVE) {
> +		res |= ICMAP_TRACK_PREFIX;
> +	}
> +
> +	return (track_type);
> +}
> +
> +static void icmap_map_free_cb(uint32_t event,
> +		char* key, void* old_value,
> +		void* value, void* user_data)
> +{
> +	struct icmap_item *item = (struct icmap_item *)old_value;
> +
> +	if (item != NULL) {
> +		free(item->key_name);
> +		free(item);
> +	}
> +}
> +
> +cs_error_t icmap_init(void)
> +{
> +	int32_t err;
> +
> +	icmap_map = qb_trie_create();
> +	if (icmap_map == NULL)
> +		return (CS_ERR_INIT);
> +
> +	err = qb_map_notify_add(icmap_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
> +
> +	return (qb_to_cs_error(err));
> +}
> +
> +static int icmap_is_valid_name_char(char c)
> +{
> +	return ((c >= 'a' && c <= 'z') ||
> +		(c >= 'A' && c <= 'Z') ||
> +		(c >= '0' && c <= '9') ||
> +		c == '.' || c == '_' || c == '-' || c == '/' || c == ':');
> +}
> +
> +void icmap_convert_name_to_valid_name(char *key_name)
> +{
> +	int i;
> +
> +	for (i = 0; i < strlen(key_name); i++) {
> +		if (!icmap_is_valid_name_char(key_name[i])) {
> +			key_name[i] = '_';
> +		}
> +	}
> +}
> +
> +static int icmap_check_key_name(const char *key_name)
> +{
> +	int i;
> +
> +	if ((strlen(key_name) < ICMAP_KEYNAME_MINLEN) || strlen(key_name) > ICMAP_KEYNAME_MAXLEN) {
> +		return (-1);
> +	}
> +
> +	for (i = 0; i < strlen(key_name); i++) {
> +		if (!icmap_is_valid_name_char(key_name[i])) {
> +			return (-1);
> +		}
> +	}
> +
> +	return (0);
> +}
> +
> +static size_t icmap_get_valuetype_len(icmap_value_types_t type)
> +{
> +	size_t res;
> +
> +	switch (type) {
> +	case ICMAP_VALUETYPE_INT8: res = sizeof(int8_t); break;
> +	case ICMAP_VALUETYPE_UINT8: res = sizeof(uint8_t); break;
> +	case ICMAP_VALUETYPE_INT16: res = sizeof(int16_t); break;
> +	case ICMAP_VALUETYPE_UINT16: res = sizeof(uint16_t); break;
> +	case ICMAP_VALUETYPE_INT32: res = sizeof(int32_t); break;
> +	case ICMAP_VALUETYPE_UINT32: res = sizeof(uint32_t); break;
> +	case ICMAP_VALUETYPE_INT64: res = sizeof(int64_t); break;
> +	case ICMAP_VALUETYPE_UINT64: res = sizeof(uint64_t); break;
> +	case ICMAP_VALUETYPE_FLOAT: res = sizeof(float); break;
> +	case ICMAP_VALUETYPE_DOUBLE: res = sizeof(double); break;
> +	case ICMAP_VALUETYPE_STRING:
> +	case ICMAP_VALUETYPE_BINARY:
> +		res = 0;
> +		break;
> +	}
> +
> +	return (res);
> +}
> +
> +static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type)
> +{
> +
> +	if (value_len > ICMAP_MAX_VALUE_LEN) {
> +		return (-1);
> +	}
> +
> +	if (type != ICMAP_VALUETYPE_STRING && type != ICMAP_VALUETYPE_BINARY) {
> +		if (icmap_get_valuetype_len(type) == value_len) {
> +			return (0);
> +		} else {
> +			return (-1);
> +		}
> +	}
> +
> +	if (type == ICMAP_VALUETYPE_STRING) {
> +		if (value_len > strlen((const char *)value)) {
> +			return (-1);
> +		} else {
> +			return (0);
> +		}
> +	}
> +
> +	return (0);
> +}
> +
> +static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type)
> +{
> +	size_t ptr_len;
> +
> +	if (item->type != type) {
> +		return (0);
> +	}
> +
> +	if (item->type == ICMAP_VALUETYPE_STRING) {
> +		ptr_len = strlen((const char *)value);
> +		if (ptr_len > value_len) {
> +			ptr_len = value_len;
> +		}
> +		ptr_len++;
> +	} else {
> +		ptr_len = value_len;
> +	}
> +
> +	if (item->value_len == ptr_len) {
> +		return (memcmp(item->value, value, value_len) == 0);
> +	};
> +
> +	return (0);
> +}
> +
> +cs_error_t icmap_set(
> +	const char *key_name,
> +	const void *value,
> +	size_t value_len,
> +	icmap_value_types_t type)
> +{
> +	struct icmap_item *item;
> +	struct icmap_item *new_item;
> +	size_t new_value_len;
> +	size_t new_item_size;
> +
> +	if (value == NULL || key_name == NULL) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	if (icmap_check_value_len(value, value_len, type) != 0) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	item = qb_map_get(icmap_map, key_name);
> +	if (item != NULL) {
> +		/*
> +		 * Check that key is really changed
> +		 */
> +		if (icmap_item_eq(item, value, value_len, type)) {
> +			return (CS_OK);
> +		}
> +	} else {
> +		if (icmap_check_key_name(key_name) != 0) {
> +			return (CS_ERR_NAME_TOO_LONG);
> +		}
> +	}
> +
> +	if (type == ICMAP_VALUETYPE_BINARY || type == ICMAP_VALUETYPE_STRING) {
> +		if (type == ICMAP_VALUETYPE_STRING) {
> +			new_value_len = strlen((const char *)value);
> +			if (new_value_len > value_len) {
> +				new_value_len = value_len;
> +			}
> +			new_value_len++;
> +		} else {
> +			new_value_len = value_len;
> +		}
> +	} else {
> +		new_value_len = icmap_get_valuetype_len(type);
> +	}
> +
> +	new_item_size = sizeof(struct icmap_item) + new_value_len;
> +	new_item = malloc(new_item_size);
> +	if (new_item == NULL) {
> +		return (CS_ERR_NO_MEMORY);
> +	}
> +	memset(new_item, 0, new_item_size);
> +
> +	if (item == NULL) {
> +		new_item->key_name = strdup(key_name);
> +		if (new_item->key_name == NULL) {
> +			free(new_item);
> +			return (CS_ERR_NO_MEMORY);
> +		}
> +	} else {
> +		new_item->key_name = item->key_name;
> +		item->key_name = NULL;
> +	}
> +
> +	new_item->type = type;
> +	new_item->value_len = new_value_len;
> +
> +	memcpy(new_item->value, value, new_value_len);
> +
> +	if (new_item->type == ICMAP_VALUETYPE_STRING) {
> +		((char *)new_item->value)[new_value_len - 1] = 0;
> +	}
> +
> +	qb_map_put(icmap_map, new_item->key_name, new_item);
> +
> +	return (CS_OK);
> +}
> +
> +cs_error_t icmap_set_int8(const char *key_name, int8_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT8));
> +}
> +
> +cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT8));
> +}
> +
> +cs_error_t icmap_set_int16(const char *key_name, int16_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT16));
> +}
> +
> +cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT16));
> +}
> +
> +cs_error_t icmap_set_int32(const char *key_name, int32_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT32));
> +}
> +
> +cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT32));
> +}
> +
> +cs_error_t icmap_set_int64(const char *key_name, int64_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT64));
> +}
> +
> +cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT64));
> +}
> +
> +cs_error_t icmap_set_float(const char *key_name, float value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_FLOAT));
> +}
> +
> +cs_error_t icmap_set_double(const char *key_name, double value)
> +{
> +
> +	return (icmap_set(key_name, &value, sizeof(value), ICMAP_VALUETYPE_DOUBLE));
> +}
> +
> +cs_error_t icmap_set_string(const char *key_name, const char *value)
> +{
> +
> +	return (icmap_set(key_name, value, strlen(value), ICMAP_VALUETYPE_STRING));
> +}
> +
> +cs_error_t icmap_delete(const char *key_name)
> +{
> +	struct icmap_item *item;
> +
> +	if (key_name == NULL) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	item = qb_map_get(icmap_map, key_name);
> +	if (item == NULL) {
> +		return (CS_ERR_NOT_EXIST);
> +	}
> +
> +	if (qb_map_rm(icmap_map, item->key_name) != QB_TRUE) {
> +		return (CS_ERR_NOT_EXIST);
> +	}
> +
> +	return (CS_OK);
> +}
> +
> +cs_error_t icmap_get(
> +	const char *key_name,
> +	void *value,
> +	size_t *value_len,
> +	icmap_value_types_t *type)
> +{
> +	struct icmap_item *item;
> +
> +	if (key_name == NULL) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	item = qb_map_get(icmap_map, key_name);
> +	if (item == NULL) {
> +		return (CS_ERR_NOT_EXIST);
> +	}
> +
> +	if (type != NULL) {
> +		*type = item->type;
> +	}
> +
> +	if (value == NULL) {
> +		if (value_len != NULL) {
> +			*value_len = item->value_len;
> +		}
> +	} else {
> +		if (value_len == NULL || *value_len < item->value_len) {
> +			return (CS_ERR_INVALID_PARAM);
> +		}
> +
> +		*value_len = item->value_len;
> +
> +		memcpy(value, item->value, item->value_len);
> +	}
> +
> +	return (CS_OK);
> +}
> +
> +static cs_error_t icmap_get_int(
> +	const char *key_name,
> +	void *value,
> +	icmap_value_types_t type)
> +{
> +	char key_value[16];
> +	size_t key_size;
> +	cs_error_t err;
> +	icmap_value_types_t key_type;
> +
> +	key_size = sizeof(key_value);
> +	memset(key_value, 0, key_size);
> +
> +	err = icmap_get(key_name, key_value, &key_size, &key_type);
> +	if (err != CS_OK)
> +		return (err);
> +
> +	if (key_type != type) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	memcpy(value, key_value, icmap_get_valuetype_len(key_type));
> +
> +	return (CS_OK);
> +}
> +
> +cs_error_t icmap_get_int8(const char *key_name, int8_t *i8)
> +{
> +
> +	return (icmap_get_int(key_name, i8, ICMAP_VALUETYPE_INT8));
> +}
> +
> +cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
> +{
> +
> +	return (icmap_get_int(key_name, u8, ICMAP_VALUETYPE_UINT8));
> +}
> +
> +cs_error_t icmap_get_int16(const char *key_name, int16_t *i16)
> +{
> +
> +	return (icmap_get_int(key_name, i16, ICMAP_VALUETYPE_INT16));
> +}
> +
> +cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
> +{
> +
> +	return (icmap_get_int(key_name, u16, ICMAP_VALUETYPE_UINT16));
> +}
> +
> +cs_error_t icmap_get_int32(const char *key_name, int32_t *i32)
> +{
> +
> +	return (icmap_get_int(key_name, i32, ICMAP_VALUETYPE_INT32));
> +}
> +
> +cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
> +{
> +
> +	return (icmap_get_int(key_name, u32, ICMAP_VALUETYPE_UINT32));
> +}
> +
> +cs_error_t icmap_get_int64(const char *key_name, int64_t *i64)
> +{
> +
> +	return(icmap_get_int(key_name, i64, ICMAP_VALUETYPE_INT64));
> +}
> +
> +cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
> +{
> +
> +	return (icmap_get_int(key_name, u64, ICMAP_VALUETYPE_UINT64));
> +}
> +
> +cs_error_t icmap_get_float(const char *key_name, float *flt)
> +{
> +
> +	return (icmap_get_int(key_name, flt, ICMAP_VALUETYPE_FLOAT));
> +}
> +
> +cs_error_t icmap_get_double(const char *key_name, double *dbl)
> +{
> +
> +	return (icmap_get_int(key_name, dbl, ICMAP_VALUETYPE_DOUBLE));
> +}
> +
> +cs_error_t icmap_get_string(const char *key_name, char **str)
> +{
> +	cs_error_t res;
> +	size_t str_len;
> +	icmap_value_types_t type;
> +
> +	res = icmap_get(key_name, NULL, &str_len, &type);
> +	if (res != CS_OK || type != ICMAP_VALUETYPE_STRING) {
> +		if (res == CS_OK) {
> +			res = CS_ERR_INVALID_PARAM;
> +		}
> +
> +		goto return_error;
> +	}
> +
> +	*str = malloc(str_len);
> +	if (*str == NULL) {
> +		res = CS_ERR_NO_MEMORY;
> +
> +		goto return_error;
> +	}
> +
> +	res = icmap_get(key_name, *str, &str_len, &type);
> +	if (res != CS_OK) {
> +		free(*str);
> +		goto return_error;
> +	}
> +
> +	return (CS_OK);
> +
> +return_error:
> +	return (res);
> +}
> +
> +cs_error_t icmap_adjust_int(
> +	const char *key_name,
> +	int32_t step)
> +{
> +	struct icmap_item *item;
> +	uint8_t u8;
> +	uint16_t u16;
> +	uint32_t u32;
> +	uint64_t u64;
> +	cs_error_t err = CS_OK;
> +
> +	if (key_name == NULL) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	item = qb_map_get(icmap_map, key_name);
> +	if (item == NULL) {
> +		return (CS_ERR_NOT_EXIST);
> +	}
> +
> +	switch (item->type) {
> +	case ICMAP_VALUETYPE_INT8:
> +	case ICMAP_VALUETYPE_UINT8:
> +		memcpy(&u8, item->value, sizeof(u8));
> +		u8 += step;
> +		err = icmap_set(key_name, &u8, sizeof(u8), item->type);
> +		break;
> +	case ICMAP_VALUETYPE_INT16:
> +	case ICMAP_VALUETYPE_UINT16:
> +		memcpy(&u16, item->value, sizeof(u16));
> +		u16 += step;
> +		err = icmap_set(key_name, &u16, sizeof(u16), item->type);
> +		break;
> +	case ICMAP_VALUETYPE_INT32:
> +	case ICMAP_VALUETYPE_UINT32:
> +		memcpy(&u32, item->value, sizeof(u32));
> +		u32 += step;
> +		err = icmap_set(key_name, &u32, sizeof(u32), item->type);
> +		break;
> +	case ICMAP_VALUETYPE_INT64:
> +	case ICMAP_VALUETYPE_UINT64:
> +		memcpy(&u64, item->value, sizeof(u64));
> +		u64 += step;
> +		err = icmap_set(key_name, &u64, sizeof(u64), item->type);
> +		break;
> +	case ICMAP_VALUETYPE_FLOAT:
> +	case ICMAP_VALUETYPE_DOUBLE:
> +	case ICMAP_VALUETYPE_STRING:
> +	case ICMAP_VALUETYPE_BINARY:
> +		err = CS_ERR_INVALID_PARAM;
> +		break;
> +	}
> +
> +	return (err);
> +}
> +
> +cs_error_t icmap_inc(const char *key_name)
> +{
> +	return (icmap_adjust_int(key_name, 1));
> +}
> +
> +cs_error_t icmap_dec(const char *key_name)
> +{
> +	return (icmap_adjust_int(key_name, -1));
> +}
> +
> +icmap_iter_t icmap_iter_init(const char *prefix)
> +{
> +	return (qb_map_pref_iter_create(icmap_map, prefix));
> +}
> +
> +const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
> +{
> +	struct icmap_item *item;
> +	const char *res;
> +
> +	res = qb_map_iter_next(iter, (void **)&item);
> +	if (res == NULL) {
> +		return (res);
> +	}
> +
> +	if (value_len != NULL) {
> +		*value_len = item->value_len;
> +	}
> +
> +	if (type != NULL) {
> +		*type = item->type;
> +	}
> +
> +	return (res);
> +}
> +
> +void icmap_iter_finalize(icmap_iter_t iter)
> +{
> +	qb_map_iter_free(iter);
> +}
> +
> +static void icmap_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
> +{
> +	icmap_track_t icmap_track = (icmap_track_t)user_data;
> +	struct icmap_item *new_item = (struct icmap_item *)value;
> +	struct icmap_item *old_item = (struct icmap_item *)old_value;
> +	struct icmap_notify_value new_val;
> +	struct icmap_notify_value old_val;
> +
> +	if (value == NULL && old_value == NULL) {
> +		return ;
> +	}
> +
> +	if (new_item != NULL) {
> +		new_val.type = new_item->type;
> +		new_val.len = new_item->value_len;
> +		new_val.data = new_item->value;
> +	} else {
> +		memset(&new_val, 0, sizeof(new_val));
> +	}
> +
> +	if (old_item != NULL) {
> +		old_val.type = old_item->type;
> +		old_val.len = old_item->value_len;
> +		old_val.data = old_item->value;
> +	} else {
> +		memset(&old_val, 0, sizeof(old_val));
> +	}
> +
> +	icmap_track->notify_fn(icmap_qbtt_to_tt(event),
> +			key,
> +			new_val,
> +			old_val,
> +			icmap_track->user_data);
> +}
> +
> +cs_error_t icmap_track_add(
> +	const char *key_name,
> +	int32_t track_type,
> +	icmap_notify_fn_t notify_fn,
> +	void *user_data,
> +	icmap_track_t *icmap_track)
> +{
> +	int32_t err;
> +
> +	if (notify_fn == NULL || icmap_track == NULL) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	if ((track_type & ~(ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX)) != 0) {
> +		return (CS_ERR_INVALID_PARAM);
> +	}
> +
> +	*icmap_track = malloc(sizeof(**icmap_track));
> +	if (*icmap_track == NULL) {
> +		return (CS_ERR_NO_MEMORY);
> +	}
> +	memset(*icmap_track, 0, sizeof(**icmap_track));
> +
> +	if (key_name != NULL) {
> +		(*icmap_track)->key_name = strdup(key_name);
> +	};
> +
> +	(*icmap_track)->track_type = track_type;
> +	(*icmap_track)->notify_fn = notify_fn;
> +	(*icmap_track)->user_data = user_data;
> +
> +	if ((err = qb_map_notify_add(icmap_map, (*icmap_track)->key_name, icmap_notify_fn,
> +					icmap_tt_to_qbtt(track_type), *icmap_track)) != 0) {
> +		free((*icmap_track)->key_name);
> +		free(*icmap_track);
> +
> +		return (qb_to_cs_error(err));
> +	}
> +
> +	return (CS_OK);
> +}
> +
> +cs_error_t icmap_track_delete(icmap_track_t icmap_track)
> +{
> +	int32_t err;
> +
> +	if ((err = qb_map_notify_del_2(icmap_map, icmap_track->key_name,
> +				icmap_notify_fn, icmap_tt_to_qbtt(icmap_track->track_type), icmap_track)) != 0) {
> +		return (qb_to_cs_error(err));
> +	}
> +
> +	free(icmap_track->key_name);
> +	free(icmap_track);
> +
> +	return (CS_OK);
> +}
> +
> +void *icmap_track_get_user_data(icmap_track_t icmap_track)
> +{
> +	return (icmap_track->user_data);
> +}
> +
> +cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
> +{
> +	struct list_head *iter;
> +	struct icmap_ro_access_item *icmap_ro_ai;
> +
> +	for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
> +		icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
> +
> +		if (icmap_ro_ai->prefix == prefix && strcmp(key_name, icmap_ro_ai->key_name) == 0) {
> +			/*
> +			 * We found item
> +			 */
> +			if (ro_access) {
> +				return (CS_ERR_EXIST);
> +			} else {
> +				list_del(&icmap_ro_ai->list);
> +				free(icmap_ro_ai);
> +
> +				return (CS_OK);
> +			}
> +		}
> +	}
> +
> +	if (!ro_access) {
> +		return (CS_ERR_NOT_EXIST);
> +	}
> +
> +	icmap_ro_ai = malloc(sizeof(*icmap_ro_ai));
> +	if (icmap_ro_ai == NULL) {
> +		return (CS_ERR_NO_MEMORY);
> +	}
> +
> +	memset(icmap_ro_ai, 0, sizeof(*icmap_ro_ai));
> +	icmap_ro_ai->key_name = strdup(key_name);
> +	if (icmap_ro_ai->key_name == NULL) {
> +		free(icmap_ro_ai);
> +		return (CS_ERR_NO_MEMORY);
> +	}
> +
> +	icmap_ro_ai->prefix = prefix;
> +	list_init(&icmap_ro_ai->list);
> +	list_add (&icmap_ro_ai->list, &icmap_ro_access_item_list_head);
> +
> +	return (CS_OK);
> +}
> +
> +int icmap_is_key_ro(const char *key_name)
> +{
> +	struct list_head *iter;
> +	struct icmap_ro_access_item *icmap_ro_ai;
> +
> +	for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
> +		icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
> +
> +		if (icmap_ro_ai->prefix) {
> +			if (strlen(icmap_ro_ai->key_name) > strlen(key_name))
> +				continue;
> +
> +			if (strncmp(icmap_ro_ai->key_name, key_name, strlen(icmap_ro_ai->key_name)) == 0) {
> +				return (CS_TRUE);
> +			}
> +		} else {
> +			if (strcmp(icmap_ro_ai->key_name, key_name) == 0) {
> +				return (CS_TRUE);
> +			}
> +		}
> +	}
> +
> +	return (CS_FALSE);
> +
> +}
> diff --git a/include/Makefile.am b/include/Makefile.am
> index e040385..ca346f4 100644
> --- a/include/Makefile.am
> +++ b/include/Makefile.am
> @@ -40,7 +40,7 @@ CS_INTERNAL_H		= ipc_cfg.h ipc_confdb.h ipc_cpg.h ipc_evs.h ipc_pload.h ipc_quor
>  
>  LCR_H			= lcr_ckpt.h lcr_comp.h	lcr_ifact.h
>  
> -ENGINE_H		= config.h coroapi.h logsys.h objdb.h quorum.h
> +ENGINE_H		= config.h coroapi.h logsys.h objdb.h quorum.h icmap.h
>  
>  TOTEM_H			= totem.h totemip.h totempg.h
>  
> diff --git a/include/corosync/engine/icmap.h b/include/corosync/engine/icmap.h
> new file mode 100644
> index 0000000..896800b
> --- /dev/null
> +++ b/include/corosync/engine/icmap.h
> @@ -0,0 +1,262 @@
> +/*
> + * Copyright (c) 2011 Red Hat, Inc.
> + *
> + * Author: Jan Friesse (jfriesse@xxxxxxxxxx)
> + *
> + * All rights reserved.
> + *
> + * This software licensed under BSD license, the text of which follows:
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *
> + * - Redistributions of source code must retain the above copyright notice,
> + *   this list of conditions and the following disclaimer.
> + * - Redistributions in binary form must reproduce the above copyright notice,
> + *   this list of conditions and the following disclaimer in the documentation
> + *   and/or other materials provided with the distribution.
> + * - Neither the name of the Red Hat, Inc. nor the names of its
> + *   contributors may be used to endorse or promote products derived from this
> + *   software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> + * THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#ifndef ICMAP_H_DEFINED
> +#define ICMAP_H_DEFINED
> +
> +#include <stdlib.h>
> +#include <corosync/corotypes.h>
> +#include <qb/qbmap.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/*
> + * Maximum length of key in icmap
> + */
> +#define ICMAP_KEYNAME_MAXLEN		255
> +
> +/*
> + * Minimum lenght of key in icmap
> + */
> +#define ICMAP_KEYNAME_MINLEN		3
> +
> +/*
> + * Possible types of value. Binary is raw data without trailing zero with given length
> + */
> +typedef enum {
> +    ICMAP_VALUETYPE_INT8	=  1,
> +    ICMAP_VALUETYPE_UINT8	=  2,
> +    ICMAP_VALUETYPE_INT16	=  3,
> +    ICMAP_VALUETYPE_UINT16	=  4,
> +    ICMAP_VALUETYPE_INT32	=  5,
> +    ICMAP_VALUETYPE_UINT32	=  6,
> +    ICMAP_VALUETYPE_INT64	=  7,
> +    ICMAP_VALUETYPE_UINT64	=  8,
> +    ICMAP_VALUETYPE_FLOAT	=  9,
> +    ICMAP_VALUETYPE_DOUBLE	= 10,
> +    ICMAP_VALUETYPE_STRING	= 11,
> +    ICMAP_VALUETYPE_BINARY	= 12,
> +} icmap_value_types_t;
> +
> +/*
> + * Tracking values.
> + */
> +#define ICMAP_TRACK_ADD		4
> +#define ICMAP_TRACK_DELETE	1
> +#define ICMAP_TRACK_MODIFY	2
> +/*
> + * Whole prefix is tracked, instead of key only (so "totem." tracking means that
> + * "totem.nodeid", "totem.version", ... applies). This value is also never returned
> + * inside of callback and is used only in adding track
> + */
> +#define ICMAP_TRACK_PREFIX	8
> +
> +/*
> + * Structure passed as new_value and old_value in change callback. It contains type of
> + * key, length of key and pointer to value of key
> + */
> +struct icmap_notify_value {
> +	icmap_value_types_t type;
> +	size_t len;
> +	const void *data;
> +};
> +
> +/*
> + * Prototype for notify callback function. Even is one of ICMAP_TRACK_* event, key_name is
> + * changed key, new and old_value contains values or are zeroed (in other words, type is non
> + * existing 0 type) if there were no old (creating of key) or new (deleting of key) value.
> + * user_data are passed when adding tracking.
> + */
> +typedef void (*icmap_notify_fn_t) (
> +	int32_t event,
> +	const char *key_name,
> +	struct icmap_notify_value new_value,
> +	struct icmap_notify_value old_value,
> +	void *user_data);
> +
> +/*
> + * Itterator type
> + */
> +typedef qb_map_iter_t *icmap_iter_t;
> +
> +/*
> + * Track type
> + */
> +typedef struct icmap_track *icmap_track_t;
> +
> +/*
> + * Initialize icmap
> + */
> +extern cs_error_t icmap_init(void);
> +
> +/*
> + * Store value with value_len length and type as key_name name in icmap.
> + */
> +extern cs_error_t icmap_set(
> +	const char *key_name,
> +	const void *value,
> +	size_t value_len,
> +        icmap_value_types_t type);
> +
> +/*
> + * Shortcuts for setting values
> + */
> +extern cs_error_t icmap_set_int8(const char *key_name, int8_t value);
> +extern cs_error_t icmap_set_uint8(const char *key_name, uint8_t value);
> +extern cs_error_t icmap_set_int16(const char *key_name, int16_t value);
> +extern cs_error_t icmap_set_uint16(const char *key_name, uint16_t value);
> +extern cs_error_t icmap_set_int32(const char *key_name, int32_t value);
> +extern cs_error_t icmap_set_uint32(const char *key_name, uint32_t value);
> +extern cs_error_t icmap_set_int64(const char *key_name, int64_t value);
> +extern cs_error_t icmap_set_uint64(const char *key_name, uint64_t value);
> +extern cs_error_t icmap_set_float(const char *key_name, float value);
> +extern cs_error_t icmap_set_double(const char *key_name, double value);
> +extern cs_error_t icmap_set_string(const char *key_name, const char *value);
> +
> +/*
> + * Delete key from map
> + */
> +extern cs_error_t icmap_delete(const char *key_name);
> +
> +/*
> + * Retrieve value of key key_name and store it in user preallocated value pointer.
> + * value can be NULL, and then only value_len and/or type is returned (both of them
> + * can also be NULL). If value is not NULL, actual length of value in map is checked
> + * against value_len. If *value_len is shorter then length of value in map, error
> + * CS_ERR_INVALID_PARAM is returned. After successful copy of value, value_len is
> + * set to actual length of value in map.
> + */
> +extern cs_error_t icmap_get(
> +	const char *key_name,
> +	void *value,
> +	size_t *value_len,
> +        icmap_value_types_t *type);
> +
> +/*
> + * Shortcuts for icmap_get
> + */
> +extern cs_error_t icmap_get_int8(const char *key_name, int8_t *i8);
> +extern cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8);
> +extern cs_error_t icmap_get_int16(const char *key_name, int16_t *i16);
> +extern cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16);
> +extern cs_error_t icmap_get_int32(const char *key_name, int32_t *i32);
> +extern cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32);
> +extern cs_error_t icmap_get_int64(const char *key_name, int64_t *i64);
> +extern cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64);
> +extern cs_error_t icmap_get_float(const char *key_name, float *flt);
> +extern cs_error_t icmap_get_double(const char *key_name, double *dbl);
> +/*
> + * Shortcut for icmap_get for string type. Returned string is newly allocated and
> + * caller is responsible for freeing memory
> + */
> +extern cs_error_t icmap_get_string(const char *key_name, char **str);
> +
> +/*
> + * Defined only for [u]int* values. It adds step to current value.
> + */
> +extern cs_error_t icmap_adjust_int(const char *key_name, int32_t step);
> +
> +/*
> + * Increase stored value by one
> + */
> +extern cs_error_t icmap_inc(const char *key_name);
> +
> +/*
> + * Decrease stored value by one
> + */
> +extern cs_error_t icmap_dec(const char *key_name);
> +
> +/*
> + * Initialize iterator with given prefix
> + */
> +extern icmap_iter_t icmap_iter_init(const char *prefix);
> +
> +/*
> + * Return next item in iterator iter. value_len and type are optional (= can be NULL), but if set,
> + * length of returned value and/or type is returned. Function returns following key_name or NULL if
> + * iteration is over.
> + */
> +extern const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type);
> +
> +/*
> + * Finalize iterator
> + */
> +extern void icmap_iter_finalize(icmap_iter_t iter);
> +
> +/*
> + * Add tracking function for given key_name. Tracked changes (add|modify|delete) depend on track_type,
> + * which is bitwise or of ICMAP_TRACK_* values. notify_fn is called on change, where user_data pointer
> + * is passed (unchanged). Value which can be used to delete tracking is passed as icmap_track.
> + */
> +extern cs_error_t icmap_track_add(
> +	const char *key_name,
> +	int32_t track_type,
> +	icmap_notify_fn_t notify_fn,
> +	void *user_data,
> +	icmap_track_t *icmap_track);
> +
> +/*
> + * Return user data associated with given track
> + */
> +extern void *icmap_track_get_user_data(icmap_track_t icmap_track);
> +
> +/*
> + * Remove previously added track
> + */
> +extern cs_error_t icmap_track_delete(icmap_track_t icmap_track);
> +
> +/*
> + * Set read-only access for given key (key_name) or prefix, if prefix is set. ro_access
> + * can be !0, which means, that old information about ro of this key is deleted.
> + * Read-only access is used only in CMAP service! (in other word it prevents users
> + * from deleting/changing key, but doesn't guarantee anything for internal icmap users.
> + */
> +extern cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access);
> +
> +/*
> + * Check in given key is read only. Returns !0 if so, otherwise (key is rw) 0.
> + */
> +extern int icmap_is_key_ro(const char *key_name);
> +
> +/*
> + * Converts given key_name to valid key name (replacing all prohibited characters by _)
> + */
> +extern void icmap_convert_name_to_valid_name(char *key_name);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* ICMAP_H_DEFINED */

_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss


[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux