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