diff options
Diffstat (limited to 'lib/cmap.c')
-rw-r--r-- | lib/cmap.c | 1119 |
1 files changed, 1119 insertions, 0 deletions
diff --git a/lib/cmap.c b/lib/cmap.c new file mode 100644 index 0000000..ed9774a --- /dev/null +++ b/lib/cmap.c @@ -0,0 +1,1119 @@ +/* + * Copyright (c) 2011-2017 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Jan Friesse (jfriesse@redhat.com) + * + * 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 <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <errno.h> + +#include <corosync/corotypes.h> +#include <corosync/corodefs.h> +#include <corosync/hdb.h> +#include <qb/qbipcc.h> + +#include <corosync/cmap.h> +#include <corosync/ipc_cmap.h> + +#include "util.h" +#include <stdio.h> + +struct cmap_inst { + int finalize; + qb_ipcc_connection_t *c; + const void *context; +}; + +struct cmap_track_inst { + void *user_data; + cmap_notify_fn_t notify_fn; + qb_ipcc_connection_t *c; + cmap_track_handle_t track_handle; +}; + +static void cmap_inst_free (void *inst); + +DECLARE_HDB_DATABASE(cmap_handle_t_db, cmap_inst_free); +DECLARE_HDB_DATABASE(cmap_track_handle_t_db,NULL); + +/* + * Function prototypes + */ +static cs_error_t cmap_get_int( + cmap_handle_t handle, + const char *key_name, + void *value, + size_t value_size, + cmap_value_types_t type); + +static cs_error_t cmap_adjust_int(cmap_handle_t handle, const char *key_name, int32_t step); + +/* + * Function implementations + */ +cs_error_t cmap_initialize (cmap_handle_t *handle) +{ + cs_error_t error; + struct cmap_inst *cmap_inst; + + error = hdb_error_to_cs(hdb_handle_create(&cmap_handle_t_db, sizeof(*cmap_inst), handle)); + if (error != CS_OK) { + goto error_no_destroy; + } + + error = hdb_error_to_cs(hdb_handle_get(&cmap_handle_t_db, *handle, (void *)&cmap_inst)); + if (error != CS_OK) { + goto error_destroy; + } + + error = CS_OK; + cmap_inst->finalize = 0; + cmap_inst->c = qb_ipcc_connect("cmap", IPC_REQUEST_SIZE); + if (cmap_inst->c == NULL) { + error = qb_to_cs_error(-errno); + goto error_put_destroy; + } + + (void)hdb_handle_put(&cmap_handle_t_db, *handle); + + return (CS_OK); + +error_put_destroy: + (void)hdb_handle_put(&cmap_handle_t_db, *handle); +error_destroy: + (void)hdb_handle_destroy(&cmap_handle_t_db, *handle); +error_no_destroy: + return (error); +} + +cs_error_t cmap_initialize_map (cmap_handle_t *handle, + cmap_map_t map) +{ + cs_error_t error; + struct iovec iov[1]; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_set_current_map req_lib_cmap_set_current_map; + struct qb_ipc_response_header res_lib_cmap_set_current_map; + + error = cmap_initialize(handle); + + if (error == CS_OK) { + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, *handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_set_current_map, 0, sizeof(req_lib_cmap_set_current_map)); + req_lib_cmap_set_current_map.header.size = sizeof(req_lib_cmap_set_current_map); + req_lib_cmap_set_current_map.header.id = MESSAGE_REQ_CMAP_SET_CURRENT_MAP; + req_lib_cmap_set_current_map.map = map; + + iov[0].iov_base = (char *)&req_lib_cmap_set_current_map; + iov[0].iov_len = sizeof(req_lib_cmap_set_current_map); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + iov, + 1, + &res_lib_cmap_set_current_map, + sizeof (res_lib_cmap_set_current_map), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_set_current_map.error; + } + + (void)hdb_handle_put (&cmap_handle_t_db, *handle); + + return (error); + } + return (error); +} + +static void cmap_inst_free (void *inst) +{ + struct cmap_inst *cmap_inst = (struct cmap_inst *)inst; + qb_ipcc_disconnect(cmap_inst->c); +} + +cs_error_t cmap_finalize(cmap_handle_t handle) +{ + struct cmap_inst *cmap_inst; + cs_error_t error; + hdb_handle_t track_inst_handle = 0; + struct cmap_track_inst *cmap_track_inst; + + error = hdb_error_to_cs(hdb_handle_get(&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + if (cmap_inst->finalize) { + (void)hdb_handle_put (&cmap_handle_t_db, handle); + return (CS_ERR_BAD_HANDLE); + } + cmap_inst->finalize = 1; + + /* + * Destroy all track instances for given connection + */ + hdb_iterator_reset(&cmap_track_handle_t_db); + while (hdb_iterator_next(&cmap_track_handle_t_db, + (void*)&cmap_track_inst, &track_inst_handle) == 0) { + + if (cmap_track_inst->c == cmap_inst->c) { + (void)hdb_handle_destroy(&cmap_track_handle_t_db, track_inst_handle); + } + + (void)hdb_handle_put (&cmap_track_handle_t_db, track_inst_handle); + } + + (void)hdb_handle_destroy(&cmap_handle_t_db, handle); + + (void)hdb_handle_put(&cmap_handle_t_db, handle); + + return (CS_OK); +} + +cs_error_t cmap_fd_get(cmap_handle_t handle, int *fd) +{ + cs_error_t error; + struct cmap_inst *cmap_inst; + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + error = qb_to_cs_error (qb_ipcc_fd_get (cmap_inst->c, fd)); + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +cs_error_t cmap_dispatch ( + cmap_handle_t handle, + cs_dispatch_flags_t dispatch_types) +{ + int timeout = -1; + cs_error_t error; + int cont = 1; /* always continue do loop except when set to 0 */ + struct cmap_inst *cmap_inst; + struct qb_ipc_response_header *dispatch_data; + char dispatch_buf[IPC_DISPATCH_SIZE]; + struct res_lib_cmap_notify_callback *res_lib_cmap_notify_callback; + struct cmap_track_inst *cmap_track_inst; + struct cmap_notify_value old_val; + struct cmap_notify_value new_val; + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + /* + * Timeout instantly for CS_DISPATCH_ONE_NONBLOCKING or CS_DISPATCH_ALL and + * wait indefinately for CS_DISPATCH_ONE or CS_DISPATCH_BLOCKING + */ + if (dispatch_types == CS_DISPATCH_ALL || dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { + timeout = 0; + } + + dispatch_data = (struct qb_ipc_response_header *)dispatch_buf; + do { + error = qb_to_cs_error(qb_ipcc_event_recv ( + cmap_inst->c, + dispatch_buf, + IPC_DISPATCH_SIZE, + timeout)); + + if (error == CS_ERR_BAD_HANDLE) { + error = CS_OK; + goto error_put; + } + if (error == CS_ERR_TRY_AGAIN) { + if (dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { + /* + * Don't mask error + */ + goto error_put; + } + error = CS_OK; + if (dispatch_types == CS_DISPATCH_ALL) { + break; /* exit do while cont is 1 loop */ + } else { + continue; /* next poll */ + } + } + + if (error != CS_OK) { + goto error_put; + } + + /* + * Dispatch incoming message + */ + switch (dispatch_data->id) { + case MESSAGE_RES_CMAP_NOTIFY_CALLBACK: + res_lib_cmap_notify_callback = (struct res_lib_cmap_notify_callback *)dispatch_data; + + error = hdb_error_to_cs(hdb_handle_get(&cmap_track_handle_t_db, + res_lib_cmap_notify_callback->track_inst_handle, + (void *)&cmap_track_inst)); + if (error == CS_ERR_BAD_HANDLE) { + /* + * User deleted tracker -> ignore error + */ + break; + } + if (error != CS_OK) { + goto error_put; + } + + new_val.type = res_lib_cmap_notify_callback->new_value_type; + old_val.type = res_lib_cmap_notify_callback->old_value_type; + new_val.len = res_lib_cmap_notify_callback->new_value_len; + old_val.len = res_lib_cmap_notify_callback->old_value_len; + new_val.data = res_lib_cmap_notify_callback->new_value; + old_val.data = (((const char *)res_lib_cmap_notify_callback->new_value) + new_val.len); + + cmap_track_inst->notify_fn(handle, + cmap_track_inst->track_handle, + res_lib_cmap_notify_callback->event, + (char *)res_lib_cmap_notify_callback->key_name.value, + new_val, + old_val, + cmap_track_inst->user_data); + + (void)hdb_handle_put(&cmap_track_handle_t_db, res_lib_cmap_notify_callback->track_inst_handle); + break; + default: + error = CS_ERR_LIBRARY; + goto error_put; + break; + } + if (cmap_inst->finalize) { + /* + * If the finalize has been called then get out of the dispatch. + */ + error = CS_ERR_BAD_HANDLE; + goto error_put; + } + + /* + * Determine if more messages should be processed + */ + if (dispatch_types == CS_DISPATCH_ONE || dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { + cont = 0; + } + } while (cont); + +error_put: + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +cs_error_t cmap_context_get ( + cmap_handle_t handle, + const void **context) +{ + cs_error_t error; + struct cmap_inst *cmap_inst; + + error = hdb_error_to_cs(hdb_handle_get(&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + *context = cmap_inst->context; + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (CS_OK); +} + +cs_error_t cmap_context_set ( + cmap_handle_t handle, + const void *context) +{ + cs_error_t error; + struct cmap_inst *cmap_inst; + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + cmap_inst->context = context; + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (CS_OK); +} + +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) +{ + cs_error_t error; + struct iovec iov[2]; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_set req_lib_cmap_set; + struct res_lib_cmap_set res_lib_cmap_set; + + if (key_name == NULL || value == NULL) { + return (CS_ERR_INVALID_PARAM); + } + + if (strlen(key_name) >= CS_MAX_NAME_LENGTH) { + return (CS_ERR_NAME_TOO_LONG); + } + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_set, 0, sizeof(req_lib_cmap_set)); + req_lib_cmap_set.header.size = sizeof(req_lib_cmap_set) + value_len; + req_lib_cmap_set.header.id = MESSAGE_REQ_CMAP_SET; + + memcpy(req_lib_cmap_set.key_name.value, key_name, strlen(key_name)); + req_lib_cmap_set.key_name.length = strlen(key_name); + + req_lib_cmap_set.value_len = value_len; + req_lib_cmap_set.type = type; + + iov[0].iov_base = (char *)&req_lib_cmap_set; + iov[0].iov_len = sizeof(req_lib_cmap_set); + iov[1].iov_base = (void *)value; + iov[1].iov_len = value_len; + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + iov, + 2, + &res_lib_cmap_set, + sizeof (struct res_lib_cmap_set), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_set.header.error; + } + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +cs_error_t cmap_set_int8(cmap_handle_t handle, const char *key_name, int8_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_INT8)); +} + +cs_error_t cmap_set_uint8(cmap_handle_t handle, const char *key_name, uint8_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_UINT8)); +} + +cs_error_t cmap_set_int16(cmap_handle_t handle, const char *key_name, int16_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_INT16)); +} + +cs_error_t cmap_set_uint16(cmap_handle_t handle, const char *key_name, uint16_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_UINT16)); +} + +cs_error_t cmap_set_int32(cmap_handle_t handle, const char *key_name, int32_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_INT32)); +} + +cs_error_t cmap_set_uint32(cmap_handle_t handle, const char *key_name, uint32_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_UINT32)); +} + +cs_error_t cmap_set_int64(cmap_handle_t handle, const char *key_name, int64_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_INT64)); +} + +cs_error_t cmap_set_uint64(cmap_handle_t handle, const char *key_name, uint64_t value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_UINT64)); +} + +cs_error_t cmap_set_float(cmap_handle_t handle, const char *key_name, float value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_FLOAT)); +} + +cs_error_t cmap_set_double(cmap_handle_t handle, const char *key_name, double value) +{ + return (cmap_set(handle, key_name, &value, sizeof(value), CMAP_VALUETYPE_DOUBLE)); +} + +cs_error_t cmap_set_string(cmap_handle_t handle, const char *key_name, const char *value) +{ + + if (value == NULL) { + return (CS_ERR_INVALID_PARAM); + } + + return (cmap_set(handle, key_name, value, strlen(value), CMAP_VALUETYPE_STRING)); +} + +cs_error_t cmap_delete(cmap_handle_t handle, const char *key_name) +{ + cs_error_t error; + struct iovec iov; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_delete req_lib_cmap_delete; + struct res_lib_cmap_delete res_lib_cmap_delete; + + if (key_name == NULL) { + return (CS_ERR_INVALID_PARAM); + } + if (strlen(key_name) >= CS_MAX_NAME_LENGTH) { + return (CS_ERR_NAME_TOO_LONG); + } + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_delete, 0, sizeof(req_lib_cmap_delete)); + req_lib_cmap_delete.header.size = sizeof(req_lib_cmap_delete); + req_lib_cmap_delete.header.id = MESSAGE_REQ_CMAP_DELETE; + + memcpy(req_lib_cmap_delete.key_name.value, key_name, strlen(key_name)); + req_lib_cmap_delete.key_name.length = strlen(key_name); + + iov.iov_base = (char *)&req_lib_cmap_delete; + iov.iov_len = sizeof(req_lib_cmap_delete); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + &res_lib_cmap_delete, + sizeof (struct res_lib_cmap_delete), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_delete.header.error; + } + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +cs_error_t cmap_get( + cmap_handle_t handle, + const char *key_name, + void *value, + size_t *value_len, + cmap_value_types_t *type) +{ + cs_error_t error; + struct cmap_inst *cmap_inst; + struct iovec iov; + struct req_lib_cmap_get req_lib_cmap_get; + struct res_lib_cmap_get *res_lib_cmap_get; + size_t res_size; + + if (key_name == NULL) { + return (CS_ERR_INVALID_PARAM); + } + if (strlen(key_name) >= CS_MAX_NAME_LENGTH) { + return (CS_ERR_NAME_TOO_LONG); + } + + if (value != NULL && value_len == NULL) { + return (CS_ERR_INVALID_PARAM); + } + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_get, 0, sizeof(req_lib_cmap_get)); + req_lib_cmap_get.header.size = sizeof(req_lib_cmap_get); + req_lib_cmap_get.header.id = MESSAGE_REQ_CMAP_GET; + + memcpy(req_lib_cmap_get.key_name.value, key_name, strlen(key_name)); + req_lib_cmap_get.key_name.length = strlen(key_name); + + if (value != NULL && value_len != NULL) { + req_lib_cmap_get.value_len = *value_len; + } else { + req_lib_cmap_get.value_len = 0; + } + + iov.iov_base = (char *)&req_lib_cmap_get; + iov.iov_len = sizeof(req_lib_cmap_get); + + res_size = sizeof(struct res_lib_cmap_get) + req_lib_cmap_get.value_len; + + res_lib_cmap_get = malloc(res_size); + if (res_lib_cmap_get == NULL) { + return (CS_ERR_NO_MEMORY); + } + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + res_lib_cmap_get, + res_size, CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_get->header.error; + } + + if (error == CS_OK) { + if (type != NULL) { + *type = res_lib_cmap_get->type; + } + + if (value_len != NULL) { + *value_len = res_lib_cmap_get->value_len; + } + + if (value != NULL && value_len != NULL) { + memcpy(value, res_lib_cmap_get->value, res_lib_cmap_get->value_len); + } + } + + free(res_lib_cmap_get); + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +static cs_error_t cmap_get_int( + cmap_handle_t handle, + const char *key_name, + void *value, + size_t value_size, + cmap_value_types_t type) +{ + char key_value[16]; + size_t key_size; + cs_error_t err; + + cmap_value_types_t key_type; + + key_size = sizeof(key_value); + memset(key_value, 0, key_size); + + err = cmap_get(handle, 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, value_size); + + return (CS_OK); +} + +cs_error_t cmap_get_int8(cmap_handle_t handle, const char *key_name, int8_t *i8) +{ + + return (cmap_get_int(handle, key_name, i8, sizeof(*i8), CMAP_VALUETYPE_INT8)); +} + +cs_error_t cmap_get_uint8(cmap_handle_t handle, const char *key_name, uint8_t *u8) +{ + + return (cmap_get_int(handle, key_name, u8, sizeof(*u8), CMAP_VALUETYPE_UINT8)); +} + +cs_error_t cmap_get_int16(cmap_handle_t handle, const char *key_name, int16_t *i16) +{ + + return (cmap_get_int(handle, key_name, i16, sizeof(*i16), CMAP_VALUETYPE_INT16)); +} + +cs_error_t cmap_get_uint16(cmap_handle_t handle, const char *key_name, uint16_t *u16) +{ + + return (cmap_get_int(handle, key_name, u16, sizeof(*u16), CMAP_VALUETYPE_UINT16)); +} + +cs_error_t cmap_get_int32(cmap_handle_t handle, const char *key_name, int32_t *i32) +{ + + return (cmap_get_int(handle, key_name, i32, sizeof(*i32), CMAP_VALUETYPE_INT32)); +} + +cs_error_t cmap_get_uint32(cmap_handle_t handle, const char *key_name, uint32_t *u32) +{ + + return (cmap_get_int(handle, key_name, u32, sizeof(*u32), CMAP_VALUETYPE_UINT32)); +} + +cs_error_t cmap_get_int64(cmap_handle_t handle, const char *key_name, int64_t *i64) +{ + + return (cmap_get_int(handle, key_name, i64, sizeof(*i64), CMAP_VALUETYPE_INT64)); +} + +cs_error_t cmap_get_uint64(cmap_handle_t handle, const char *key_name, uint64_t *u64) +{ + + return (cmap_get_int(handle, key_name, u64, sizeof(*u64), CMAP_VALUETYPE_UINT64)); +} + +cs_error_t cmap_get_float(cmap_handle_t handle, const char *key_name, float *flt) +{ + + return (cmap_get_int(handle, key_name, flt, sizeof(*flt), CMAP_VALUETYPE_FLOAT)); +} + +cs_error_t cmap_get_double(cmap_handle_t handle, const char *key_name, double *dbl) +{ + + return (cmap_get_int(handle, key_name, dbl, sizeof(*dbl), CMAP_VALUETYPE_DOUBLE)); +} + +cs_error_t cmap_get_string(cmap_handle_t handle, const char *key_name, char **str) +{ + cs_error_t res; + size_t str_len; + cmap_value_types_t type; + + res = cmap_get(handle, key_name, NULL, &str_len, &type); + + if (res != CS_OK || type != CMAP_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 = cmap_get(handle, key_name, *str, &str_len, &type); + if (res != CS_OK) { + free(*str); + + goto return_error; + } + + return (CS_OK); + +return_error: + return (res); +} + +static cs_error_t cmap_adjust_int(cmap_handle_t handle, const char *key_name, int32_t step) +{ + cs_error_t error; + struct iovec iov; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_adjust_int req_lib_cmap_adjust_int; + struct res_lib_cmap_adjust_int res_lib_cmap_adjust_int; + + if (key_name == NULL) { + return (CS_ERR_INVALID_PARAM); + } + if (strlen(key_name) >= CS_MAX_NAME_LENGTH) { + return (CS_ERR_NAME_TOO_LONG); + } + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_adjust_int, 0, sizeof(req_lib_cmap_adjust_int)); + req_lib_cmap_adjust_int.header.size = sizeof(req_lib_cmap_adjust_int); + req_lib_cmap_adjust_int.header.id = MESSAGE_REQ_CMAP_ADJUST_INT; + + memcpy(req_lib_cmap_adjust_int.key_name.value, key_name, strlen(key_name)); + req_lib_cmap_adjust_int.key_name.length = strlen(key_name); + + req_lib_cmap_adjust_int.step = step; + + iov.iov_base = (char *)&req_lib_cmap_adjust_int; + iov.iov_len = sizeof(req_lib_cmap_adjust_int); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + &res_lib_cmap_adjust_int, + sizeof (struct res_lib_cmap_adjust_int), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_adjust_int.header.error; + } + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +cs_error_t cmap_inc(cmap_handle_t handle, const char *key_name) +{ + + return (cmap_adjust_int(handle, key_name, 1)); +} + +cs_error_t cmap_dec(cmap_handle_t handle, const char *key_name) +{ + + return (cmap_adjust_int(handle, key_name, -1)); +} + +cs_error_t cmap_iter_init( + cmap_handle_t handle, + const char *prefix, + cmap_iter_handle_t *cmap_iter_handle) +{ + cs_error_t error; + struct iovec iov; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_iter_init req_lib_cmap_iter_init; + struct res_lib_cmap_iter_init res_lib_cmap_iter_init; + + if (cmap_iter_handle == NULL) { + return (CS_ERR_INVALID_PARAM); + } + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_iter_init, 0, sizeof(req_lib_cmap_iter_init)); + req_lib_cmap_iter_init.header.size = sizeof(req_lib_cmap_iter_init); + req_lib_cmap_iter_init.header.id = MESSAGE_REQ_CMAP_ITER_INIT; + + if (prefix) { + if (strlen(prefix) >= CS_MAX_NAME_LENGTH) { + return (CS_ERR_NAME_TOO_LONG); + } + memcpy(req_lib_cmap_iter_init.prefix.value, prefix, strlen(prefix)); + req_lib_cmap_iter_init.prefix.length = strlen(prefix); + } + + iov.iov_base = (char *)&req_lib_cmap_iter_init; + iov.iov_len = sizeof(req_lib_cmap_iter_init); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + &res_lib_cmap_iter_init, + sizeof (struct res_lib_cmap_iter_init), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_iter_init.header.error; + } + + if (error == CS_OK) { + *cmap_iter_handle = res_lib_cmap_iter_init.iter_handle; + } + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +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) +{ + cs_error_t error; + struct iovec iov; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_iter_next req_lib_cmap_iter_next; + struct res_lib_cmap_iter_next res_lib_cmap_iter_next; + + if (key_name == NULL) { + return (CS_ERR_INVALID_PARAM); + } + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_iter_next, 0, sizeof(req_lib_cmap_iter_next)); + req_lib_cmap_iter_next.header.size = sizeof(req_lib_cmap_iter_next); + req_lib_cmap_iter_next.header.id = MESSAGE_REQ_CMAP_ITER_NEXT; + req_lib_cmap_iter_next.iter_handle = iter_handle; + + iov.iov_base = (char *)&req_lib_cmap_iter_next; + iov.iov_len = sizeof(req_lib_cmap_iter_next); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + &res_lib_cmap_iter_next, + sizeof (struct res_lib_cmap_iter_next), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_iter_next.header.error; + } + + if (error == CS_OK) { + memcpy(key_name, (const char *)res_lib_cmap_iter_next.key_name.value, + res_lib_cmap_iter_next.key_name.length); + key_name[res_lib_cmap_iter_next.key_name.length] = '\0'; + + if (value_len != NULL) { + *value_len = res_lib_cmap_iter_next.value_len; + } + + if (type != NULL) { + *type = res_lib_cmap_iter_next.type; + } + } + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +cs_error_t cmap_iter_finalize( + cmap_handle_t handle, + cmap_iter_handle_t iter_handle) +{ + cs_error_t error; + struct iovec iov; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_iter_finalize req_lib_cmap_iter_finalize; + struct res_lib_cmap_iter_finalize res_lib_cmap_iter_finalize; + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_iter_finalize, 0, sizeof(req_lib_cmap_iter_finalize)); + req_lib_cmap_iter_finalize.header.size = sizeof(req_lib_cmap_iter_finalize); + req_lib_cmap_iter_finalize.header.id = MESSAGE_REQ_CMAP_ITER_FINALIZE; + req_lib_cmap_iter_finalize.iter_handle = iter_handle; + + iov.iov_base = (char *)&req_lib_cmap_iter_finalize; + iov.iov_len = sizeof(req_lib_cmap_iter_finalize); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + &res_lib_cmap_iter_finalize, + sizeof (struct res_lib_cmap_iter_finalize), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_iter_finalize.header.error; + } + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +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) +{ + cs_error_t error; + struct iovec iov; + struct cmap_inst *cmap_inst; + struct req_lib_cmap_track_add req_lib_cmap_track_add; + struct res_lib_cmap_track_add res_lib_cmap_track_add; + struct cmap_track_inst *cmap_track_inst; + cmap_track_handle_t cmap_track_inst_handle; + + if (cmap_track_handle == NULL || notify_fn == NULL) { + return (CS_ERR_INVALID_PARAM); + } + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + error = hdb_error_to_cs(hdb_handle_create(&cmap_track_handle_t_db, + sizeof(*cmap_track_inst), &cmap_track_inst_handle)); + if (error != CS_OK) { + goto error_put; + } + + error = hdb_error_to_cs(hdb_handle_get(&cmap_track_handle_t_db, + cmap_track_inst_handle, (void *)&cmap_track_inst)); + if (error != CS_OK) { + goto error_put_destroy; + } + + cmap_track_inst->user_data = user_data; + cmap_track_inst->notify_fn = notify_fn; + cmap_track_inst->c = cmap_inst->c; + + memset(&req_lib_cmap_track_add, 0, sizeof(req_lib_cmap_track_add)); + req_lib_cmap_track_add.header.size = sizeof(req_lib_cmap_track_add); + req_lib_cmap_track_add.header.id = MESSAGE_REQ_CMAP_TRACK_ADD; + + if (key_name) { + if (strlen(key_name) >= CS_MAX_NAME_LENGTH) { + return (CS_ERR_NAME_TOO_LONG); + } + memcpy(req_lib_cmap_track_add.key_name.value, key_name, strlen(key_name)); + req_lib_cmap_track_add.key_name.length = strlen(key_name); + } + + req_lib_cmap_track_add.track_type = track_type; + req_lib_cmap_track_add.track_inst_handle = cmap_track_inst_handle; + + iov.iov_base = (char *)&req_lib_cmap_track_add; + iov.iov_len = sizeof(req_lib_cmap_track_add); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + &res_lib_cmap_track_add, + sizeof (struct res_lib_cmap_track_add), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_track_add.header.error; + } + + if (error == CS_OK) { + *cmap_track_handle = res_lib_cmap_track_add.track_handle; + cmap_track_inst->track_handle = *cmap_track_handle; + } + + (void)hdb_handle_put (&cmap_track_handle_t_db, cmap_track_inst_handle); + + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); + +error_put_destroy: + (void)hdb_handle_put (&cmap_track_handle_t_db, cmap_track_inst_handle); + (void)hdb_handle_destroy (&cmap_track_handle_t_db, cmap_track_inst_handle); + +error_put: + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} + +cs_error_t cmap_track_delete( + cmap_handle_t handle, + cmap_track_handle_t track_handle) +{ + cs_error_t error; + struct iovec iov; + struct cmap_inst *cmap_inst; + struct cmap_track_inst *cmap_track_inst; + struct req_lib_cmap_track_delete req_lib_cmap_track_delete; + struct res_lib_cmap_track_delete res_lib_cmap_track_delete; + + error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); + if (error != CS_OK) { + return (error); + } + + memset(&req_lib_cmap_track_delete, 0, sizeof(req_lib_cmap_track_delete)); + req_lib_cmap_track_delete.header.size = sizeof(req_lib_cmap_track_delete); + req_lib_cmap_track_delete.header.id = MESSAGE_REQ_CMAP_TRACK_DELETE; + req_lib_cmap_track_delete.track_handle = track_handle; + + iov.iov_base = (char *)&req_lib_cmap_track_delete; + iov.iov_len = sizeof(req_lib_cmap_track_delete); + + error = qb_to_cs_error(qb_ipcc_sendv_recv( + cmap_inst->c, + &iov, + 1, + &res_lib_cmap_track_delete, + sizeof (struct res_lib_cmap_track_delete), CS_IPC_TIMEOUT_MS)); + + if (error == CS_OK) { + error = res_lib_cmap_track_delete.header.error; + } + + if (error == CS_OK) { + error = hdb_error_to_cs(hdb_handle_get(&cmap_track_handle_t_db, + res_lib_cmap_track_delete.track_inst_handle, + (void *)&cmap_track_inst)); + if (error != CS_OK) { + goto error_put; + } + + (void)hdb_handle_put(&cmap_track_handle_t_db, res_lib_cmap_track_delete.track_inst_handle); + (void)hdb_handle_destroy(&cmap_track_handle_t_db, res_lib_cmap_track_delete.track_inst_handle); + } + +error_put: + (void)hdb_handle_put (&cmap_handle_t_db, handle); + + return (error); +} |