Reviewed-by: Steven Dake <sdake@xxxxxxxxxx> On 12/14/2011 08:41 AM, Jan Friesse wrote: > Cmap service is application developer interface to icmap and it is > direct replacement for confdb. > > Signed-off-by: Jan Friesse <jfriesse@xxxxxxxxxx> > --- > include/corosync/cmap.h | 334 ++++++++++++++++++++++ > include/corosync/corodefs.h | 3 +- > include/corosync/ipc_cmap.h | 183 ++++++++++++ > services/Makefile.am | 2 +- > services/cmap.c | 645 +++++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 1165 insertions(+), 2 deletions(-) > create mode 100644 include/corosync/cmap.h > create mode 100644 include/corosync/ipc_cmap.h > create mode 100644 services/cmap.c > > diff --git a/include/corosync/cmap.h b/include/corosync/cmap.h > new file mode 100644 > index 0000000..b43dcea > --- /dev/null > +++ b/include/corosync/cmap.h > @@ -0,0 +1,334 @@ > +/* > + * 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. > + */ > + > +#ifndef COROSYNC_CMAP_H_DEFINED > +#define COROSYNC_CMAP_H_DEFINED > + > +#include <corosync/corotypes.h> > +#include <corosync/hdb.h> > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** > + * @addtogroup cmap_corosync > + * > + * @{ > + */ > + > +/* > + * Handle for cmap service connection > + */ > +typedef uint64_t cmap_handle_t; > + > +/* > + * Handle for cmap iterator > + */ > +typedef uint64_t cmap_iter_handle_t; > + > +/* > + * Handle for cmap tracking function > + */ > +typedef uint64_t cmap_track_handle_t; > + > +/* > + * Maximum length of key in cmap > + */ > +#define CMAP_KEYNAME_MAXLEN 255 > +/* > + * Minumum length of key in cmap > + */ > +#define CMAP_KEYNAME_MINLEN 3 > + > +/* > + * Tracking values. > + */ > +#define CMAP_TRACK_ADD 4 > +#define CMAP_TRACK_DELETE 1 > +#define CMAP_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 CMAP_TRACK_PREFIX 8 > + > +/* > + * Possible types of value. Binary is raw data without trailing zero with given length > + */ > +typedef enum { > + CMAP_VALUETYPE_INT8 = 1, > + CMAP_VALUETYPE_UINT8 = 2, > + CMAP_VALUETYPE_INT16 = 3, > + CMAP_VALUETYPE_UINT16 = 4, > + CMAP_VALUETYPE_INT32 = 5, > + CMAP_VALUETYPE_UINT32 = 6, > + CMAP_VALUETYPE_INT64 = 7, > + CMAP_VALUETYPE_UINT64 = 8, > + CMAP_VALUETYPE_FLOAT = 9, > + CMAP_VALUETYPE_DOUBLE = 10, > + CMAP_VALUETYPE_STRING = 11, > + CMAP_VALUETYPE_BINARY = 12, > +} cmap_value_types_t; > + > +/* > + * 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 cmap_notify_value { > + cmap_value_types_t type; > + size_t len; > + const void *data; > +}; > + > +/* > + * Prototype for notify callback function. Even is one of CMAP_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 (*cmap_notify_fn_t) ( > + cmap_handle_t cmap_handle, > + cmap_track_handle_t cmap_track_handle, > + int32_t event, > + const char *key_name, > + struct cmap_notify_value new_value, > + struct cmap_notify_value old_value, > + void *user_data); > + > +/** > + * Create a new cmap connection > + * > + * @param handle will be filled with handle to be used for all following > + * operations with cht. > + */ > +extern cs_error_t cmap_initialize ( > + cmap_handle_t *handle); > + > +/** > + * Close the cmap handle > + * @param handle cmap handle > + */ > +extern cs_error_t cmap_finalize ( > + cmap_handle_t handle); > + > +/* > + * Get a file descriptor on which to poll. cmap_handle_t is NOT a > + * file descriptor and may not be used directly. > + * @param handle cmap handle initialized by cmap_initialize > + * @param fd file descriptor for poll > + */ > +extern cs_error_t cmap_fd_get ( > + cmap_handle_t handle, > + int *fd); > + > +/** > + * Dispatch data from service. > + * @param handle cmap handle initialized by cmap_initialize > + * @param dispatch_types one of standard corosync dispatch values > + */ > +extern cs_error_t cmap_dispatch ( > + cmap_handle_t handle, > + cs_dispatch_flags_t dispatch_types); > +/* > + * Get/set context variable > + */ > +extern cs_error_t cmap_context_get ( > + cmap_handle_t handle, > + const void **context); > + > +extern cs_error_t cmap_context_set ( > + cmap_handle_t handle, > + const void *context); > + > + > +/** > + * Store value in cmap > + * @param handle cmap handle > + * @param key_name name of key where to store value > + * @param value value to store > + * @param value_len length of value to store > + * @param type type to store > + */ > +extern cs_error_t cmap_set( > + cmap_handle_t handle, > + const char *key_name, > + const void *value, > + size_t value_len, > + cmap_value_types_t type); > + > +/* > + * Shortcuts for cmap_set with given type > + */ > +extern cs_error_t cmap_set_int8(cmap_handle_t handle, const char *key_name, int8_t value); > +extern cs_error_t cmap_set_uint8(cmap_handle_t handle, const char *key_name, uint8_t value); > +extern cs_error_t cmap_set_int16(cmap_handle_t handle, const char *key_name, int16_t value); > +extern cs_error_t cmap_set_uint16(cmap_handle_t handle, const char *key_name, uint16_t value); > +extern cs_error_t cmap_set_int32(cmap_handle_t handle, const char *key_name, int32_t value); > +extern cs_error_t cmap_set_uint32(cmap_handle_t handle, const char *key_name, uint32_t value); > +extern cs_error_t cmap_set_int64(cmap_handle_t handle, const char *key_name, int64_t value); > +extern cs_error_t cmap_set_uint64(cmap_handle_t handle, const char *key_name, uint64_t value); > +extern cs_error_t cmap_set_float(cmap_handle_t handle, const char *key_name, float value); > +extern cs_error_t cmap_set_double(cmap_handle_t handle, const char *key_name, double value); > +extern cs_error_t cmap_set_string(cmap_handle_t handle, const char *key_name, const char *value); > + > +/** > + * Deletes key from cmap database > + * @param handle cmap handle > + * @param key_name name of key to delete > + */ > +extern cs_error_t cmap_delete(cmap_handle_t handle, 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. > + * > + * @param handle cmap handle > + * @param key_name name of key where to get value > + * @param value pointer to store data (or NULL) > + * @param value_len pointer with length of value (value != NULL), or pointer where value length > + * will be returned (value == NULL) or NULL. > + * @param type type of value in cmap > + */ > +extern cs_error_t cmap_get( > + cmap_handle_t handle, > + const char *key_name, > + void *value, > + size_t *value_len, > + cmap_value_types_t *type); > + > +/* > + * Shortcuts for cmap_get. > + */ > +extern cs_error_t cmap_get_int8(cmap_handle_t handle, const char *key_name, int8_t *i8); > +extern cs_error_t cmap_get_uint8(cmap_handle_t handle, const char *key_name, uint8_t *u8); > +extern cs_error_t cmap_get_int16(cmap_handle_t handle, const char *key_name, int16_t *i16); > +extern cs_error_t cmap_get_uint16(cmap_handle_t handle, const char *key_name, uint16_t *u16); > +extern cs_error_t cmap_get_int32(cmap_handle_t handle, const char *key_name, int32_t *i32); > +extern cs_error_t cmap_get_uint32(cmap_handle_t handle, const char *key_name, uint32_t *u32); > +extern cs_error_t cmap_get_int64(cmap_handle_t handle, const char *key_name, int64_t *i64); > +extern cs_error_t cmap_get_uint64(cmap_handle_t handle, const char *key_name, uint64_t *u64); > +extern cs_error_t cmap_get_float(cmap_handle_t handle, const char *key_name, float *flt); > +extern cs_error_t cmap_get_double(cmap_handle_t handle, const char *key_name, double *dbl); > + > +/** > + * Shortcut for cmap_get for string type. Returned string is newly allocated and > + * caller is responsible for freeing memory > + * @param handle cmap handle > + * @param key_name name of key to get value from > + * @param str pointer where char pointer will be stored > + */ > +extern cs_error_t cmap_get_string(cmap_handle_t handle, const char *key_name, char **str); > + > +/** > + * Increment value of key_name if it is [u]int* type > + * @param handle cmap handle > + * @param key_name key name > + */ > +extern cs_error_t cmap_inc(cmap_handle_t handle, const char *key_name); > + > +/** > + * Decrement value of key_name if it is [u]int* type > + * @param handle cmap handle > + * @param key_name key name > + */ > +extern cs_error_t cmap_dec(cmap_handle_t handle, const char *key_name); > + > +/** > + * Initialize iterator with given prefix > + * @param handle cmap handle > + * @param prefix prefix to iterate on > + * @param cmap_iter_handle value used for getting next value of iterator and/or deleting iteration > + */ > +extern cs_error_t cmap_iter_init(cmap_handle_t handle, const char *prefix, cmap_iter_handle_t *cmap_iter_handle); > + > +/** > + * 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. > + * > + * @param handle cmap handle > + * @param cmap_iter_handle handle of iteration returned by cmap_iter_init > + * @param key_name place to store name of key. Maximum length is CMAP_KEYNAME_MAXLEN > + * @param value_len length of value > + * @param type type of value > + * @return CS_NO_SECTION if there are no more sections to iterate > + */ > +extern cs_error_t cmap_iter_next( > + cmap_handle_t handle, > + cmap_iter_handle_t iter_handle, > + char key_name[], > + size_t *value_len, > + cmap_value_types_t *type); > + > +/** > + * Finalize iterator > + */ > +extern cs_error_t cmap_iter_finalize(cmap_handle_t handle, cmap_iter_handle_t iter_handle); > + > +/* > + * Add tracking function for given key_name. Tracked changes (add|modify|delete) depend on track_type, > + * which is bitwise or of CMAP_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 cmap_track. > + * @param handle cmap handle > + * @param key_name name of key to track changes on > + * @param track_type bitwise-or of CMAP_TRACK_* values > + * @param notify_fn function to be called on change of key > + * @param user_data given pointer is unchanged passed to notify_fn > + * @param cmap_track_handle handle used for removing of newly created track > + */ > +extern cs_error_t cmap_track_add( > + cmap_handle_t handle, > + const char *key_name, > + int32_t track_type, > + cmap_notify_fn_t notify_fn, > + void *user_data, > + cmap_track_handle_t *cmap_track_handle); > + > +/** > + * Delete track created previously by cmap_track_add > + * @param handle cmap handle > + * @param track_handle Track handle > + */ > +extern cs_error_t cmap_track_delete(cmap_handle_t handle, cmap_track_handle_t track_handle); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* COROSYNC_CMAP_H_DEFINED */ > diff --git a/include/corosync/corodefs.h b/include/corosync/corodefs.h > index 7d03644..c43f6ca 100644 > --- a/include/corosync/corodefs.h > +++ b/include/corosync/corodefs.h > @@ -59,7 +59,8 @@ enum corosync_service_types { > TST_SV1_SERVICE = 18, > TST_SV2_SERVICE = 19, > MON_SERVICE = 20, > - WD_SERVICE = 21 > + WD_SERVICE = 21, > + CMAP_SERVICE = 22, > }; > > #ifdef HAVE_SMALL_MEMORY_FOOTPRINT > diff --git a/include/corosync/ipc_cmap.h b/include/corosync/ipc_cmap.h > new file mode 100644 > index 0000000..5784410 > --- /dev/null > +++ b/include/corosync/ipc_cmap.h > @@ -0,0 +1,183 @@ > +/* > + * 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. > + */ > + > +#ifndef IPC_CMAP_H_DEFINED > +#define IPC_CMAP_H_DEFINED > + > +#include <netinet/in.h> > +#include <corosync/corotypes.h> > +#include <corosync/mar_gen.h> > + > +enum req_cmap_types { > + MESSAGE_REQ_CMAP_SET = 0, > + MESSAGE_REQ_CMAP_DELETE = 1, > + MESSAGE_REQ_CMAP_GET = 2, > + MESSAGE_REQ_CMAP_ADJUST_INT = 3, > + MESSAGE_REQ_CMAP_ITER_INIT = 4, > + MESSAGE_REQ_CMAP_ITER_NEXT = 5, > + MESSAGE_REQ_CMAP_ITER_FINALIZE = 6, > + MESSAGE_REQ_CMAP_TRACK_ADD = 7, > + MESSAGE_REQ_CMAP_TRACK_DELETE = 8, > +}; > + > +enum res_cmap_types { > + MESSAGE_RES_CMAP_SET = 0, > + MESSAGE_RES_CMAP_DELETE = 1, > + MESSAGE_RES_CMAP_GET = 2, > + MESSAGE_RES_CMAP_ADJUST_INT = 3, > + MESSAGE_RES_CMAP_ITER_INIT = 4, > + MESSAGE_RES_CMAP_ITER_NEXT = 5, > + MESSAGE_RES_CMAP_ITER_FINALIZE = 6, > + MESSAGE_RES_CMAP_TRACK_ADD = 7, > + MESSAGE_RES_CMAP_TRACK_DELETE = 8, > + MESSAGE_RES_CMAP_NOTIFY_CALLBACK = 9, > +}; > + > +struct req_lib_cmap_set { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_name_t key_name __attribute__((aligned(8))); > + mar_size_t value_len __attribute__((aligned(8))); > + mar_uint8_t type __attribute__((aligned(8))); > + mar_uint8_t value[] __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_set { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_delete { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_name_t key_name __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_delete { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_get { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_name_t key_name __attribute__((aligned(8))); > + mar_size_t value_len __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_get { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > + mar_size_t value_len __attribute__((aligned(8))); > + mar_uint8_t type __attribute__((aligned(8))); > + mar_uint8_t value[] __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_adjust_int { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_name_t key_name __attribute__((aligned(8))); > + mar_int32_t step __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_adjust_int { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_iter_init { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_name_t prefix __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_iter_init { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > + mar_uint64_t iter_handle __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_iter_next { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_uint64_t iter_handle __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_iter_next { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > + mar_name_t key_name __attribute__((aligned(8))); > + mar_size_t value_len __attribute__((aligned(8))); > + mar_uint8_t type __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_iter_finalize { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_uint64_t iter_handle __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_iter_finalize { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_track_add { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_name_t key_name __attribute__((aligned(8))); > + mar_int32_t track_type __attribute__((aligned(8))); > + mar_uint64_t track_inst_handle __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_track_add { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > + mar_uint64_t track_handle __attribute__((aligned(8))); > +}; > + > +struct req_lib_cmap_track_delete { > + struct qb_ipc_request_header header __attribute__((aligned(8))); > + mar_uint64_t track_handle __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_track_delete { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > + mar_uint64_t track_inst_handle __attribute__((aligned(8))); > +}; > + > +struct res_lib_cmap_notify_callback { > + struct qb_ipc_response_header header __attribute__((aligned(8))); > + mar_uint64_t track_inst_handle __attribute__((aligned(8))); > + mar_name_t key_name __attribute__((aligned(8))); > + mar_int32_t event __attribute__((aligned(8))); > + mar_uint8_t new_value_type __attribute__((aligned(8))); > + mar_uint8_t old_value_type __attribute__((aligned(8))); > + mar_size_t new_value_len __attribute__((aligned(8))); > + mar_size_t old_value_len __attribute__((aligned(8))); > + /* > + * After old_vale_len, there are two items with length of new_value_len > + * and old_value_len, only first (as a pointer) is defined > + * > + * mar_uint8_t *new_value; > + * mar_uint8_t *old_value; > + */ > + mar_uint8_t new_value[]; > +}; > + > +#endif /* IPC_CMAP_H_DEFINED */ > diff --git a/services/Makefile.am b/services/Makefile.am > index f39adc3..376363d 100644 > --- a/services/Makefile.am > +++ b/services/Makefile.am > @@ -37,7 +37,7 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ > -I$(top_builddir)/include/corosync \ > -I$(top_srcdir)/include/corosync > > -SERVICE_LCRSO = evs cfg cpg confdb pload > +SERVICE_LCRSO = evs cfg cpg confdb pload cmap > if BUILD_WATCHDOG > SERVICE_LCRSO += wd > endif > diff --git a/services/cmap.c b/services/cmap.c > new file mode 100644 > index 0000000..92f0574 > --- /dev/null > +++ b/services/cmap.c > @@ -0,0 +1,645 @@ > +/* > + * 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 <sys/types.h> > +#include <unistd.h> > +#include <fcntl.h> > +#include <stdlib.h> > +#include <errno.h> > +#include <unistd.h> > +#include <poll.h> > +#include <assert.h> > + > +#include <qb/qbloop.h> > +#include <qb/qbipc_common.h> > + > +#include <corosync/corotypes.h> > +#include <corosync/corodefs.h> > +#include <corosync/list.h> > +#include <corosync/mar_gen.h> > +#include <corosync/ipc_cmap.h> > +#include <corosync/lcr/lcr_comp.h> > +#include <corosync/engine/logsys.h> > +#include <corosync/engine/coroapi.h> > +#include <corosync/engine/icmap.h> > + > +#define hdb_error_to_cs(_result_) qb_to_cs_error(_result_) > + > +LOGSYS_DECLARE_SUBSYS ("CMAP"); > + > +struct cmap_conn_info { > + struct hdb_handle_database iter_db; > + struct hdb_handle_database track_db; > +}; > + > +typedef uint64_t cmap_iter_handle_t; > +typedef uint64_t cmap_track_handle_t; > + > +struct cmap_track_user_data { > + void *conn; > + cmap_track_handle_t track_handle; > + uint64_t track_inst_handle; > +}; > + > +static struct corosync_api_v1 *api; > + > +static int cmap_exec_init_fn (struct corosync_api_v1 *corosync_api); > +static int cmap_exec_exit_fn(void); > + > +static int cmap_lib_init_fn (void *conn); > +static int cmap_lib_exit_fn (void *conn); > + > +static void message_handler_req_lib_cmap_set(void *conn, const void *message); > +static void message_handler_req_lib_cmap_delete(void *conn, const void *message); > +static void message_handler_req_lib_cmap_get(void *conn, const void *message); > +static void message_handler_req_lib_cmap_adjust_int(void *conn, const void *message); > +static void message_handler_req_lib_cmap_iter_init(void *conn, const void *message); > +static void message_handler_req_lib_cmap_iter_next(void *conn, const void *message); > +static void message_handler_req_lib_cmap_iter_finalize(void *conn, const void *message); > +static void message_handler_req_lib_cmap_track_add(void *conn, const void *message); > +static void message_handler_req_lib_cmap_track_delete(void *conn, const void *message); > + > +static void cmap_notify_fn(int32_t event, > + const char *key_name, > + struct icmap_notify_value new_val, > + struct icmap_notify_value old_val, > + void *user_data); > + > +/* > + * Library Handler Definition > + */ > +static struct corosync_lib_handler cmap_lib_engine[] = > +{ > + { /* 0 */ > + .lib_handler_fn = message_handler_req_lib_cmap_set, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 1 */ > + .lib_handler_fn = message_handler_req_lib_cmap_delete, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 2 */ > + .lib_handler_fn = message_handler_req_lib_cmap_get, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 3 */ > + .lib_handler_fn = message_handler_req_lib_cmap_adjust_int, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 4 */ > + .lib_handler_fn = message_handler_req_lib_cmap_iter_init, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 5 */ > + .lib_handler_fn = message_handler_req_lib_cmap_iter_next, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 6 */ > + .lib_handler_fn = message_handler_req_lib_cmap_iter_finalize, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 7 */ > + .lib_handler_fn = message_handler_req_lib_cmap_track_add, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > + { /* 8 */ > + .lib_handler_fn = message_handler_req_lib_cmap_track_delete, > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED > + }, > +}; > + > + > +struct corosync_service_engine cmap_service_engine = { > + .name = "corosync configuration map access", > + .id = CMAP_SERVICE, > + .priority = 1, > + .private_data_size = sizeof(struct cmap_conn_info), > + .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED, > + .allow_inquorate = CS_LIB_ALLOW_INQUORATE, > + .lib_init_fn = cmap_lib_init_fn, > + .lib_exit_fn = cmap_lib_exit_fn, > + .lib_engine = cmap_lib_engine, > + .lib_engine_count = sizeof (cmap_lib_engine) / sizeof (struct corosync_lib_handler), > + .exec_init_fn = cmap_exec_init_fn, > + .exec_exit_fn = cmap_exec_exit_fn, > +}; > + > +/* > + * Dynamic loader definition > + */ > +static struct corosync_service_engine *cmap_get_service_engine_ver0 (void); > + > +static struct corosync_service_engine_iface_ver0 cmap_service_engine_iface = { > + .corosync_get_service_engine_ver0 = cmap_get_service_engine_ver0 > +}; > + > +static struct lcr_iface corosync_cmap_ver0[1] = { > + { > + .name = "corosync_cmap", > + .version = 0, > + .versions_replace = 0, > + .versions_replace_count = 0, > + .dependencies = 0, > + .dependency_count = 0, > + .constructor = NULL, > + .destructor = NULL, > + .interfaces = NULL > + } > +}; > + > +static struct lcr_comp cmap_comp_ver0 = { > + .iface_count = 1, > + .ifaces = corosync_cmap_ver0 > +}; > + > + > +static struct corosync_service_engine *cmap_get_service_engine_ver0 (void) > +{ > + return (&cmap_service_engine); > +} > + > +#ifdef COROSYNC_SOLARIS > +void corosync_lcr_component_register (void); > + > +void corosync_lcr_component_register (void) { > +#else > +__attribute__ ((constructor)) static void corosync_lcr_component_register (void) { > +#endif > + lcr_interfaces_set (&corosync_cmap_ver0[0], &cmap_service_engine_iface); > + > + lcr_component_register (&cmap_comp_ver0); > +} > + > +static int cmap_exec_exit_fn(void) > +{ > + return 0; > +} > + > +static int cmap_exec_init_fn ( > + struct corosync_api_v1 *corosync_api) > +{ > + > +#ifdef COROSYNC_SOLARIS > + logsys_subsys_init(); > +#endif > + api = corosync_api; > + > + return (0); > +} > + > +static int cmap_lib_init_fn (void *conn) > +{ > + struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn); > + > + log_printf(LOGSYS_LEVEL_DEBUG, "lib_init_fn: conn=%p\n", conn); > + > + api->ipc_refcnt_inc(conn); > + > + memset(conn_info, 0, sizeof(*conn_info)); > + hdb_create(&conn_info->iter_db); > + hdb_create(&conn_info->track_db); > + > + return (0); > +} > + > +static int cmap_lib_exit_fn (void *conn) > +{ > + struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn); > + hdb_handle_t iter_handle = 0; > + icmap_iter_t *iter; > + hdb_handle_t track_handle = 0; > + icmap_track_t *track; > + > + log_printf(LOGSYS_LEVEL_DEBUG, "exit_fn for conn=%p\n", conn); > + > + hdb_iterator_reset(&conn_info->iter_db); > + while (hdb_iterator_next(&conn_info->iter_db, > + (void*)&iter, &iter_handle) == 0) { > + > + icmap_iter_finalize(*iter); > + > + (void)hdb_handle_put (&conn_info->iter_db, iter_handle); > + } > + > + hdb_destroy(&conn_info->iter_db); > + > + hdb_iterator_reset(&conn_info->track_db); > + while (hdb_iterator_next(&conn_info->track_db, > + (void*)&track, &track_handle) == 0) { > + > + free(icmap_track_get_user_data(*track)); > + > + icmap_track_delete(*track); > + > + (void)hdb_handle_put (&conn_info->track_db, track_handle); > + } > + hdb_destroy(&conn_info->track_db); > + > + api->ipc_refcnt_dec(conn); > + > + return (0); > +} > + > +static void message_handler_req_lib_cmap_set(void *conn, const void *message) > +{ > + const struct req_lib_cmap_set *req_lib_cmap_set = message; > + struct res_lib_cmap_set res_lib_cmap_set; > + cs_error_t ret; > + > + if (icmap_is_key_ro((char *)req_lib_cmap_set->key_name.value)) { > + ret = CS_ERR_ACCESS; > + } else { > + ret = icmap_set((char *)req_lib_cmap_set->key_name.value, &req_lib_cmap_set->value, > + req_lib_cmap_set->value_len, req_lib_cmap_set->type); > + } > + > + memset(&res_lib_cmap_set, 0, sizeof(res_lib_cmap_set)); > + res_lib_cmap_set.header.size = sizeof(res_lib_cmap_set); > + res_lib_cmap_set.header.id = MESSAGE_RES_CMAP_SET; > + res_lib_cmap_set.header.error = ret; > + > + api->ipc_response_send(conn, &res_lib_cmap_set, sizeof(res_lib_cmap_set)); > +} > + > +static void message_handler_req_lib_cmap_delete(void *conn, const void *message) > +{ > + const struct req_lib_cmap_set *req_lib_cmap_set = message; > + struct res_lib_cmap_delete res_lib_cmap_delete; > + cs_error_t ret; > + > + if (icmap_is_key_ro((char *)req_lib_cmap_set->key_name.value)) { > + ret = CS_ERR_ACCESS; > + } else { > + ret = icmap_delete((char *)req_lib_cmap_set->key_name.value); > + } > + > + memset(&res_lib_cmap_delete, 0, sizeof(res_lib_cmap_delete)); > + res_lib_cmap_delete.header.size = sizeof(res_lib_cmap_delete); > + res_lib_cmap_delete.header.id = MESSAGE_RES_CMAP_DELETE; > + res_lib_cmap_delete.header.error = ret; > + > + api->ipc_response_send(conn, &res_lib_cmap_delete, sizeof(res_lib_cmap_delete)); > +} > + > +static void message_handler_req_lib_cmap_get(void *conn, const void *message) > +{ > + const struct req_lib_cmap_get *req_lib_cmap_get = message; > + struct res_lib_cmap_get *res_lib_cmap_get; > + struct res_lib_cmap_get error_res_lib_cmap_get; > + cs_error_t ret; > + size_t value_len; > + size_t res_lib_cmap_get_size; > + icmap_value_types_t type; > + void *value; > + > + value_len = req_lib_cmap_get->value_len; > + > + res_lib_cmap_get_size = sizeof(*res_lib_cmap_get) + value_len; > + res_lib_cmap_get = malloc(res_lib_cmap_get_size); > + if (res_lib_cmap_get == NULL) { > + ret = CS_ERR_NO_MEMORY; > + goto error_exit; > + } > + > + memset(res_lib_cmap_get, 0, res_lib_cmap_get_size); > + > + if (value_len > 0) { > + value = res_lib_cmap_get->value; > + } else { > + value = NULL; > + } > + > + ret = icmap_get((char *)req_lib_cmap_get->key_name.value, > + value, > + &value_len, > + &type); > + > + if (ret != CS_OK) { > + free(res_lib_cmap_get); > + goto error_exit; > + } > + > + res_lib_cmap_get->header.size = res_lib_cmap_get_size; > + res_lib_cmap_get->header.id = MESSAGE_RES_CMAP_GET; > + res_lib_cmap_get->header.error = ret; > + res_lib_cmap_get->type = type; > + res_lib_cmap_get->value_len = value_len; > + > + api->ipc_response_send(conn, res_lib_cmap_get, res_lib_cmap_get_size); > + free(res_lib_cmap_get); > + > + return ; > + > +error_exit: > + memset(&error_res_lib_cmap_get, 0, sizeof(error_res_lib_cmap_get)); > + error_res_lib_cmap_get.header.size = sizeof(error_res_lib_cmap_get); > + error_res_lib_cmap_get.header.id = MESSAGE_RES_CMAP_GET; > + error_res_lib_cmap_get.header.error = ret; > + > + api->ipc_response_send(conn, &error_res_lib_cmap_get, sizeof(error_res_lib_cmap_get)); > +} > + > +static void message_handler_req_lib_cmap_adjust_int(void *conn, const void *message) > +{ > + const struct req_lib_cmap_adjust_int *req_lib_cmap_adjust_int = message; > + struct res_lib_cmap_adjust_int res_lib_cmap_adjust_int; > + cs_error_t ret; > + > + ret = icmap_adjust_int((char *)req_lib_cmap_adjust_int->key_name.value, req_lib_cmap_adjust_int->step); > + > + memset(&res_lib_cmap_adjust_int, 0, sizeof(res_lib_cmap_adjust_int)); > + res_lib_cmap_adjust_int.header.size = sizeof(res_lib_cmap_adjust_int); > + res_lib_cmap_adjust_int.header.id = MESSAGE_RES_CMAP_ADJUST_INT; > + res_lib_cmap_adjust_int.header.error = ret; > + > + api->ipc_response_send(conn, &res_lib_cmap_adjust_int, sizeof(res_lib_cmap_adjust_int)); > +} > + > +static void message_handler_req_lib_cmap_iter_init(void *conn, const void *message) > +{ > + const struct req_lib_cmap_iter_init *req_lib_cmap_iter_init = message; > + struct res_lib_cmap_iter_init res_lib_cmap_iter_init; > + cs_error_t ret; > + icmap_iter_t iter; > + icmap_iter_t *hdb_iter; > + cmap_iter_handle_t handle; > + const char *prefix; > + struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn); > + > + if (req_lib_cmap_iter_init->prefix.length > 0) { > + prefix = (char *)req_lib_cmap_iter_init->prefix.value; > + } else { > + prefix = NULL; > + } > + > + iter = icmap_iter_init(prefix); > + if (iter == NULL) { > + ret = CS_ERR_NO_SECTIONS; > + goto reply_send; > + } > + > + ret = hdb_error_to_cs(hdb_handle_create(&conn_info->iter_db, sizeof(iter), &handle)); > + if (ret != CS_OK) { > + goto reply_send; > + } > + > + ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db, handle, (void *)&hdb_iter)); > + if (ret != CS_OK) { > + goto reply_send; > + } > + > + *hdb_iter = iter; > + > + (void)hdb_handle_put (&conn_info->iter_db, handle); > + > +reply_send: > + memset(&res_lib_cmap_iter_init, 0, sizeof(res_lib_cmap_iter_init)); > + res_lib_cmap_iter_init.header.size = sizeof(res_lib_cmap_iter_init); > + res_lib_cmap_iter_init.header.id = MESSAGE_RES_CMAP_ITER_INIT; > + res_lib_cmap_iter_init.header.error = ret; > + res_lib_cmap_iter_init.iter_handle = handle; > + > + api->ipc_response_send(conn, &res_lib_cmap_iter_init, sizeof(res_lib_cmap_iter_init)); > +} > + > +static void message_handler_req_lib_cmap_iter_next(void *conn, const void *message) > +{ > + const struct req_lib_cmap_iter_next *req_lib_cmap_iter_next = message; > + struct res_lib_cmap_iter_next res_lib_cmap_iter_next; > + cs_error_t ret; > + icmap_iter_t *iter; > + size_t value_len; > + icmap_value_types_t type; > + const char *res = NULL; > + struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn); > + > + ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db, > + req_lib_cmap_iter_next->iter_handle, (void *)&iter)); > + if (ret != CS_OK) { > + goto reply_send; > + } > + > + res = icmap_iter_next(*iter, &value_len, &type); > + if (res == NULL) { > + ret = CS_ERR_NO_SECTIONS; > + } > + > + (void)hdb_handle_put (&conn_info->iter_db, req_lib_cmap_iter_next->iter_handle); > + > +reply_send: > + memset(&res_lib_cmap_iter_next, 0, sizeof(res_lib_cmap_iter_next)); > + res_lib_cmap_iter_next.header.size = sizeof(res_lib_cmap_iter_next); > + res_lib_cmap_iter_next.header.id = MESSAGE_RES_CMAP_ITER_NEXT; > + res_lib_cmap_iter_next.header.error = ret; > + > + if (res != NULL) { > + res_lib_cmap_iter_next.value_len = value_len; > + res_lib_cmap_iter_next.type = type; > + > + memcpy(res_lib_cmap_iter_next.key_name.value, res, strlen(res)); > + res_lib_cmap_iter_next.key_name.length = strlen(res); > + } > + > + api->ipc_response_send(conn, &res_lib_cmap_iter_next, sizeof(res_lib_cmap_iter_next)); > +} > + > +static void message_handler_req_lib_cmap_iter_finalize(void *conn, const void *message) > +{ > + const struct req_lib_cmap_iter_finalize *req_lib_cmap_iter_finalize = message; > + struct res_lib_cmap_iter_finalize res_lib_cmap_iter_finalize; > + cs_error_t ret; > + icmap_iter_t *iter; > + struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn); > + > + ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db, > + req_lib_cmap_iter_finalize->iter_handle, (void *)&iter)); > + if (ret != CS_OK) { > + goto reply_send; > + } > + > + icmap_iter_finalize(*iter); > + > + (void)hdb_handle_destroy(&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle); > + > + (void)hdb_handle_put (&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle); > + > +reply_send: > + memset(&res_lib_cmap_iter_finalize, 0, sizeof(res_lib_cmap_iter_finalize)); > + res_lib_cmap_iter_finalize.header.size = sizeof(res_lib_cmap_iter_finalize); > + res_lib_cmap_iter_finalize.header.id = MESSAGE_RES_CMAP_ITER_FINALIZE; > + res_lib_cmap_iter_finalize.header.error = ret; > + > + api->ipc_response_send(conn, &res_lib_cmap_iter_finalize, sizeof(res_lib_cmap_iter_finalize)); > +} > + > +static void cmap_notify_fn(int32_t event, > + const char *key_name, > + struct icmap_notify_value new_val, > + struct icmap_notify_value old_val, > + void *user_data) > +{ > + struct cmap_track_user_data *cmap_track_user_data = (struct cmap_track_user_data *)user_data; > + struct res_lib_cmap_notify_callback res_lib_cmap_notify_callback; > + struct iovec iov[3]; > + > + memset(&res_lib_cmap_notify_callback, 0, sizeof(res_lib_cmap_notify_callback)); > + > + res_lib_cmap_notify_callback.header.size = sizeof(res_lib_cmap_notify_callback) + new_val.len + old_val.len; > + res_lib_cmap_notify_callback.header.id = MESSAGE_RES_CMAP_NOTIFY_CALLBACK; > + res_lib_cmap_notify_callback.header.error = CS_OK; > + > + res_lib_cmap_notify_callback.new_value_type = new_val.type; > + res_lib_cmap_notify_callback.old_value_type = old_val.type; > + res_lib_cmap_notify_callback.new_value_len = new_val.len; > + res_lib_cmap_notify_callback.old_value_len = old_val.len; > + res_lib_cmap_notify_callback.event = event; > + res_lib_cmap_notify_callback.key_name.length = strlen(key_name); > + res_lib_cmap_notify_callback.track_inst_handle = cmap_track_user_data->track_inst_handle; > + > + memcpy(res_lib_cmap_notify_callback.key_name.value, key_name, strlen(key_name)); > + > + iov[0].iov_base = (char *)&res_lib_cmap_notify_callback; > + iov[0].iov_len = sizeof(res_lib_cmap_notify_callback); > + iov[1].iov_base = (char *)new_val.data; > + iov[1].iov_len = new_val.len; > + iov[2].iov_base = (char *)old_val.data; > + iov[2].iov_len = old_val.len; > + > + api->ipc_dispatch_iov_send(cmap_track_user_data->conn, iov, 3); > +} > + > +static void message_handler_req_lib_cmap_track_add(void *conn, const void *message) > +{ > + const struct req_lib_cmap_track_add *req_lib_cmap_track_add = message; > + struct res_lib_cmap_track_add res_lib_cmap_track_add; > + cs_error_t ret; > + cmap_track_handle_t handle; > + icmap_track_t track; > + icmap_track_t *hdb_track; > + struct cmap_track_user_data *cmap_track_user_data; > + const char *key_name; > + > + struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn); > + > + cmap_track_user_data = malloc(sizeof(*cmap_track_user_data)); > + if (cmap_track_user_data == NULL) { > + ret = CS_ERR_NO_MEMORY; > + > + goto reply_send; > + } > + memset(cmap_track_user_data, 0, sizeof(*cmap_track_user_data)); > + > + if (req_lib_cmap_track_add->key_name.length > 0) { > + key_name = (char *)req_lib_cmap_track_add->key_name.value; > + } else { > + key_name = NULL; > + } > + > + ret = icmap_track_add(key_name, > + req_lib_cmap_track_add->track_type, > + cmap_notify_fn, > + cmap_track_user_data, > + &track); > + if (ret != CS_OK) { > + free(cmap_track_user_data); > + > + goto reply_send; > + } > + > + ret = hdb_error_to_cs(hdb_handle_create(&conn_info->track_db, sizeof(track), &handle)); > + if (ret != CS_OK) { > + free(cmap_track_user_data); > + > + goto reply_send; > + } > + > + ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db, handle, (void *)&hdb_track)); > + if (ret != CS_OK) { > + free(cmap_track_user_data); > + > + goto reply_send; > + } > + > + *hdb_track = track; > + cmap_track_user_data->conn = conn; > + cmap_track_user_data->track_handle = handle; > + cmap_track_user_data->track_inst_handle = req_lib_cmap_track_add->track_inst_handle; > + > + (void)hdb_handle_put (&conn_info->track_db, handle); > + > +reply_send: > + memset(&res_lib_cmap_track_add, 0, sizeof(res_lib_cmap_track_add)); > + res_lib_cmap_track_add.header.size = sizeof(res_lib_cmap_track_add); > + res_lib_cmap_track_add.header.id = MESSAGE_RES_CMAP_TRACK_ADD; > + res_lib_cmap_track_add.header.error = ret; > + res_lib_cmap_track_add.track_handle = handle; > + > + api->ipc_response_send(conn, &res_lib_cmap_track_add, sizeof(res_lib_cmap_track_add)); > +} > + > +static void message_handler_req_lib_cmap_track_delete(void *conn, const void *message) > +{ > + const struct req_lib_cmap_track_delete *req_lib_cmap_track_delete = message; > + struct res_lib_cmap_track_delete res_lib_cmap_track_delete; > + cs_error_t ret; > + icmap_track_t *track; > + struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn); > + uint64_t track_inst_handle = 0; > + > + ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db, > + req_lib_cmap_track_delete->track_handle, (void *)&track)); > + if (ret != CS_OK) { > + goto reply_send; > + } > + > + track_inst_handle = ((struct cmap_track_user_data *)icmap_track_get_user_data(*track))->track_inst_handle; > + > + free(icmap_track_get_user_data(*track)); > + > + ret = icmap_track_delete(*track); > + > + (void)hdb_handle_put (&conn_info->track_db, req_lib_cmap_track_delete->track_handle); > + (void)hdb_handle_destroy(&conn_info->track_db, req_lib_cmap_track_delete->track_handle); > + > +reply_send: > + memset(&res_lib_cmap_track_delete, 0, sizeof(res_lib_cmap_track_delete)); > + res_lib_cmap_track_delete.header.size = sizeof(res_lib_cmap_track_delete); > + res_lib_cmap_track_delete.header.id = MESSAGE_RES_CMAP_TRACK_DELETE; > + res_lib_cmap_track_delete.header.error = ret; > + res_lib_cmap_track_delete.track_inst_handle = track_inst_handle; > + > + api->ipc_response_send(conn, &res_lib_cmap_track_delete, sizeof(res_lib_cmap_track_delete)); > +} _______________________________________________ discuss mailing list discuss@xxxxxxxxxxxx http://lists.corosync.org/mailman/listinfo/discuss