/* * Copyright (c) 2008-2010 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@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 MontaVista Software, 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. */ /* * Provides access to data in the corosync object database */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "sa-confdb.h" #undef MIN #define MIN(x,y) ((x) < (y) ? (x) : (y)) /* Hold the information for iterators so that callers can do recursive tree traversals. each object_handle can have its own iterator */ struct iter_context { struct list_head list; hdb_handle_t parent_object_handle; hdb_handle_t find_handle; hdb_handle_t next_entry; }; struct confdb_inst { hdb_handle_t handle; int finalize; int standalone; confdb_callbacks_t callbacks; const void *context; struct list_head object_find_head; struct list_head object_iter_head; struct list_head key_iter_head; }; DECLARE_HDB_DATABASE(confdb_handle_t_db,NULL); static cs_error_t do_find_destroy(struct confdb_inst *confdb_inst, hdb_handle_t find_handle); /* Safely tidy one iterator context list */ static void free_context_list(struct confdb_inst *confdb_inst, struct list_head *list) { struct iter_context *context; struct list_head *iter, *tmp; for (iter = list->next, tmp = iter->next; iter != list; iter = tmp, tmp = iter->next) { context = list_entry (iter, struct iter_context, list); (void)do_find_destroy(confdb_inst, context->find_handle); free(context); } } static struct iter_context *find_iter_context(struct list_head *list, hdb_handle_t object_handle) { struct iter_context *context; struct list_head *iter; for (iter = list->next; iter != list; iter = iter->next) { context = list_entry (iter, struct iter_context, list); if (context->parent_object_handle == object_handle) return context; } return NULL; } /** * @defgroup confdb_corosync * @ingroup corosync * * @{ */ cs_error_t confdb_initialize ( confdb_handle_t *handle, confdb_callbacks_t *callbacks) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_create (&confdb_handle_t_db, sizeof (struct confdb_inst), handle)); if (error != CS_OK) { goto error_no_destroy; } error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, *handle, (void *)&confdb_inst)); if (error != CS_OK) { goto error_destroy; } if (getenv("COROSYNC_DEFAULT_CONFIG_IFACE")) { error = confdb_sa_init(); confdb_inst->standalone = 1; } else { error = coroipcc_service_connect ( COROSYNC_SOCKET_NAME, CONFDB_SERVICE, IPC_REQUEST_SIZE, IPC_RESPONSE_SIZE, IPC_DISPATCH_SIZE, &confdb_inst->handle); } if (error != CS_OK) goto error_put_destroy; if (callbacks) { memcpy (&confdb_inst->callbacks, callbacks, sizeof (confdb_callbacks_t)); } list_init (&confdb_inst->object_find_head); list_init (&confdb_inst->object_iter_head); list_init (&confdb_inst->key_iter_head); (void)hdb_handle_put (&confdb_handle_t_db, *handle); return (CS_OK); error_put_destroy: (void)hdb_handle_put (&confdb_handle_t_db, *handle); error_destroy: (void)hdb_handle_destroy (&confdb_handle_t_db, *handle); error_no_destroy: return (error); } cs_error_t confdb_finalize ( confdb_handle_t handle) { struct confdb_inst *confdb_inst; cs_error_t error; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* * Another thread has already started finalizing */ if (confdb_inst->finalize) { (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_ERR_BAD_HANDLE); } confdb_inst->finalize = 1; /* Free saved context handles */ free_context_list(confdb_inst, &confdb_inst->object_find_head); free_context_list(confdb_inst, &confdb_inst->object_iter_head); free_context_list(confdb_inst, &confdb_inst->key_iter_head); if (!confdb_inst->standalone) { coroipcc_service_disconnect (confdb_inst->handle); } (void)hdb_handle_destroy (&confdb_handle_t_db, handle); (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_fd_get ( confdb_handle_t handle, int *fd) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } error = coroipcc_fd_get (confdb_inst->handle, fd); (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_context_get ( confdb_handle_t handle, const void **context) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } *context = confdb_inst->context; (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_context_set ( confdb_handle_t handle, const void *context) { cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } confdb_inst->context = context; (void)hdb_handle_put (&confdb_handle_t_db, handle); return (CS_OK); } cs_error_t confdb_dispatch ( confdb_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 confdb_inst *confdb_inst; confdb_callbacks_t callbacks; struct res_lib_confdb_key_change_callback *res_key_changed_pt; struct res_lib_confdb_object_create_callback *res_object_created_pt; struct res_lib_confdb_object_destroy_callback *res_object_destroyed_pt; struct res_lib_confdb_reload_callback *res_reload_pt; coroipc_response_header_t *dispatch_data; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_put; } /* * Timeout instantly for CS_DISPATCH_ONE or CS_DISPATCH_ALL and * wait indefinitely for CS_DISPATCH_BLOCKING */ if (dispatch_types == CONFDB_DISPATCH_ALL) { timeout = 0; } do { error = coroipcc_dispatch_get ( confdb_inst->handle, (void **)&dispatch_data, timeout); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { error = CS_OK; if (dispatch_types == CONFDB_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that confdbFinalize has been called. */ memcpy (&callbacks, &confdb_inst->callbacks, sizeof (confdb_callbacks_t)); /* * Dispatch incoming message */ switch (dispatch_data->id) { case MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK: if (callbacks.confdb_key_change_notify_fn == NULL) { break; } res_key_changed_pt = (struct res_lib_confdb_key_change_callback *)dispatch_data; callbacks.confdb_key_change_notify_fn(handle, res_key_changed_pt->change_type, res_key_changed_pt->object_handle, res_key_changed_pt->parent_object_handle, res_key_changed_pt->object_name.value, res_key_changed_pt->object_name.length, res_key_changed_pt->key_name.value, res_key_changed_pt->key_name.length, res_key_changed_pt->key_value.value, res_key_changed_pt->key_value.length); break; case MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK: if (callbacks.confdb_object_create_change_notify_fn == NULL) { break; } res_object_created_pt = (struct res_lib_confdb_object_create_callback *)dispatch_data; callbacks.confdb_object_create_change_notify_fn(handle, res_object_created_pt->object_handle, res_object_created_pt->parent_object_handle, res_object_created_pt->name.value, res_object_created_pt->name.length); break; case MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK: if (callbacks.confdb_object_delete_change_notify_fn == NULL) { break; } res_object_destroyed_pt = (struct res_lib_confdb_object_destroy_callback *)dispatch_data; callbacks.confdb_object_delete_change_notify_fn(handle, res_object_destroyed_pt->parent_object_handle, res_object_destroyed_pt->name.value, res_object_destroyed_pt->name.length); break; case MESSAGE_RES_CONFDB_RELOAD_CALLBACK: if (callbacks.confdb_reload_notify_fn == NULL) { break; } res_reload_pt = (struct res_lib_confdb_reload_callback *)dispatch_data; callbacks.confdb_reload_notify_fn(handle, res_reload_pt->type); break; default: coroipcc_dispatch_put (confdb_inst->handle); error = CS_ERR_LIBRARY; goto error_noput; break; } coroipcc_dispatch_put (confdb_inst->handle); /* * Determine if more messages should be processed */ if (dispatch_types == CS_DISPATCH_ONE) { cont = 0; } } while (cont); error_put: (void)hdb_handle_put (&confdb_handle_t_db, handle); error_noput: return (error); } cs_error_t confdb_object_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_create req_lib_confdb_object_create; struct res_lib_confdb_object_create res_lib_confdb_object_create; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_create(parent_object_handle, object_name, object_name_len, object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_create.header.size = sizeof (struct req_lib_confdb_object_create); req_lib_confdb_object_create.header.id = MESSAGE_REQ_CONFDB_OBJECT_CREATE; req_lib_confdb_object_create.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_object_create.object_name.value, object_name, object_name_len); req_lib_confdb_object_create.object_name.length = object_name_len; iov.iov_base = (char *)&req_lib_confdb_object_create; iov.iov_len = sizeof (struct req_lib_confdb_object_create); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_create, sizeof (struct res_lib_confdb_object_create)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_create.header.error; *object_handle = res_lib_confdb_object_create.object_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_destroy ( confdb_handle_t handle, hdb_handle_t object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_destroy req_lib_confdb_object_destroy; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_destroy(object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_destroy.header.size = sizeof (struct req_lib_confdb_object_destroy); req_lib_confdb_object_destroy.header.id = MESSAGE_REQ_CONFDB_OBJECT_DESTROY; req_lib_confdb_object_destroy.object_handle = object_handle; iov.iov_base = (char *)&req_lib_confdb_object_destroy; iov.iov_len = sizeof (struct req_lib_confdb_object_destroy); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_parent_get ( confdb_handle_t handle, hdb_handle_t object_handle, hdb_handle_t *parent_object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_parent_get req_lib_confdb_object_parent_get; struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_parent_get(object_handle, parent_object_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_parent_get.header.size = sizeof (struct req_lib_confdb_object_parent_get); req_lib_confdb_object_parent_get.header.id = MESSAGE_REQ_CONFDB_OBJECT_PARENT_GET; req_lib_confdb_object_parent_get.object_handle = object_handle; iov.iov_base = (char *)&req_lib_confdb_object_parent_get; iov.iov_len = sizeof (struct req_lib_confdb_object_parent_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_parent_get, sizeof (struct res_lib_confdb_object_parent_get)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_parent_get.header.error; *parent_object_handle = res_lib_confdb_object_parent_get.parent_object_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } static cs_error_t do_find_destroy( struct confdb_inst *confdb_inst, hdb_handle_t find_handle) { cs_error_t error; struct iovec iov; struct req_lib_confdb_object_find_destroy req_lib_confdb_object_find_destroy; coroipc_response_header_t res; if (!find_handle) return CS_OK; if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_find_destroy(find_handle)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_find_destroy.header.size = sizeof (struct req_lib_confdb_object_find_destroy); req_lib_confdb_object_find_destroy.header.id = MESSAGE_REQ_CONFDB_OBJECT_FIND_DESTROY; req_lib_confdb_object_find_destroy.find_handle = find_handle; iov.iov_base = (char *)&req_lib_confdb_object_find_destroy; iov.iov_len = sizeof (struct req_lib_confdb_object_find_destroy); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: return (error); } cs_error_t confdb_object_find_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct iter_context *context; cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); error = do_find_destroy(confdb_inst, context->find_handle); if (error == CS_OK) { list_del(&context->list); free(context); } (void)hdb_handle_put (&confdb_handle_t_db, handle); return error; } cs_error_t confdb_object_iter_destroy( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct iter_context *context; cs_error_t error; struct confdb_inst *confdb_inst; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle); error = do_find_destroy(confdb_inst, context->find_handle); if (error == CS_OK) { list_del(&context->list); free(context); } (void)hdb_handle_put (&confdb_handle_t_db, handle); return error; } cs_error_t confdb_key_create ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_create req_lib_confdb_key_create; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_create(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_create.header.size = sizeof (struct req_lib_confdb_key_create); req_lib_confdb_key_create.header.id = MESSAGE_REQ_CONFDB_KEY_CREATE; req_lib_confdb_key_create.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_create.key_name.value, key_name, key_name_len); req_lib_confdb_key_create.key_name.length = key_name_len; memcpy(req_lib_confdb_key_create.value.value, value, value_len); req_lib_confdb_key_create.value.length = value_len; iov.iov_base = (char *)&req_lib_confdb_key_create; iov.iov_len = sizeof (struct req_lib_confdb_key_create); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_create_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, const void *value, size_t value_len, confdb_value_types_t type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_create_typed request; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_create_typed(parent_object_handle, key_name, value, value_len, type)) error = CS_ERR_ACCESS; goto error_exit; } request.header.size = sizeof (struct req_lib_confdb_key_create_typed); request.header.id = MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED; request.object_handle = parent_object_handle; request.key_name.length = strlen(key_name)+1; memcpy(request.key_name.value, key_name, request.key_name.length); memcpy(request.value.value, value, value_len); request.value.length = value_len; request.type = type; iov.iov_base = (char *)&request; iov.iov_len = sizeof (struct req_lib_confdb_key_create_typed); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_delete ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_delete req_lib_confdb_key_delete; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_delete(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_delete.header.size = sizeof (struct req_lib_confdb_key_delete); req_lib_confdb_key_delete.header.id = MESSAGE_REQ_CONFDB_KEY_DELETE; req_lib_confdb_key_delete.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_delete.key_name.value, key_name, key_name_len); req_lib_confdb_key_delete.key_name.length = key_name_len; memcpy(req_lib_confdb_key_delete.value.value, value, value_len); req_lib_confdb_key_delete.value.length = value_len; iov.iov_base = (char *)&req_lib_confdb_key_delete; iov.iov_len = sizeof (struct req_lib_confdb_key_delete); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_get ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, void *value, size_t *value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_get res_lib_confdb_key_get; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_get(parent_object_handle, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_get, sizeof (struct res_lib_confdb_key_get)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_get.header.error; if (error == CS_OK) { *value_len = res_lib_confdb_key_get.value.length; memcpy(value, res_lib_confdb_key_get.value.value, *value_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_get_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const char *key_name, void *value, size_t *value_len, confdb_value_types_t *type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_get_typed response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_get_typed(parent_object_handle, key_name, value, value_len, (int*)type)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET_TYPED; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; req_lib_confdb_key_get.key_name.length = strlen(key_name) + 1; memcpy(req_lib_confdb_key_get.key_name.value, key_name, req_lib_confdb_key_get.key_name.length); iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &response, sizeof (struct res_lib_confdb_key_get_typed)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { *value_len = response.value.length; *type = response.type; memcpy(value, response.value.value, *value_len); } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_increment ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_increment(parent_object_handle, key_name, key_name_len, value)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_INCREMENT; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_incdec.header.error; if (error == CS_OK) { *value = res_lib_confdb_key_incdec.value; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_decrement ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_get req_lib_confdb_key_get; struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_decrement(parent_object_handle, key_name, key_name_len, value)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get); req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_DECREMENT; req_lib_confdb_key_get.parent_object_handle = parent_object_handle; memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len); req_lib_confdb_key_get.key_name.length = key_name_len; iov.iov_base = (char *)&req_lib_confdb_key_get; iov.iov_len = sizeof (struct req_lib_confdb_key_get); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_incdec.header.error; if (error == CS_OK) { *value = res_lib_confdb_key_incdec.value; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_replace ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *old_value, size_t old_value_len, const void *new_value, size_t new_value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_key_replace req_lib_confdb_key_replace; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_replace(parent_object_handle, key_name, key_name_len, old_value, old_value_len, new_value, new_value_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_key_replace.header.size = sizeof (struct req_lib_confdb_key_replace); req_lib_confdb_key_replace.header.id = MESSAGE_REQ_CONFDB_KEY_REPLACE; req_lib_confdb_key_replace.object_handle = parent_object_handle; memcpy(req_lib_confdb_key_replace.key_name.value, key_name, key_name_len); req_lib_confdb_key_replace.key_name.length = key_name_len; memcpy(req_lib_confdb_key_replace.old_value.value, old_value, old_value_len); req_lib_confdb_key_replace.old_value.length = old_value_len; memcpy(req_lib_confdb_key_replace.new_value.value, new_value, new_value_len); req_lib_confdb_key_replace.new_value.length = new_value_len; iov.iov_base = (char *)&req_lib_confdb_key_replace; iov.iov_len = sizeof (struct req_lib_confdb_key_replace); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (res)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_iter_start ( confdb_handle_t handle, hdb_handle_t object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_iter_head, object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->parent_object_handle = object_handle; context->find_handle = 0; list_add(&context->list, &confdb_inst->object_iter_head); } /* Start a new find context */ if (context->find_handle) { (void)do_find_destroy(confdb_inst, context->find_handle); context->find_handle = 0; } (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_key_iter_start ( confdb_handle_t handle, hdb_handle_t object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->key_iter_head, object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->parent_object_handle = object_handle; list_add(&context->list, &confdb_inst->key_iter_head); } context->find_handle = 0; context->next_entry = 0; (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_object_find_start ( confdb_handle_t handle, hdb_handle_t parent_object_handle) { struct confdb_inst *confdb_inst; cs_error_t error = CS_OK; struct iter_context *context; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); if (!context) { context = malloc(sizeof(struct iter_context)); if (!context) { error = CS_ERR_NO_MEMORY; goto ret; } context->find_handle = 0; context->parent_object_handle = parent_object_handle; list_add(&context->list, &confdb_inst->object_find_head); } /* Start a new find context */ if (context->find_handle) { (void)do_find_destroy(confdb_inst, context->find_handle); context->find_handle = 0; } (void)hdb_handle_put (&confdb_handle_t_db, handle); ret: return error; } cs_error_t confdb_object_find ( confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_object_find req_lib_confdb_object_find; struct res_lib_confdb_object_find res_lib_confdb_object_find; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_object_find_start first */ context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_object_find(parent_object_handle, &context->find_handle, object_handle, object_name, object_name_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_object_find.header.size = sizeof (struct req_lib_confdb_object_find); req_lib_confdb_object_find.header.id = MESSAGE_REQ_CONFDB_OBJECT_FIND; req_lib_confdb_object_find.parent_object_handle = parent_object_handle; req_lib_confdb_object_find.find_handle = context->find_handle; memcpy(req_lib_confdb_object_find.object_name.value, object_name, object_name_len); req_lib_confdb_object_find.object_name.length = object_name_len; iov.iov_base = (char *)&req_lib_confdb_object_find; iov.iov_len = sizeof (struct req_lib_confdb_object_find); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_find, sizeof (struct res_lib_confdb_object_find)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_find.header.error; *object_handle = res_lib_confdb_object_find.object_handle; context->find_handle = res_lib_confdb_object_find.find_handle; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_object_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, void *object_name, size_t *object_name_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_object_iter req_lib_confdb_object_iter; struct res_lib_confdb_object_iter res_lib_confdb_object_iter; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_object_iter_start first */ context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; *object_name_len = 0; if (confdb_sa_object_iter(parent_object_handle, &context->find_handle, object_handle, NULL, 0, object_name, object_name_len)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_object_iter.header.size = sizeof (struct req_lib_confdb_object_iter); req_lib_confdb_object_iter.header.id = MESSAGE_REQ_CONFDB_OBJECT_ITER; req_lib_confdb_object_iter.parent_object_handle = parent_object_handle; req_lib_confdb_object_iter.find_handle = context->find_handle; iov.iov_base = (char *)&req_lib_confdb_object_iter; iov.iov_len = sizeof (struct req_lib_confdb_object_iter); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_object_iter, sizeof (struct res_lib_confdb_object_iter)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_object_iter.header.error; if (error == CS_OK) { *object_name_len = res_lib_confdb_object_iter.object_name.length; memcpy(object_name, res_lib_confdb_object_iter.object_name.value, *object_name_len); *object_handle = res_lib_confdb_object_iter.object_handle; context->find_handle = res_lib_confdb_object_iter.find_handle; } sa_exit: error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_iter ( confdb_handle_t handle, hdb_handle_t parent_object_handle, void *key_name, size_t *key_name_len, void *value, size_t *value_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_key_iter req_lib_confdb_key_iter; struct res_lib_confdb_key_iter res_lib_confdb_key_iter; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_key_iter_start first */ context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_iter(parent_object_handle, context->next_entry, key_name, key_name_len, value, value_len)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter); req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER; req_lib_confdb_key_iter.parent_object_handle = parent_object_handle; req_lib_confdb_key_iter.next_entry= context->next_entry; iov.iov_base = (char *)&req_lib_confdb_key_iter; iov.iov_len = sizeof (struct req_lib_confdb_key_iter); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_key_iter, sizeof (struct res_lib_confdb_key_iter)); if (error != CS_OK) { goto error_exit; } error = res_lib_confdb_key_iter.header.error; if (error == CS_OK) { char* key_name_str = (char*)key_name; *key_name_len = res_lib_confdb_key_iter.key_name.length; memcpy(key_name, res_lib_confdb_key_iter.key_name.value, *key_name_len); key_name_str[res_lib_confdb_key_iter.key_name.length] = '\0'; *value_len = res_lib_confdb_key_iter.value.length; memcpy(value, res_lib_confdb_key_iter.value.value, *value_len); } sa_exit: context->next_entry++; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_key_iter_typed ( confdb_handle_t handle, hdb_handle_t parent_object_handle, char *key_name, void *value, size_t *value_len, confdb_value_types_t *type) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct iter_context *context; struct req_lib_confdb_key_iter req_lib_confdb_key_iter; struct res_lib_confdb_key_iter_typed response; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } /* You MUST call confdb_key_iter_start first */ context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle); if (!context) { error = CS_ERR_CONTEXT_NOT_FOUND; goto error_exit; } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_key_iter_typed(parent_object_handle, context->next_entry, key_name, value, value_len, (int*)type)) error = CS_ERR_ACCESS; goto sa_exit; } req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter); req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER_TYPED; req_lib_confdb_key_iter.parent_object_handle = parent_object_handle; req_lib_confdb_key_iter.next_entry= context->next_entry; iov.iov_base = (char *)&req_lib_confdb_key_iter; iov.iov_len = sizeof (struct req_lib_confdb_key_iter); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &response, sizeof (struct res_lib_confdb_key_iter_typed)); if (error != CS_OK) { goto error_exit; } error = response.header.error; if (error == CS_OK) { memcpy(key_name, response.key_name.value, response.key_name.length); key_name[response.key_name.length] = '\0'; *value_len = response.value.length; memcpy(value, response.value.value, *value_len); *type = response.type; } sa_exit: context->next_entry++; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_write ( confdb_handle_t handle, char *error_text, size_t errbuf_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; coroipc_request_header_t req; struct res_lib_confdb_write res_lib_confdb_write; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { /* FIXME: set error_text */ return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_write(error_text, errbuf_len)) error = CS_ERR_ACCESS; goto error_exit; } req.size = sizeof (coroipc_request_header_t); req.id = MESSAGE_REQ_CONFDB_WRITE; iov.iov_base = (char *)&req; iov.iov_len = sizeof (coroipc_request_header_t); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_write, sizeof (struct res_lib_confdb_write)); if (error != CS_OK) { /* FIXME: set error_text */ goto error_exit; } error = res_lib_confdb_write.header.error; if (res_lib_confdb_write.error.length) { memcpy(error_text, res_lib_confdb_write.error.value, MIN(res_lib_confdb_write.error.length,errbuf_len)); error_text[errbuf_len-1] = '\0'; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_reload ( confdb_handle_t handle, int flush, char *error_text, size_t errbuf_len) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct res_lib_confdb_reload res_lib_confdb_reload; struct req_lib_confdb_reload req_lib_confdb_reload; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { /* FIXME: set error_text */ return (error); } if (confdb_inst->standalone) { error = CS_OK; if (confdb_sa_reload(flush, error_text, errbuf_len)) error = CS_ERR_ACCESS; goto error_exit; } req_lib_confdb_reload.header.size = sizeof (req_lib_confdb_reload); req_lib_confdb_reload.header.id = MESSAGE_REQ_CONFDB_RELOAD; req_lib_confdb_reload.flush = flush; iov.iov_base = (char *)&req_lib_confdb_reload; iov.iov_len = sizeof (req_lib_confdb_reload); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res_lib_confdb_reload, sizeof (struct res_lib_confdb_reload)); if (error != CS_OK) { /* FIXME: set error_text */ goto error_exit; } error = res_lib_confdb_reload.header.error; if(res_lib_confdb_reload.error.length) { memcpy(error_text, res_lib_confdb_reload.error.value, MIN(res_lib_confdb_reload.error.length,errbuf_len)); error_text[errbuf_len-1] = '\0'; } error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_track_changes ( confdb_handle_t handle, hdb_handle_t object_handle, unsigned int flags) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; struct req_lib_confdb_object_track_start req; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_exit; } req.header.size = sizeof (struct req_lib_confdb_object_track_start); req.header.id = MESSAGE_REQ_CONFDB_TRACK_START; req.object_handle = object_handle; req.flags = flags; iov.iov_base = (char *)&req; iov.iov_len = sizeof (struct req_lib_confdb_object_track_start); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); } cs_error_t confdb_stop_track_changes (confdb_handle_t handle) { cs_error_t error; struct confdb_inst *confdb_inst; struct iovec iov; coroipc_request_header_t req; coroipc_response_header_t res; error = hdb_error_to_cs(hdb_handle_get (&confdb_handle_t_db, handle, (void *)&confdb_inst)); if (error != CS_OK) { return (error); } if (confdb_inst->standalone) { error = CS_ERR_NOT_SUPPORTED; goto error_exit; } req.size = sizeof (coroipc_request_header_t); req.id = MESSAGE_REQ_CONFDB_TRACK_STOP; iov.iov_base = (char *)&req; iov.iov_len = sizeof (coroipc_request_header_t); error = coroipcc_msg_send_reply_receive ( confdb_inst->handle, &iov, 1, &res, sizeof (coroipc_response_header_t)); if (error != CS_OK) { goto error_exit; } error = res.error; error_exit: (void)hdb_handle_put (&confdb_handle_t_db, handle); return (error); }