Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/include/corosync/confdb.h b/include/corosync/confdb.h
index ca0d7ba3..6879383d 100644
--- a/include/corosync/confdb.h
+++ b/include/corosync/confdb.h
@@ -1,348 +1,364 @@
/*
- * Copyright (c) 2008-2010 Red Hat, Inc.
+ * Copyright (c) 2008-2012 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Christine Caulfield (ccaulfi@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.
*/
#ifndef COROSYNC_CONFDB_H_DEFINED
#define COROSYNC_CONFDB_H_DEFINED
#include <corosync/corotypes.h>
#include <corosync/hdb.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup confdb_corosync
*
* @{
*/
typedef uint64_t confdb_handle_t;
#define OBJECT_PARENT_HANDLE 0xFFFFFFFF00000000ULL
typedef enum {
CONFDB_VALUETYPE_INT16,
CONFDB_VALUETYPE_UINT16,
CONFDB_VALUETYPE_INT32,
CONFDB_VALUETYPE_UINT32,
CONFDB_VALUETYPE_INT64,
CONFDB_VALUETYPE_UINT64,
CONFDB_VALUETYPE_FLOAT,
CONFDB_VALUETYPE_DOUBLE,
CONFDB_VALUETYPE_STRING,
CONFDB_VALUETYPE_ANY,
} confdb_value_types_t;
typedef enum {
CONFDB_TRACK_DEPTH_ONE,
CONFDB_TRACK_DEPTH_RECURSIVE
} confdb_track_depth_t;
typedef enum {
OBJECT_KEY_CREATED,
OBJECT_KEY_REPLACED,
OBJECT_KEY_DELETED,
} confdb_change_type_t;
typedef enum {
CONFDB_RELOAD_NOTIFY_START,
CONFDB_RELOAD_NOTIFY_END,
CONFDB_RELOAD_NOTIFY_FAILED
} confdb_reload_type_t;
typedef void (*confdb_key_change_notify_fn_t) (
confdb_handle_t handle,
confdb_change_type_t change_type,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *object_name,
size_t object_name_len,
const void *key_name,
size_t key_name_len,
const void *key_value,
size_t key_value_len);
typedef void (*confdb_object_create_notify_fn_t) (
confdb_handle_t handle,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *name_pt,
size_t name_len);
typedef void (*confdb_object_delete_notify_fn_t) (
confdb_handle_t handle,
hdb_handle_t parent_object_handle,
const void *name_pt,
size_t name_len);
typedef void (*confdb_reload_notify_fn_t) (
confdb_handle_t handle,
confdb_reload_type_t type);
typedef struct {
confdb_object_create_notify_fn_t confdb_object_create_change_notify_fn;
confdb_object_delete_notify_fn_t confdb_object_delete_change_notify_fn;
confdb_key_change_notify_fn_t confdb_key_change_notify_fn;
confdb_reload_notify_fn_t confdb_reload_notify_fn;
} confdb_callbacks_t;
/** @} */
/*
* Create a new confdb connection
*/
cs_error_t confdb_initialize (
confdb_handle_t *handle,
confdb_callbacks_t *callbacks);
/*
* Close the confdb handle
*/
cs_error_t confdb_finalize (
confdb_handle_t handle);
/*
* Write back the configuration
*/
cs_error_t confdb_write (
confdb_handle_t handle,
char *error_text,
size_t errbuf_len);
/*
* Reload the configuration
*/
cs_error_t confdb_reload (
confdb_handle_t handle,
int flush,
char *error_text,
size_t errbuf_len);
/*
* Get a file descriptor on which to poll. confdb_handle_t is NOT a
* file descriptor and may not be used directly.
*/
cs_error_t confdb_fd_get (
confdb_handle_t handle,
int *fd);
/*
* Dispatch configuration changes
*/
cs_error_t confdb_dispatch (
confdb_handle_t handle,
cs_dispatch_flags_t dispatch_types);
/*
* Change notification
*/
cs_error_t confdb_track_changes (
confdb_handle_t handle,
hdb_handle_t object_handle,
unsigned int flags);
cs_error_t confdb_stop_track_changes (
confdb_handle_t handle);
/*
* Manipulate objects
*/
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 confdb_object_destroy (
confdb_handle_t handle,
hdb_handle_t object_handle);
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 confdb_object_name_get (
confdb_handle_t handle,
hdb_handle_t object_handle,
char *object_name,
size_t *object_name_len);
/*
* Manipulate keys
*/
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 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 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);
/*
* Key queries
*/
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 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 confdb_key_get_typed2 (
+ 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 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 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 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);
/*
* Object queries
* "find" loops through all objects of a given name and is also
* a quick way of finding a specific object,
* "iter" returns each object in sequence.
*/
cs_error_t confdb_object_find_start (
confdb_handle_t handle,
hdb_handle_t parent_object_handle);
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 confdb_object_find_destroy(
confdb_handle_t handle,
hdb_handle_t parent_object_handle);
cs_error_t confdb_object_iter_start (
confdb_handle_t handle,
hdb_handle_t parent_object_handle);
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 confdb_object_iter_destroy(
confdb_handle_t handle,
hdb_handle_t parent_object_handle);
/*
* Key iterator
*/
cs_error_t confdb_key_iter_start (
confdb_handle_t handle,
hdb_handle_t object_handle);
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 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 confdb_key_iter_typed2 (
+ confdb_handle_t handle,
+ hdb_handle_t parent_object_handle,
+ char *key_name,
+ void **value,
+ size_t *value_len,
+ confdb_value_types_t *type);
+
/*
* Get/set context variable
*/
cs_error_t confdb_context_get (
confdb_handle_t handle,
const void **context);
cs_error_t confdb_context_set (
confdb_handle_t handle,
const void *context);
#ifdef __cplusplus
}
#endif
#endif /* COROSYNC_CONFDB_H_DEFINED */
diff --git a/include/corosync/ipc_confdb.h b/include/corosync/ipc_confdb.h
index 856c8a67..709c6770 100644
--- a/include/corosync/ipc_confdb.h
+++ b/include/corosync/ipc_confdb.h
@@ -1,278 +1,330 @@
/*
- * Copyright (c) 2008-2010 Red Hat, Inc.
+ * Copyright (c) 2008-2012 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.
*/
#ifndef IPC_CONFDB_H_DEFINED
#define IPC_CONFDB_H_DEFINED
#include <netinet/in.h>
#include <corosync/corotypes.h>
#include <corosync/mar_gen.h>
enum req_confdb_types {
MESSAGE_REQ_CONFDB_OBJECT_CREATE = 0,
MESSAGE_REQ_CONFDB_OBJECT_DESTROY = 1,
MESSAGE_REQ_CONFDB_OBJECT_FIND = 2,
MESSAGE_REQ_CONFDB_KEY_CREATE = 3,
MESSAGE_REQ_CONFDB_KEY_GET = 4,
MESSAGE_REQ_CONFDB_KEY_REPLACE = 5,
MESSAGE_REQ_CONFDB_KEY_DELETE = 6,
MESSAGE_REQ_CONFDB_OBJECT_ITER = 7,
MESSAGE_REQ_CONFDB_OBJECT_PARENT_GET = 8,
MESSAGE_REQ_CONFDB_KEY_ITER = 9,
MESSAGE_REQ_CONFDB_TRACK_START = 10,
MESSAGE_REQ_CONFDB_TRACK_STOP = 11,
MESSAGE_REQ_CONFDB_WRITE = 12,
MESSAGE_REQ_CONFDB_RELOAD = 13,
MESSAGE_REQ_CONFDB_OBJECT_FIND_DESTROY = 14,
MESSAGE_REQ_CONFDB_KEY_INCREMENT = 15,
MESSAGE_REQ_CONFDB_KEY_DECREMENT = 16,
MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED = 17,
MESSAGE_REQ_CONFDB_KEY_GET_TYPED = 18,
MESSAGE_REQ_CONFDB_KEY_ITER_TYPED = 19,
MESSAGE_REQ_CONFDB_OBJECT_NAME_GET = 20,
+ MESSAGE_REQ_CONFDB_KEY_ITER_TYPED2 = 21,
+ MESSAGE_REQ_CONFDB_KEY_REPLACE2 = 22,
+ MESSAGE_REQ_CONFDB_KEY_GET_TYPED2 = 23,
+ MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED2 = 24,
};
enum res_confdb_types {
MESSAGE_RES_CONFDB_OBJECT_CREATE = 0,
MESSAGE_RES_CONFDB_OBJECT_DESTROY = 1,
MESSAGE_RES_CONFDB_OBJECT_FIND = 2,
MESSAGE_RES_CONFDB_KEY_CREATE = 3,
MESSAGE_RES_CONFDB_KEY_GET = 4,
MESSAGE_RES_CONFDB_KEY_REPLACE = 5,
MESSAGE_RES_CONFDB_KEY_DELETE = 6,
MESSAGE_RES_CONFDB_OBJECT_ITER = 7,
MESSAGE_RES_CONFDB_OBJECT_PARENT_GET = 8,
MESSAGE_RES_CONFDB_KEY_ITER = 9,
MESSAGE_RES_CONFDB_TRACK_START = 10,
MESSAGE_RES_CONFDB_TRACK_STOP = 11,
MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK = 12,
MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK = 13,
MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK = 14,
MESSAGE_RES_CONFDB_WRITE = 15,
MESSAGE_RES_CONFDB_RELOAD = 16,
MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY = 17,
MESSAGE_RES_CONFDB_KEY_INCREMENT = 18,
MESSAGE_RES_CONFDB_KEY_DECREMENT = 19,
MESSAGE_RES_CONFDB_KEY_GET_TYPED = 20,
MESSAGE_RES_CONFDB_KEY_ITER_TYPED = 21,
MESSAGE_RES_CONFDB_RELOAD_CALLBACK = 22,
MESSAGE_RES_CONFDB_OBJECT_NAME_GET = 23,
+ MESSAGE_RES_CONFDB_KEY_ITER_TYPED2 = 24,
+ MESSAGE_RES_CONFDB_KEY_GET_TYPED2 = 25,
+ MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK2 = 26,
};
struct req_lib_confdb_object_create {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
};
struct res_lib_confdb_object_create {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_object_destroy {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_object_parent_get {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
};
struct res_lib_confdb_object_parent_get {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_object_name_get {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
};
struct res_lib_confdb_object_name_get {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
};
struct req_lib_confdb_key_create {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
};
struct req_lib_confdb_key_create_typed {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
mar_int32_t type __attribute__((aligned(8)));
};
+struct req_lib_confdb_key_create_typed2 {
+ coroipc_request_header_t header __attribute__((aligned(8)));
+ mar_uint64_t object_handle __attribute__((aligned(8)));
+ mar_name_t key_name __attribute__((aligned(8)));
+ mar_int32_t type __attribute__((aligned(8)));
+ mar_int32_t value_length __attribute__((aligned(8)));
+ mar_uint8_t value __attribute__((aligned(8))); /* First byte of value */
+};
+
struct req_lib_confdb_key_delete {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
};
struct req_lib_confdb_key_replace {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t old_value __attribute__((aligned(8)));
mar_name_t new_value __attribute__((aligned(8)));
};
struct req_lib_confdb_object_find {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
mar_uint64_t find_handle __attribute__((aligned(8)));
};
struct res_lib_confdb_object_find {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_uint64_t find_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_object_iter {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_uint64_t find_handle __attribute__((aligned(8)));
};
struct res_lib_confdb_object_iter {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_uint64_t find_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_key_iter {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_uint64_t next_entry __attribute__((aligned(8)));
};
struct res_lib_confdb_key_iter {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
};
struct res_lib_confdb_key_iter_typed {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
mar_int32_t type __attribute__((aligned(8)));
};
struct req_lib_confdb_key_get {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
};
struct req_lib_confdb_object_find_destroy {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t find_handle __attribute__((aligned(8)));
};
struct res_lib_confdb_key_get {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
};
struct res_lib_confdb_key_get_typed {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
mar_int32_t type __attribute__((aligned(8)));
};
struct res_lib_confdb_key_incdec {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint32_t value __attribute__((aligned(8)));
};
struct res_lib_confdb_write {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t error __attribute__((aligned(8)));
};
struct req_lib_confdb_reload {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_int32_t flush __attribute__((aligned(8)));
};
struct res_lib_confdb_reload {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_name_t error __attribute__((aligned(8)));
};
struct res_lib_confdb_key_change_callback {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint64_t change_type __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t key_value __attribute__((aligned(8)));
};
+struct res_lib_confdb_key_change_callback2 {
+ coroipc_response_header_t header __attribute__((aligned(8)));
+ mar_uint64_t change_type __attribute__((aligned(8)));
+ mar_uint64_t parent_object_handle __attribute__((aligned(8)));
+ mar_uint64_t object_handle __attribute__((aligned(8)));
+ mar_name_t object_name __attribute__((aligned(8)));
+ mar_name_t key_name __attribute__((aligned(8)));
+ mar_uint32_t key_value_length __attribute__((aligned(8)));
+ mar_uint8_t key_value __attribute__((aligned(8))); /* First byte of new value */
+};
+
struct res_lib_confdb_object_create_callback {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_name_t name __attribute__((aligned(8)));
};
struct res_lib_confdb_object_destroy_callback {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint64_t parent_object_handle __attribute__((aligned(8)));
mar_name_t name __attribute__((aligned(8)));
};
struct res_lib_confdb_reload_callback {
coroipc_response_header_t header __attribute__((aligned(8)));
mar_uint32_t type __attribute__((aligned(8)));
};
struct req_lib_confdb_object_track_start {
coroipc_request_header_t header __attribute__((aligned(8)));
mar_uint64_t object_handle __attribute__((aligned(8)));
mar_uint32_t flags __attribute__((aligned(8)));
};
+struct res_lib_confdb_key_get_typed2 {
+ coroipc_response_header_t header __attribute__((aligned(8)));
+ mar_int32_t type __attribute__((aligned(8)));
+ mar_uint32_t value_length __attribute__((aligned(8)));
+ mar_uint8_t value __attribute__((aligned(8)));
+ // Actual value follows this
+};
+
+struct res_lib_confdb_key_iter_typed2 {
+ coroipc_response_header_t header __attribute__((aligned(8)));
+ mar_name_t key_name __attribute__((aligned(8)));
+ mar_int32_t type __attribute__((aligned(8)));
+ mar_int32_t value_length __attribute__((aligned(8)));
+ mar_uint8_t value __attribute__((aligned(8))); /* First byte of value */
+};
+
+struct req_lib_confdb_key_replace2 {
+ coroipc_request_header_t header __attribute__((aligned(8)));
+ mar_uint64_t object_handle __attribute__((aligned(8)));
+ mar_name_t key_name __attribute__((aligned(8)));
+ mar_int32_t new_value_length __attribute__((aligned(8)));
+ mar_uint8_t new_value __attribute__((aligned(8))); /* First byte of new value */
+ /* Oddly objdb doesn't use the old value, so we don't bother sending it */
+};
+
#endif /* IPC_CONFDB_H_DEFINED */
diff --git a/lib/confdb.c b/lib/confdb.c
index 1ea2ed0b..0dbecb96 100644
--- a/lib/confdb.c
+++ b/lib/confdb.c
@@ -1,1814 +1,1994 @@
/*
- * Copyright (c) 2008-2010 Red Hat, Inc.
+ * Copyright (c) 2008-2012 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 <config.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <errno.h>
#include <corosync/corotypes.h>
#include <corosync/coroipc_types.h>
#include <corosync/coroipcc.h>
#include <corosync/corodefs.h>
#include <corosync/hdb.h>
#include <corosync/list.h>
#include <corosync/confdb.h>
#include <corosync/ipc_confdb.h>
#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_KEY_CHANGE_CALLBACK2:
+ 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) {
continue;
}
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);
}
cs_error_t confdb_object_name_get (
confdb_handle_t handle,
hdb_handle_t object_handle,
char *object_name,
size_t *object_name_len)
{
cs_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov;
struct req_lib_confdb_object_name_get request;
struct res_lib_confdb_object_name_get 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_object_name_get(object_handle, object_name, object_name_len))
error = CS_ERR_ACCESS;
goto error_exit;
}
request.header.size = sizeof (struct req_lib_confdb_object_name_get);
request.header.id = MESSAGE_REQ_CONFDB_OBJECT_NAME_GET;
request.object_handle = object_handle;
iov.iov_base = (char *)&request;
iov.iov_len = sizeof (struct req_lib_confdb_object_name_get);
error = coroipcc_msg_send_reply_receive (
confdb_inst->handle,
&iov,
1,
&response,
sizeof (struct res_lib_confdb_object_name_get));
if (error != CS_OK) {
goto error_exit;
}
error = response.header.error;
if (error == CS_OK) {
*object_name_len = response.object_name.length;
memcpy(object_name, response.object_name.value, *object_name_len);
}
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;
+ struct req_lib_confdb_key_create_typed2 *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;
+ request = malloc(sizeof(struct req_lib_confdb_key_create_typed2)+value_len);
+ if (!request) {
+ error = CS_ERR_NO_MEMORY;
+ goto error_exit;
+ }
- iov.iov_base = (char *)&request;
- iov.iov_len = sizeof (struct req_lib_confdb_key_create_typed);
+ request->header.size = sizeof (struct req_lib_confdb_key_create_typed2) + value_len;
+ request->header.id = MESSAGE_REQ_CONFDB_KEY_CREATE_TYPED2;
+ 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_len);
+ request->value_length = value_len;
+ request->type = type;
+
+ iov.iov_base = (char *)request;
+ iov.iov_len = request->header.size;
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))
+ 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_get_typed2 (
+ 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_typed2 *response;
+ void *return_address;
+
+ 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_TYPED2;
+ 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_in_buf_get (
+ confdb_inst->handle,
+ &iov,
+ 1,
+ &return_address);
+ response = return_address;
+
+ if (error != CS_OK) {
+ goto error_exit;
+ }
+ error = response->header.error;
+
+ if (error == CS_OK) {
+ if (!*value) {
+ /* Allow space for naughty callers to put a NUL for printing */
+ *value = malloc(response->value_length+1);
+ if (!*value) {
+ error = CS_ERR_NO_MEMORY;
+ goto error_exit;
+ }
+ }
+ memcpy(*value, &response->value, response->value_length);
+ *value_len = response->value_length;
+ *type = response->type;
+ }
+
+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;
+ struct req_lib_confdb_key_replace2 *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);
+ req_lib_confdb_key_replace = malloc(sizeof(struct req_lib_confdb_key_replace2) + new_value_len);
+
+ req_lib_confdb_key_replace->header.size = sizeof(struct req_lib_confdb_key_replace2) + new_value_len;
+ req_lib_confdb_key_replace->header.id = MESSAGE_REQ_CONFDB_KEY_REPLACE2;
+ 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->new_value, new_value, new_value_len);
+ req_lib_confdb_key_replace->new_value_length = new_value_len;
+ /* Oddly objdb doesn't use the old value, so we don't bother sending it */
+ iov.iov_base = (char *)req_lib_confdb_key_replace;
+ iov.iov_len = sizeof(struct req_lib_confdb_key_replace2) + new_value_len;
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))
+ &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_key_iter_typed2 (
+ 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_typed2 *response;
+ void *return_address;
+
+ 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_TYPED2;
+ 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_in_buf_get (
+ confdb_inst->handle,
+ &iov,
+ 1,
+ &return_address);
+ response = return_address;
+
+ if (error != CS_OK) {
+ goto error_exit;
+ }
+ error = response->header.error;
+
+ if (error == CS_OK) {
+ if (!*value) {
+ /* Allow space for naughty callers to put a NUL for printing */
+ *value = malloc(response->value_length+1);
+ if (!*value) {
+ error = CS_ERR_NO_MEMORY;
+ goto error_exit;
+ }
+ }
+ memcpy(key_name, response->key_name.value, response->key_name.length);
+ key_name[response->key_name.length] = '\0';
+ memcpy(*value, &response->value, response->value_length);
+ *value_len = response->value_length;
+ *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);
}
diff --git a/lib/sa-confdb.c b/lib/sa-confdb.c
index 03995e34..9a11418b 100644
--- a/lib/sa-confdb.c
+++ b/lib/sa-confdb.c
@@ -1,449 +1,464 @@
/*
- * Copyright (c) 2008, 2009 Red Hat, Inc.
+ * Copyright (c) 2008, 2012 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 stand-alone access to data in the corosync object database
* when aisexec is not running.
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <corosync/corotypes.h>
#include <corosync/coroipcc.h>
#include <corosync/engine/objdb.h>
#include <corosync/engine/config.h>
#include <corosync/engine/logsys.h>
#include <corosync/lcr/lcr_comp.h>
#include <corosync/lcr/lcr_ifact.h>
#include "sa-confdb.h"
static struct objdb_iface_ver0 *objdb;
static int num_config_modules;
static struct config_iface_ver0 *config_modules[128];
void main_get_config_modules(struct config_iface_ver0 ***modules, int *num);
static int load_objdb(void)
{
hdb_handle_t objdb_handle;
void *objdb_p;
int res;
/*
* Load the object database interface
*/
res = lcr_ifact_reference (
&objdb_handle,
"objdb",
0,
&objdb_p,
(void *)0);
if (res == -1) {
return -1;
}
objdb = (struct objdb_iface_ver0 *)objdb_p;
objdb->objdb_init ();
return CS_OK;
}
static int load_config(void)
{
char *config_iface;
char *iface;
int res;
hdb_handle_t config_handle;
hdb_handle_t config_version = 0;
void *config_p;
struct config_iface_ver0 *config;
const char *error_string;
char *strtok_savept;
/* User's bootstrap config service */
config_iface = getenv("COROSYNC_DEFAULT_CONFIG_IFACE");
if (!config_iface) {
if ((config_iface = strdup("corosync_parser")) == NULL) {
return -1;
}
}
/* Make a copy so we can deface it with strtok */
if ((config_iface = strdup(config_iface)) == NULL) {
return -1;
}
iface = strtok_r (config_iface, ":", &strtok_savept);
while (iface)
{
res = lcr_ifact_reference (
&config_handle,
iface,
config_version,
&config_p,
0);
config = (struct config_iface_ver0 *)config_p;
if (res == -1) {
return -1;
}
res = config->config_readconfig(objdb, &error_string);
if (res == -1) {
return -1;
}
config_modules[num_config_modules++] = config;
iface = strtok_r (NULL, ":", &strtok_savept);
}
free(config_iface);
return CS_OK;
}
/* Needed by objdb when it writes back the configuration */
void main_get_config_modules(struct config_iface_ver0 ***modules, int *num)
{
*modules = config_modules;
*num = num_config_modules;
}
int confdb_sa_init (void)
{
int res;
res = load_objdb();
if (res != CS_OK)
return res;
res = load_config();
return res;
}
int confdb_sa_object_create (
hdb_handle_t parent_object_handle,
const void *object_name,
size_t object_name_len,
hdb_handle_t *object_handle)
{
return objdb->object_create(parent_object_handle,
object_handle,
object_name, object_name_len);
}
int confdb_sa_object_destroy (
hdb_handle_t object_handle)
{
return objdb->object_destroy(object_handle);
}
int confdb_sa_object_parent_get (
hdb_handle_t object_handle,
hdb_handle_t *parent_object_handle)
{
return objdb->object_parent_get(object_handle, parent_object_handle);
}
int confdb_sa_object_name_get(
hdb_handle_t object_handle,
char *object_name,
size_t *object_name_len)
{
return objdb->object_name_get(object_handle, object_name, object_name_len);
}
int confdb_sa_key_create (
hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
const void *value,
size_t value_len)
{
return objdb->object_key_create(parent_object_handle,
key_name, key_name_len,
value, value_len);
}
int confdb_sa_key_create_typed (
hdb_handle_t parent_object_handle,
const char *key_name,
const void *value,
size_t value_len,
int type)
{
return objdb->object_key_create_typed(parent_object_handle,
key_name,
value, value_len, type);
}
int confdb_sa_key_delete (
hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
const void *value,
size_t value_len)
{
return objdb->object_key_delete(parent_object_handle,
key_name, key_name_len);
}
int confdb_sa_key_get (
hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
void *value,
size_t *value_len)
{
int res;
void *kvalue;
res = objdb->object_key_get(parent_object_handle,
key_name, key_name_len,
&kvalue, value_len);
if (!res) {
memcpy(value, kvalue, *value_len);
}
return res;
}
int confdb_sa_key_get_typed (
hdb_handle_t parent_object_handle,
const char *key_name,
- void *value,
+ void **value,
size_t *value_len,
int *type)
{
int res;
void *kvalue;
res = objdb->object_key_get_typed(parent_object_handle,
key_name,
&kvalue, value_len, (objdb_value_types_t*)type);
if (!res) {
- memcpy(value, kvalue, *value_len);
+ if (!*value) {
+ *value = malloc(*value_len);
+ if (!*value) {
+ res = CS_ERR_NO_MEMORY;
+ }
+ }
+ if (*value) {
+ memcpy(*value, kvalue, *value_len);
+ }
}
return res;
}
int confdb_sa_key_increment (
hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
unsigned int *value)
{
int res;
res = objdb->object_key_increment(parent_object_handle,
key_name, key_name_len,
value);
return res;
}
int confdb_sa_key_decrement (
hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
unsigned int *value)
{
int res;
res = objdb->object_key_decrement(parent_object_handle,
key_name, key_name_len,
value);
return res;
}
int confdb_sa_key_replace (
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)
{
return objdb->object_key_replace(parent_object_handle,
key_name, key_name_len,
new_value, new_value_len);
}
int confdb_sa_write (char *error_text, size_t errbuf_len)
{
const char *errtext;
int ret;
ret = objdb->object_write_config(&errtext);
if (!ret) {
strncpy(error_text, errtext, errbuf_len);
if (errbuf_len > 0)
error_text[errbuf_len-1] = '\0';
}
return ret;
}
int confdb_sa_reload (
int flush,
char *error_text,
size_t errbuf_len)
{
char *errtext;
int ret;
ret = objdb->object_reload_config(flush, (const char **) &errtext);
if (!ret) {
strncpy(error_text, errtext, errbuf_len);
if (errbuf_len > 0)
error_text[errbuf_len-1] = '\0';
}
return ret;
}
int confdb_sa_object_find (
hdb_handle_t parent_object_handle,
hdb_handle_t *find_handle,
hdb_handle_t *object_handle,
const void *object_name,
size_t object_name_len)
{
int res;
if (!*find_handle) {
objdb->object_find_create(parent_object_handle,
object_name, object_name_len,
find_handle);
}
res = objdb->object_find_next(*find_handle,
object_handle);
return res;
}
int confdb_sa_object_iter (
hdb_handle_t parent_object_handle,
hdb_handle_t *find_handle,
hdb_handle_t *object_handle,
const void *object_name,
size_t object_name_len,
void *found_object_name,
size_t *found_object_name_len)
{
int res;
if (!*find_handle) {
objdb->object_find_create(parent_object_handle,
object_name, object_name_len,
find_handle);
}
res = objdb->object_find_next(*find_handle,
object_handle);
/* Return object name if we were called as _iter */
if (!res) {
objdb->object_name_get(*object_handle,
found_object_name, found_object_name_len);
}
return res;
}
int confdb_sa_key_iter (
hdb_handle_t parent_object_handle,
hdb_handle_t start_pos,
void *key_name,
size_t *key_name_len,
void *value,
size_t *value_len)
{
int res;
void *kname, *kvalue;
res = objdb->object_key_iter_from(parent_object_handle,
start_pos,
&kname, key_name_len,
&kvalue, value_len);
if (!res) {
memcpy(key_name, kname, *key_name_len);
memcpy(value, kvalue, *value_len);
}
return res;
}
int confdb_sa_key_iter_typed (
hdb_handle_t parent_object_handle,
hdb_handle_t start_pos,
char *key_name,
- void *value,
+ void **value,
size_t *value_len,
int *type)
{
int res;
void *kname;
void *kvalue;
size_t key_name_len;
res = objdb->object_key_iter_from(parent_object_handle,
start_pos,
&kname, &key_name_len,
&kvalue, value_len);
if (!res) {
memcpy(key_name, kname, key_name_len);
key_name[key_name_len] = '\0';
- memcpy(value, kvalue, *value_len);
-
- objdb->object_key_get_typed(parent_object_handle,
- key_name,
- &kvalue, value_len, (objdb_value_types_t*)type);
+ if (!*value) {
+ *value = malloc(*value_len);
+ if (!*value) {
+ res = CS_ERR_NO_MEMORY;
+ }
+ }
+ if (*value) {
+ memcpy(*value, kvalue, *value_len);
+ objdb->object_key_get_typed(parent_object_handle,
+ key_name,
+ &kvalue, value_len, (objdb_value_types_t*)type);
+ }
}
return res;
}
int confdb_sa_find_destroy(hdb_handle_t find_handle)
{
return objdb->object_find_destroy(find_handle);
}
diff --git a/lib/sa-confdb.h b/lib/sa-confdb.h
index 61a0fa75..439c760f 100644
--- a/lib/sa-confdb.h
+++ b/lib/sa-confdb.h
@@ -1,112 +1,112 @@
/*
- * Copyright (c) 2008, 2009 Red Hat, Inc.
+ * Copyright (c) 2008, 2012 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.
*/
extern int confdb_sa_init(void);
extern int confdb_sa_object_create(hdb_handle_t parent_object_handle,
const void *object_name,
size_t object_name_len,
hdb_handle_t *object_handle);
extern int confdb_sa_object_destroy(hdb_handle_t object_handle);
extern int confdb_sa_object_parent_get(hdb_handle_t object_handle,
hdb_handle_t *parent_object_handle);
extern int confdb_sa_object_name_get(hdb_handle_t object_handle,
char *object_name,
size_t *object_name_len);
extern int confdb_sa_key_create(hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
const void *value,
size_t value_len);
extern int confdb_sa_key_create_typed (hdb_handle_t parent_object_handle,
const char *key_name,
const void *value,
size_t value_len,
int type);
extern int confdb_sa_key_delete(hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
const void *value,
size_t value_len);
extern int confdb_sa_key_get(hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
void *value,
size_t *value_len);
extern int confdb_sa_key_get_typed(hdb_handle_t parent_object_handle,
const char *key_name,
- void *value,
+ void **value,
size_t *value_len,
int *type);
extern int confdb_sa_key_replace(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);
extern int confdb_sa_object_find(hdb_handle_t parent_object_handle,
hdb_handle_t *find_handle,
hdb_handle_t *object_handle,
const void *object_name,
size_t object_name_len);
extern int confdb_sa_object_iter(hdb_handle_t parent_object_handle,
hdb_handle_t *find_handle,
hdb_handle_t *object_handle,
const void *object_name,
size_t object_name_len,
void *found_object_name,
size_t *found_object_name_len);
extern int confdb_sa_key_iter(hdb_handle_t parent_object_handle,
hdb_handle_t start_pos,
void *key_name,
size_t *key_name_len,
void *value,
size_t *value_len);
extern int confdb_sa_key_iter_typed (hdb_handle_t parent_object_handle,
hdb_handle_t start_pos,
char *key_name,
- void *value,
+ void **value,
size_t *value_len,
int *type);
extern int confdb_sa_key_increment(hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
unsigned int *value);
extern int confdb_sa_key_decrement(hdb_handle_t parent_object_handle,
const void *key_name,
size_t key_name_len,
unsigned int *value);
extern int confdb_sa_find_destroy(hdb_handle_t find_handle);
extern int confdb_sa_write(char *error_text, size_t errbuf_len);
extern int confdb_sa_reload(int flush, char *error_text, size_t errbuf_len);
diff --git a/services/confdb.c b/services/confdb.c
index 39dbd939..1559604a 100644
--- a/services/confdb.c
+++ b/services/confdb.c
@@ -1,1092 +1,1263 @@
/*
- * Copyright (c) 2008-2010 Red Hat, Inc.
+ * Copyright (c) 2008-2012 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 CONTIBUTORS "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 <corosync/corotypes.h>
#include <corosync/coroipc_types.h>
#include <corosync/corodefs.h>
#include <corosync/cfg.h>
#include <corosync/list.h>
#include <corosync/mar_gen.h>
#include <corosync/ipc_confdb.h>
#include <corosync/lcr/lcr_comp.h>
#include <corosync/engine/logsys.h>
#include <corosync/engine/coroapi.h>
#include <corosync/totem/coropoll.h>
LOGSYS_DECLARE_SUBSYS ("CONFDB");
static hdb_handle_t *
m2h (mar_uint64_t *m)
{
/* FIXME enable the following when/if we use gnulib:
(it's a compile-time assertion; i.e., zero run-time cost)
verify (sizeof (*m) == sizeof (hdb_handle_t)); */
return (void *) m;
}
static struct corosync_api_v1 *api;
static int notify_pipe[2];
struct confdb_ipc_message_holder {
void *conn;
size_t mlen;
struct list_head list;
char msg[];
};
DECLARE_LIST_INIT(confdb_ipc_message_holder_list_head);
pthread_mutex_t confdb_ipc_message_holder_list_mutex =
PTHREAD_MUTEX_INITIALIZER;
static int confdb_exec_init_fn (
struct corosync_api_v1 *corosync_api);
static int confdb_exec_exit_fn(void);
static int fd_set_nonblocking(int fd);
static int objdb_notify_dispatch(hdb_handle_t handle,
int fd, int revents, void *data);
static int confdb_lib_init_fn (void *conn);
static int confdb_lib_exit_fn (void *conn);
static void message_handler_req_lib_confdb_object_create (void *conn,
const void *message);
static void message_handler_req_lib_confdb_object_destroy (void *conn,
const void *message);
static void message_handler_req_lib_confdb_object_find_destroy (void *conn,
const void *message);
static void message_handler_req_lib_confdb_key_create (void *conn,
const void *message);
static void message_handler_req_lib_confdb_key_create_typed (void *conn,
- const void *message);
+ const void *message);
+static void message_handler_req_lib_confdb_key_create_typed2 (void *conn,
+ const void *message);
static void message_handler_req_lib_confdb_key_get (void *conn,
const void *message);
static void message_handler_req_lib_confdb_key_get_typed (void *conn,
const void *message);
+
+static void message_handler_req_lib_confdb_key_get_typed2 (void *conn,
+ const void *message);
+
static void message_handler_req_lib_confdb_key_replace (void *conn,
const void *message);
+static void message_handler_req_lib_confdb_key_replace2 (void *conn,
+ const void *message);
static void message_handler_req_lib_confdb_key_delete (void *conn,
const void *message);
+
static void message_handler_req_lib_confdb_key_iter (void *conn,
- const void *message);
+ const void *message);
+
static void message_handler_req_lib_confdb_key_iter_typed (void *conn,
const void *message);
+static void message_handler_req_lib_confdb_key_iter_typed2 (void *conn,
+ const void *message);
+
static void message_handler_req_lib_confdb_key_increment (void *conn,
const void *message);
static void message_handler_req_lib_confdb_key_decrement (void *conn,
const void *message);
static void message_handler_req_lib_confdb_object_iter (void *conn,
const void *message);
static void message_handler_req_lib_confdb_object_find (void *conn,
const void *message);
static void message_handler_req_lib_confdb_object_parent_get (void *conn,
const void *message);
static void message_handler_req_lib_confdb_object_name_get (void *conn,
const void *message);
static void message_handler_req_lib_confdb_write (void *conn,
const void *message);
static void message_handler_req_lib_confdb_reload (void *conn,
const void *message);
static void message_handler_req_lib_confdb_track_start (void *conn,
const void *message);
static void message_handler_req_lib_confdb_track_stop (void *conn,
const void *message);
static void confdb_notify_lib_of_key_change(
object_change_type_t change_type,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *object_name_pt, size_t object_name_len,
const void *key_name_pt, size_t key_name_len,
const void *key_value_pt, size_t key_value_len,
void *priv_data_pt);
static void confdb_notify_lib_of_new_object(
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *name_pt, size_t name_len,
void *priv_data_pt);
static void confdb_notify_lib_of_destroyed_object(
hdb_handle_t parent_object_handle,
const void *name_pt, size_t name_len,
void *priv_data_pt);
static void confdb_notify_lib_of_reload(
objdb_reload_notify_type_t notify_type,
int flush,
void *priv_data_pt);
/*
* Library Handler Definition
*/
static struct corosync_lib_handler confdb_lib_engine[] =
{
{ /* 0 */
.lib_handler_fn = message_handler_req_lib_confdb_object_create,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 1 */
.lib_handler_fn = message_handler_req_lib_confdb_object_destroy,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 2 */
.lib_handler_fn = message_handler_req_lib_confdb_object_find,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 3 */
.lib_handler_fn = message_handler_req_lib_confdb_key_create,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 4 */
.lib_handler_fn = message_handler_req_lib_confdb_key_get,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 5 */
.lib_handler_fn = message_handler_req_lib_confdb_key_replace,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 6 */
.lib_handler_fn = message_handler_req_lib_confdb_key_delete,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 7 */
.lib_handler_fn = message_handler_req_lib_confdb_object_iter,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 8 */
.lib_handler_fn = message_handler_req_lib_confdb_object_parent_get,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 9 */
.lib_handler_fn = message_handler_req_lib_confdb_key_iter,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 10 */
.lib_handler_fn = message_handler_req_lib_confdb_track_start,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 11 */
.lib_handler_fn = message_handler_req_lib_confdb_track_stop,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 12 */
.lib_handler_fn = message_handler_req_lib_confdb_write,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 13 */
.lib_handler_fn = message_handler_req_lib_confdb_reload,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 14 */
.lib_handler_fn = message_handler_req_lib_confdb_object_find_destroy,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 15 */
.lib_handler_fn = message_handler_req_lib_confdb_key_increment,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 16 */
.lib_handler_fn = message_handler_req_lib_confdb_key_decrement,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 17 */
.lib_handler_fn = message_handler_req_lib_confdb_key_create_typed,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 18 */
.lib_handler_fn = message_handler_req_lib_confdb_key_get_typed,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 19 */
.lib_handler_fn = message_handler_req_lib_confdb_key_iter_typed,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 20 */
.lib_handler_fn = message_handler_req_lib_confdb_object_name_get,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
},
+ { /* 21 */
+ .lib_handler_fn = message_handler_req_lib_confdb_key_iter_typed2,
+ .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+ },
+ { /* 22 */
+ .lib_handler_fn = message_handler_req_lib_confdb_key_replace2,
+ .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+ },
+ { /* 23 */
+ .lib_handler_fn = message_handler_req_lib_confdb_key_get_typed2,
+ .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+ },
+ { /* 24 */
+ .lib_handler_fn = message_handler_req_lib_confdb_key_create_typed2,
+ .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+ },
};
struct corosync_service_engine confdb_service_engine = {
.name = "corosync cluster config database access v1.01",
.id = CONFDB_SERVICE,
.priority = 1,
.private_data_size = 0,
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
.allow_inquorate = CS_LIB_ALLOW_INQUORATE,
.lib_init_fn = confdb_lib_init_fn,
.lib_exit_fn = confdb_lib_exit_fn,
.lib_engine = confdb_lib_engine,
.lib_engine_count = sizeof (confdb_lib_engine) / sizeof (struct corosync_lib_handler),
.exec_init_fn = confdb_exec_init_fn,
.exec_exit_fn = confdb_exec_exit_fn,
};
/*
* Dynamic loader definition
*/
static struct corosync_service_engine *confdb_get_service_engine_ver0 (void);
static struct corosync_service_engine_iface_ver0 confdb_service_engine_iface = {
.corosync_get_service_engine_ver0 = confdb_get_service_engine_ver0
};
static struct lcr_iface corosync_confdb_ver0[1] = {
{
.name = "corosync_confdb",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = NULL
}
};
static struct lcr_comp confdb_comp_ver0 = {
.iface_count = 1,
.ifaces = corosync_confdb_ver0
};
static struct corosync_service_engine *confdb_get_service_engine_ver0 (void)
{
return (&confdb_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_confdb_ver0[0], &confdb_service_engine_iface);
lcr_component_register (&confdb_comp_ver0);
}
static int confdb_exec_exit_fn(void)
{
api->poll_dispatch_delete(api->poll_handle_get(), notify_pipe[0]);
close(notify_pipe[0]);
close(notify_pipe[1]);
return 0;
}
static int confdb_exec_init_fn (
struct corosync_api_v1 *corosync_api)
{
int i;
#ifdef COROSYNC_SOLARIS
logsys_subsys_init();
#endif
api = corosync_api;
if (pipe(notify_pipe) != 0) {
return -1;
}
for (i = 0; i < 2; i++) {
if (fd_set_nonblocking (notify_pipe[i]) == -1) {
return -1;
}
}
return api->poll_dispatch_add(api->poll_handle_get(), notify_pipe[0],
POLLIN, NULL, objdb_notify_dispatch);
}
static int confdb_lib_init_fn (void *conn)
{
log_printf(LOGSYS_LEVEL_DEBUG, "lib_init_fn: conn=%p\n", conn);
return (0);
}
static int confdb_lib_exit_fn (void *conn)
{
log_printf(LOGSYS_LEVEL_DEBUG, "exit_fn for conn=%p\n", conn);
/* cleanup the object trackers for this client. */
api->object_track_stop(confdb_notify_lib_of_key_change,
confdb_notify_lib_of_new_object,
confdb_notify_lib_of_destroyed_object,
confdb_notify_lib_of_reload,
conn);
return (0);
}
static int fd_set_nonblocking(int fd)
{
int flags;
int res;
flags = fcntl (fd, F_GETFL);
if (flags == -1) {
return -1;
}
flags |= O_NONBLOCK;
res = fcntl (fd, F_SETFL, flags);
return res;
}
static void message_handler_req_lib_confdb_object_create (void *conn,
const void *message)
{
const struct req_lib_confdb_object_create *req_lib_confdb_object_create
= message;
struct res_lib_confdb_object_create res_lib_confdb_object_create;
hdb_handle_t object_handle;
int ret = CS_OK;
if (api->object_create(req_lib_confdb_object_create->parent_object_handle,
&object_handle,
req_lib_confdb_object_create->object_name.value,
req_lib_confdb_object_create->object_name.length))
ret = CS_ERR_ACCESS;
res_lib_confdb_object_create.object_handle = object_handle;
res_lib_confdb_object_create.header.size = sizeof(res_lib_confdb_object_create);
res_lib_confdb_object_create.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE;
res_lib_confdb_object_create.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_object_create, sizeof(res_lib_confdb_object_create));
}
static void message_handler_req_lib_confdb_object_destroy (void *conn,
const void *message)
{
const struct req_lib_confdb_object_destroy *req_lib_confdb_object_destroy
= message;
coroipc_response_header_t res;
int ret = CS_OK;
if (api->object_destroy(req_lib_confdb_object_destroy->object_handle))
ret = CS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY;
res.error = ret;
api->ipc_response_send(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_object_find_destroy (void *conn,
const void *message)
{
const struct req_lib_confdb_object_find_destroy
*req_lib_confdb_object_find_destroy = message;
coroipc_response_header_t res;
int ret = CS_OK;
if (api->object_find_destroy(req_lib_confdb_object_find_destroy->find_handle))
ret = CS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY;
res.error = ret;
api->ipc_response_send(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_key_create (void *conn,
const void *message)
{
const struct req_lib_confdb_key_create *req_lib_confdb_key_create
= message;
coroipc_response_header_t res;
int ret = CS_OK;
if (api->object_key_create(req_lib_confdb_key_create->object_handle,
req_lib_confdb_key_create->key_name.value,
req_lib_confdb_key_create->key_name.length,
req_lib_confdb_key_create->value.value,
req_lib_confdb_key_create->value.length))
ret = CS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_KEY_CREATE;
res.error = ret;
api->ipc_response_send(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_key_create_typed (void *conn,
const void *message)
{
const struct req_lib_confdb_key_create_typed *req_lib_confdb_key_create
= message;
coroipc_response_header_t res;
int ret = CS_OK;
if (api->object_key_create_typed(req_lib_confdb_key_create->object_handle,
(char*)req_lib_confdb_key_create->key_name.value,
req_lib_confdb_key_create->value.value,
req_lib_confdb_key_create->value.length,
req_lib_confdb_key_create->type))
ret = CS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_KEY_CREATE;
res.error = ret;
api->ipc_response_send(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_key_get (void *conn,
const void *message)
{
const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message;
struct res_lib_confdb_key_get res_lib_confdb_key_get;
size_t value_len;
void *value;
int ret = CS_OK;
if (api->object_key_get(req_lib_confdb_key_get->parent_object_handle,
req_lib_confdb_key_get->key_name.value,
req_lib_confdb_key_get->key_name.length,
&value,
&value_len))
ret = CS_ERR_ACCESS;
else {
- memcpy(res_lib_confdb_key_get.value.value, value, value_len);
+ if (value_len > CS_MAX_NAME_LENGTH) {
+ ret = CS_ERR_TOO_BIG;
+ } else {
+ memcpy(res_lib_confdb_key_get.value.value, value, value_len);
+ }
res_lib_confdb_key_get.value.length = value_len;
}
res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get);
res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET;
res_lib_confdb_key_get.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get));
}
static void message_handler_req_lib_confdb_key_get_typed (void *conn,
const void *message)
{
const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message;
struct res_lib_confdb_key_get_typed res_lib_confdb_key_get;
size_t value_len;
void *value;
int ret = CS_OK;
objdb_value_types_t type;
char * key_name = (char*)req_lib_confdb_key_get->key_name.value;
key_name[req_lib_confdb_key_get->key_name.length] = '\0';
if (api->object_key_get_typed(req_lib_confdb_key_get->parent_object_handle,
key_name,
&value,
&value_len, &type))
ret = CS_ERR_ACCESS;
else {
- memcpy(res_lib_confdb_key_get.value.value, value, value_len);
+ if (value_len > CS_MAX_NAME_LENGTH) {
+ ret = CS_ERR_TOO_BIG;
+ } else {
+ memcpy(res_lib_confdb_key_get.value.value, value, value_len);
+ }
res_lib_confdb_key_get.value.length = value_len;
res_lib_confdb_key_get.type = type;
-
}
res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get);
res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET_TYPED;
res_lib_confdb_key_get.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get));
}
+static void message_handler_req_lib_confdb_key_get_typed2 (void *conn,
+ const void *message)
+{
+ const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message;
+ struct res_lib_confdb_key_get_typed2 res_lib_confdb_key_get;
+ struct res_lib_confdb_key_get_typed2 *res = &res_lib_confdb_key_get;
+ size_t value_len;
+ void *value;
+ int ret = CS_OK;
+ objdb_value_types_t type;
+ char * key_name = (char*)req_lib_confdb_key_get->key_name.value;
+ key_name[req_lib_confdb_key_get->key_name.length] = '\0';
+
+ if (api->object_key_get_typed(req_lib_confdb_key_get->parent_object_handle,
+ key_name,
+ &value,
+ &value_len, &type)) {
+ ret = CS_ERR_ACCESS;
+ res->header.size = sizeof(res_lib_confdb_key_get);
+ }
+ else {
+ res = alloca(sizeof(struct res_lib_confdb_key_get_typed2) + value_len);
+
+ memcpy(&res->value, value, value_len);
+ res->value_length = value_len;
+ res->type = type;
+
+ res->header.size = sizeof(struct res_lib_confdb_key_get_typed2)+value_len;
+ res->header.error = ret;
+ }
+ res->header.id = MESSAGE_RES_CONFDB_KEY_GET_TYPED2;
+ res->header.error = ret;
+
+ api->ipc_response_send(conn, res, res->header.size);
+
+}
static void message_handler_req_lib_confdb_key_increment (void *conn,
const void *message)
{
const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message;
struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
int ret = CS_OK;
if (api->object_key_increment(req_lib_confdb_key_get->parent_object_handle,
req_lib_confdb_key_get->key_name.value,
req_lib_confdb_key_get->key_name.length,
&res_lib_confdb_key_incdec.value))
ret = CS_ERR_ACCESS;
res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec);
res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_INCREMENT;
res_lib_confdb_key_incdec.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec));
}
static void message_handler_req_lib_confdb_key_decrement (void *conn,
const void *message)
{
const struct req_lib_confdb_key_get *req_lib_confdb_key_get = message;
struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
int ret = CS_OK;
if (api->object_key_decrement(req_lib_confdb_key_get->parent_object_handle,
req_lib_confdb_key_get->key_name.value,
req_lib_confdb_key_get->key_name.length,
&res_lib_confdb_key_incdec.value))
ret = CS_ERR_ACCESS;
res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec);
res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_DECREMENT;
res_lib_confdb_key_incdec.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec));
}
static void message_handler_req_lib_confdb_key_replace (void *conn,
const void *message)
{
const struct req_lib_confdb_key_replace *req_lib_confdb_key_replace
= message;
coroipc_response_header_t res;
int ret = CS_OK;
if (api->object_key_replace(req_lib_confdb_key_replace->object_handle,
req_lib_confdb_key_replace->key_name.value,
req_lib_confdb_key_replace->key_name.length,
req_lib_confdb_key_replace->new_value.value,
req_lib_confdb_key_replace->new_value.length))
ret = CS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_KEY_REPLACE;
res.error = ret;
api->ipc_response_send(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_key_delete (void *conn,
const void *message)
{
const struct req_lib_confdb_key_delete *req_lib_confdb_key_delete
= message;
coroipc_response_header_t res;
int ret = CS_OK;
if (api->object_key_delete(req_lib_confdb_key_delete->object_handle,
req_lib_confdb_key_delete->key_name.value,
req_lib_confdb_key_delete->key_name.length))
ret = CS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_KEY_DELETE;
res.error = ret;
api->ipc_response_send(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_object_parent_get (void *conn,
const void *message)
{
const struct req_lib_confdb_object_parent_get
*req_lib_confdb_object_parent_get = message;
struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get;
hdb_handle_t object_handle;
int ret = CS_OK;
if (api->object_parent_get(req_lib_confdb_object_parent_get->object_handle,
&object_handle))
ret = CS_ERR_ACCESS;
res_lib_confdb_object_parent_get.parent_object_handle = object_handle;
res_lib_confdb_object_parent_get.header.size = sizeof(res_lib_confdb_object_parent_get);
res_lib_confdb_object_parent_get.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE;
res_lib_confdb_object_parent_get.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_object_parent_get, sizeof(res_lib_confdb_object_parent_get));
}
static void message_handler_req_lib_confdb_object_name_get (void *conn,
const void *message)
{
const struct req_lib_confdb_object_name_get *request = message;
struct res_lib_confdb_object_name_get response;
int ret = CS_OK;
char object_name[CS_MAX_NAME_LENGTH];
size_t object_name_len;
if (api->object_name_get(request->object_handle,
object_name, &object_name_len)) {
ret = CS_ERR_ACCESS;
}
response.object_name.length = object_name_len;
strncpy((char*)response.object_name.value, object_name, CS_MAX_NAME_LENGTH);
response.object_name.value[CS_MAX_NAME_LENGTH-1] = '\0';
response.header.size = sizeof(response);
response.header.id = MESSAGE_RES_CONFDB_OBJECT_NAME_GET;
response.header.error = ret;
api->ipc_response_send(conn, &response, sizeof(response));
}
static void message_handler_req_lib_confdb_key_iter (void *conn,
const void *message)
{
const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message;
struct res_lib_confdb_key_iter res_lib_confdb_key_iter;
void *key_name;
size_t key_name_len;
void *value;
size_t value_len;
int ret = CS_OK;
if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle,
req_lib_confdb_key_iter->next_entry,
&key_name,
&key_name_len,
&value,
&value_len))
ret = CS_ERR_ACCESS;
else {
memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len);
- memcpy(res_lib_confdb_key_iter.value.value, value, value_len);
+ if (value_len > CS_MAX_NAME_LENGTH) {
+ ret = CS_ERR_TOO_BIG;
+ } else {
+ memcpy(res_lib_confdb_key_iter.value.value, value, value_len);
+ }
res_lib_confdb_key_iter.key_name.length = key_name_len;
res_lib_confdb_key_iter.value.length = value_len;
}
res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter);
res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER;
res_lib_confdb_key_iter.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter));
}
static void message_handler_req_lib_confdb_key_iter_typed (void *conn,
const void *message)
{
const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message;
struct res_lib_confdb_key_iter_typed res_lib_confdb_key_iter;
void *key_name;
size_t key_name_len;
void *value;
size_t value_len;
int ret = CS_OK;
objdb_value_types_t my_type;
if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle,
req_lib_confdb_key_iter->next_entry,
&key_name,
&key_name_len,
&value,
&value_len))
ret = CS_ERR_ACCESS;
else {
memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len);
- memcpy(res_lib_confdb_key_iter.value.value, value, value_len);
+ if (value_len > CS_MAX_NAME_LENGTH) {
+ ret = CS_ERR_TOO_BIG;
+ } else {
+ memcpy(res_lib_confdb_key_iter.value.value, value, value_len);
+ }
res_lib_confdb_key_iter.key_name.length = key_name_len;
res_lib_confdb_key_iter.key_name.value[key_name_len] = '\0';
res_lib_confdb_key_iter.value.length = value_len;
api->object_key_get_typed(req_lib_confdb_key_iter->parent_object_handle,
(const char*)res_lib_confdb_key_iter.key_name.value,
&value,
&value_len,
&my_type);
res_lib_confdb_key_iter.type = my_type;
}
res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter);
res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER_TYPED;
res_lib_confdb_key_iter.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter));
}
+static void message_handler_req_lib_confdb_key_iter_typed2 (void *conn,
+ const void *message)
+{
+ const struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = message;
+ struct res_lib_confdb_key_iter_typed2 res_lib_confdb_key_iter;
+ struct res_lib_confdb_key_iter_typed2 *res = &res_lib_confdb_key_iter;
+ void *key_name;
+ size_t key_name_len;
+ void *value;
+ size_t value_len;
+ int ret = CS_OK;
+ objdb_value_types_t my_type;
+
+ if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle,
+ req_lib_confdb_key_iter->next_entry,
+ &key_name,
+ &key_name_len,
+ &value,
+ &value_len)) {
+ ret = CS_ERR_ACCESS;
+ res->header.size = sizeof(res_lib_confdb_key_iter);
+ }
+ else {
+ res = alloca(sizeof(struct res_lib_confdb_key_iter_typed2) + value_len);
+
+ memcpy(res->key_name.value, key_name, key_name_len);
+ res->key_name.length = key_name_len;
+ res->key_name.value[key_name_len] = '\0';
+ memcpy(&res->value, value, value_len);
+ res->value_length = value_len;
+
+ api->object_key_get_typed(req_lib_confdb_key_iter->parent_object_handle,
+ (const char*)res->key_name.value,
+ &value,
+ &value_len,
+ &my_type);
+ res->type = my_type;
+
+ res->header.size = sizeof(res_lib_confdb_key_iter)+value_len;
+ }
+ res->header.id = MESSAGE_RES_CONFDB_KEY_ITER_TYPED2;
+ res->header.error = ret;
+
+ api->ipc_response_send(conn, res, res->header.size);
+}
+
static void message_handler_req_lib_confdb_object_iter (void *conn,
const void *message)
{
const struct req_lib_confdb_object_iter *req_lib_confdb_object_iter
= message;
struct res_lib_confdb_object_iter res_lib_confdb_object_iter;
size_t object_name_len;
int ret = CS_OK;
if (!req_lib_confdb_object_iter->find_handle) {
if (api->object_find_create(req_lib_confdb_object_iter->parent_object_handle,
NULL, 0,
m2h(&res_lib_confdb_object_iter.find_handle)) == -1) {
ret = CS_ERR_ACCESS;
goto response_send;
}
}
else
res_lib_confdb_object_iter.find_handle = req_lib_confdb_object_iter->find_handle;
if (api->object_find_next(res_lib_confdb_object_iter.find_handle,
m2h(&res_lib_confdb_object_iter.object_handle))) {
ret = CS_ERR_ACCESS;
api->object_find_destroy(res_lib_confdb_object_iter.find_handle);
}
else {
if (api->object_name_get(res_lib_confdb_object_iter.object_handle,
(char *)res_lib_confdb_object_iter.object_name.value,
&object_name_len) == -1) {
ret = CS_ERR_ACCESS;
goto response_send;
} else {
res_lib_confdb_object_iter.object_name.length = object_name_len;
}
}
response_send:
res_lib_confdb_object_iter.header.size = sizeof(res_lib_confdb_object_iter);
res_lib_confdb_object_iter.header.id = MESSAGE_RES_CONFDB_OBJECT_ITER;
res_lib_confdb_object_iter.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_object_iter, sizeof(res_lib_confdb_object_iter));
}
static void message_handler_req_lib_confdb_object_find (void *conn,
const void *message)
{
const struct req_lib_confdb_object_find *req_lib_confdb_object_find
= message;
struct res_lib_confdb_object_find res_lib_confdb_object_find;
int ret = CS_OK;
if (!req_lib_confdb_object_find->find_handle) {
if (api->object_find_create(req_lib_confdb_object_find->parent_object_handle,
req_lib_confdb_object_find->object_name.value,
req_lib_confdb_object_find->object_name.length,
m2h(&res_lib_confdb_object_find.find_handle)) == -1) {
ret = CS_ERR_ACCESS;
goto response_send;
}
}
else
res_lib_confdb_object_find.find_handle = req_lib_confdb_object_find->find_handle;
if (api->object_find_next(res_lib_confdb_object_find.find_handle,
m2h(&res_lib_confdb_object_find.object_handle))) {
ret = CS_ERR_ACCESS;
api->object_find_destroy(res_lib_confdb_object_find.find_handle);
}
response_send:
res_lib_confdb_object_find.header.size = sizeof(res_lib_confdb_object_find);
res_lib_confdb_object_find.header.id = MESSAGE_RES_CONFDB_OBJECT_FIND;
res_lib_confdb_object_find.header.error = ret;
api->ipc_response_send(conn, &res_lib_confdb_object_find, sizeof(res_lib_confdb_object_find));
}
static void message_handler_req_lib_confdb_write (void *conn,
const void *message)
{
struct res_lib_confdb_write res_lib_confdb_write;
int ret = CS_OK;
const char *error_string = NULL;
if (api->object_write_config(&error_string))
ret = CS_ERR_ACCESS;
res_lib_confdb_write.header.size = sizeof(res_lib_confdb_write);
res_lib_confdb_write.header.id = MESSAGE_RES_CONFDB_WRITE;
res_lib_confdb_write.header.error = ret;
if (error_string) {
strcpy((char *)res_lib_confdb_write.error.value, error_string);
res_lib_confdb_write.error.length = strlen(error_string) + 1;
} else
res_lib_confdb_write.error.length = 0;
api->ipc_response_send(conn, &res_lib_confdb_write, sizeof(res_lib_confdb_write));
}
static void message_handler_req_lib_confdb_reload (void *conn,
const void *message)
{
const struct req_lib_confdb_reload *req_lib_confdb_reload = message;
struct res_lib_confdb_reload res_lib_confdb_reload;
int ret = CS_OK;
const char *error_string = NULL;
if (api->object_reload_config(req_lib_confdb_reload->flush, &error_string))
ret = CS_ERR_ACCESS;
res_lib_confdb_reload.header.size = sizeof(res_lib_confdb_reload);
res_lib_confdb_reload.header.id = MESSAGE_RES_CONFDB_RELOAD;
res_lib_confdb_reload.header.error = ret;
if(error_string) {
strcpy((char *)res_lib_confdb_reload.error.value, error_string);
res_lib_confdb_reload.error.length = strlen(error_string) + 1;
} else
res_lib_confdb_reload.error.length = 0;
api->ipc_response_send(conn, &res_lib_confdb_reload, sizeof(res_lib_confdb_reload));
}
static int objdb_notify_dispatch(hdb_handle_t handle,
int fd, int revents, void *data)
{
struct confdb_ipc_message_holder *holder;
ssize_t rc;
char pipe_cmd;
if (revents & POLLHUP) {
return -1;
}
pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex);
retry_read:
rc = read(fd, &pipe_cmd, sizeof(pipe_cmd));
if (rc == sizeof(pipe_cmd)) {
goto retry_read; /* Flush whole buffer */
}
if (rc == -1) {
if (errno == EINTR) {
goto retry_read;
}
if (errno != EAGAIN && errno != EWOULDBLOCK) {
goto unlock_exit;
}
} else {
goto unlock_exit; /* rc != -1 && rc != 1 -> end of file */
}
while (!list_empty (&confdb_ipc_message_holder_list_head)) {
holder = list_entry (confdb_ipc_message_holder_list_head.next,
struct confdb_ipc_message_holder, list);
list_del (&holder->list);
/*
* All list operations are done now, so unlock list mutex to
* prevent deadlock in IPC.
*/
pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex);
api->ipc_dispatch_send(holder->conn, holder->msg, holder->mlen);
api->ipc_refcnt_dec(holder->conn);
free(holder);
/*
* Next operation is again list one, so lock list again.
*/
pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex);
}
unlock_exit:
pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex);
return 0;
}
static int32_t ipc_dispatch_send_from_poll_thread(void *conn, const void *msg, size_t mlen)
{
struct confdb_ipc_message_holder *holder;
ssize_t written;
size_t holder_size;
char pipe_cmd;
api->ipc_refcnt_inc(conn);
holder_size = sizeof (*holder) + mlen;
holder = malloc (holder_size);
if (holder == NULL) {
api->ipc_refcnt_dec(conn);
return -1;
}
memset(holder, 0, holder_size);
holder->conn = conn;
holder->mlen = mlen;
memcpy(holder->msg, msg, mlen);
list_init(&holder->list);
pthread_mutex_lock (&confdb_ipc_message_holder_list_mutex);
list_add_tail (&holder->list, &confdb_ipc_message_holder_list_head);
pipe_cmd = 'M'; /* Message */
retry_write:
written = write(notify_pipe[1], &pipe_cmd, sizeof(pipe_cmd));
if (written == -1) {
if (errno == EINTR) {
goto retry_write;
}
if (errno != EAGAIN && errno != EWOULDBLOCK) {
/*
* Different error then EINTR or BLOCK -> exit with error
*/
goto refcnt_del_unlock_exit;
}
} else if (written != sizeof (pipe_cmd)) {
goto refcnt_del_unlock_exit;
}
pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex);
return 0;
refcnt_del_unlock_exit:
list_del (&holder->list);
free(holder);
api->ipc_refcnt_dec(conn);
pthread_mutex_unlock (&confdb_ipc_message_holder_list_mutex);
return -1;
}
static void confdb_notify_lib_of_key_change(object_change_type_t change_type,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *object_name_pt, size_t object_name_len,
const void *key_name_pt, size_t key_name_len,
const void *key_value_pt, size_t key_value_len,
void *priv_data_pt)
{
- struct res_lib_confdb_key_change_callback res;
+ struct res_lib_confdb_key_change_callback2 *res;
- res.header.size = sizeof(res);
- res.header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK;
- res.header.error = CS_OK;
+ res = alloca(sizeof(struct res_lib_confdb_key_change_callback2) + key_value_len);
+
+ res->header.size = sizeof(struct res_lib_confdb_key_change_callback2) + key_value_len;
+ res->header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK2;
+ res->header.error = CS_OK;
// handle & type
- res.change_type = change_type;
- res.parent_object_handle = parent_object_handle;
- res.object_handle = object_handle;
+ res->change_type = change_type;
+ res->parent_object_handle = parent_object_handle;
+ res->object_handle = object_handle;
//object
- memcpy(res.object_name.value, object_name_pt, object_name_len);
- res.object_name.length = object_name_len;
+ memcpy(res->object_name.value, object_name_pt, object_name_len);
+ res->object_name.length = object_name_len;
//key name
- memcpy(res.key_name.value, key_name_pt, key_name_len);
- res.key_name.length = key_name_len;
+ memcpy(res->key_name.value, key_name_pt, key_name_len);
+ res->key_name.length = key_name_len;
//key value
- memcpy(res.key_value.value, key_value_pt, key_value_len);
- res.key_value.length = key_value_len;
+ memcpy(&res->key_value, key_value_pt, key_value_len);
+ res->key_value_length = key_value_len;
- ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res));
+ ipc_dispatch_send_from_poll_thread(priv_data_pt, res, res->header.size);
}
static void confdb_notify_lib_of_new_object(hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *name_pt, size_t name_len,
void *priv_data_pt)
{
struct res_lib_confdb_object_create_callback res;
res.header.size = sizeof(res);
res.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK;
res.header.error = CS_OK;
res.parent_object_handle = parent_object_handle;
res.object_handle = object_handle;
memcpy(res.name.value, name_pt, name_len);
res.name.length = name_len;
ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res));
}
static void confdb_notify_lib_of_destroyed_object(
hdb_handle_t parent_object_handle,
const void *name_pt, size_t name_len,
void *priv_data_pt)
{
struct res_lib_confdb_object_destroy_callback res;
res.header.size = sizeof(res);
res.header.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK;
res.header.error = CS_OK;
res.parent_object_handle = parent_object_handle;
memcpy(res.name.value, name_pt, name_len);
res.name.length = name_len;
ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res));
}
static void confdb_notify_lib_of_reload(objdb_reload_notify_type_t notify_type,
int flush,
void *priv_data_pt)
{
struct res_lib_confdb_reload_callback res;
res.header.size = sizeof(res);
res.header.id = MESSAGE_RES_CONFDB_RELOAD_CALLBACK;
res.header.error = CS_OK;
res.type = notify_type;
ipc_dispatch_send_from_poll_thread(priv_data_pt, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_track_start (void *conn,
const void *message)
{
const struct req_lib_confdb_object_track_start *req = message;
coroipc_response_header_t res;
api->object_track_start(req->object_handle,
req->flags,
confdb_notify_lib_of_key_change,
confdb_notify_lib_of_new_object,
confdb_notify_lib_of_destroyed_object,
confdb_notify_lib_of_reload,
conn);
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_TRACK_START;
res.error = CS_OK;
api->ipc_response_send(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_track_stop (void *conn,
const void *message)
{
coroipc_response_header_t res;
api->object_track_stop(confdb_notify_lib_of_key_change,
confdb_notify_lib_of_new_object,
confdb_notify_lib_of_destroyed_object,
confdb_notify_lib_of_reload,
conn);
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_TRACK_STOP;
res.error = CS_OK;
api->ipc_response_send(conn, &res, sizeof(res));
}
+
+static void message_handler_req_lib_confdb_key_create_typed2 (void *conn,
+ const void *message)
+{
+ const struct req_lib_confdb_key_create_typed2 *req_lib_confdb_key_create
+ = message;
+ coroipc_response_header_t res;
+ int ret = CS_OK;
+
+ if (api->object_key_create_typed(req_lib_confdb_key_create->object_handle,
+ (char*)req_lib_confdb_key_create->key_name.value,
+ &req_lib_confdb_key_create->value,
+ req_lib_confdb_key_create->value_length,
+ req_lib_confdb_key_create->type))
+ ret = CS_ERR_ACCESS;
+
+ res.size = sizeof(res);
+ res.id = MESSAGE_RES_CONFDB_KEY_CREATE;
+ res.error = ret;
+ api->ipc_response_send(conn, &res, sizeof(res));
+}
+
+
+static void message_handler_req_lib_confdb_key_replace2 (void *conn,
+ const void *message)
+{
+ const struct req_lib_confdb_key_replace2 *req_lib_confdb_key_replace
+ = message;
+ coroipc_response_header_t res;
+ int ret = CS_OK;
+
+ if (api->object_key_replace(req_lib_confdb_key_replace->object_handle,
+ req_lib_confdb_key_replace->key_name.value,
+ req_lib_confdb_key_replace->key_name.length,
+ &req_lib_confdb_key_replace->new_value,
+ req_lib_confdb_key_replace->new_value_length))
+ ret = CS_ERR_ACCESS;
+
+ res.size = sizeof(res);
+ res.id = MESSAGE_RES_CONFDB_KEY_REPLACE;
+ res.error = ret;
+ api->ipc_response_send(conn, &res, sizeof(res));
+}
diff --git a/tools/corosync-objctl.c b/tools/corosync-objctl.c
index d7909bb2..3e2bd4c8 100644
--- a/tools/corosync-objctl.c
+++ b/tools/corosync-objctl.c
@@ -1,936 +1,945 @@
/*
* Copyright (c) 2008 Allied Telesis Labs NZ
+ * (c) 2012 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Angus Salkeld <angus.salkeld@alliedtelesis.co.nz>
*
* 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.
*/
#include <config.h>
#include <sys/select.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/un.h>
#include <corosync/corotypes.h>
#include <corosync/confdb.h>
#define SEPERATOR '.'
#define SEPERATOR_STR "."
-#define OBJ_NAME_SIZE 512
+#define OBJ_NAME_SIZE 4096
typedef enum {
ACTION_READ,
ACTION_WRITE,
ACTION_CREATE,
ACTION_CREATE_KEY,
ACTION_DELETE,
ACTION_PRINT_ALL,
ACTION_PRINT_DEFAULT,
ACTION_TRACK,
} action_types_t;
typedef enum {
FIND_OBJECT_ONLY,
FIND_OBJECT_OR_KEY,
FIND_KEY_ONLY
} find_object_of_type_t;
static void tail_key_changed(confdb_handle_t handle,
confdb_change_type_t change_type,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *object_name,
size_t object_name_len,
const void *key_name,
size_t key_name_len,
const void *key_value,
size_t key_value_len);
static void tail_object_created(confdb_handle_t handle,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *name_pt,
size_t name_len);
static void tail_object_deleted(confdb_handle_t handle,
hdb_handle_t parent_object_handle,
const void *name_pt,
size_t name_len);
static void create_object(confdb_handle_t handle, char * name_pt);
static void create_object_key(confdb_handle_t handle, char * name_pt);
static void write_key(confdb_handle_t handle, char * path_pt);
static void get_parent_name(const char * name_pt, char * parent_name);
static confdb_callbacks_t callbacks = {
.confdb_key_change_notify_fn = tail_key_changed,
.confdb_object_create_change_notify_fn = tail_object_created,
.confdb_object_delete_change_notify_fn = tail_object_deleted,
};
static int debug = 0;
static int show_binary = 0;
static int action;
static void print_binary_key (char *value, size_t value_len)
{
size_t i;
char c;
for (i = 0; i < value_len; i++) {
c = value[i];
if (c >= ' ' && c < 0x7f && c != '\\') {
fputc (c, stdout);
} else {
if (c == '\\') {
printf ("\\\\");
} else {
printf ("\\x%02X", c);
}
}
}
printf ("\n");
}
static void print_key (char *key_name, void *value, size_t value_len, confdb_value_types_t type)
{
switch (type) {
case CONFDB_VALUETYPE_INT16:
printf ("%s=%hd\n", key_name,
*(int16_t*)value);
break;
case CONFDB_VALUETYPE_UINT16:
printf ("%s=%hu\n", key_name,
*(uint16_t*)value);
break;
case CONFDB_VALUETYPE_INT32:
printf ("%s=%d\n", key_name,
*(int32_t*)value);
break;
case CONFDB_VALUETYPE_UINT32:
printf ("%s=%u\n", key_name,
*(uint32_t*)value);
break;
case CONFDB_VALUETYPE_INT64:
printf ("%s=%"PRIi64"\n", key_name,
*(int64_t*)value);
break;
case CONFDB_VALUETYPE_UINT64:
printf ("%s=%"PRIu64"\n", key_name,
*(uint64_t*)value);
break;
case CONFDB_VALUETYPE_FLOAT:
printf ("%s=%f\n", key_name,
*(float*)value);
break;
case CONFDB_VALUETYPE_DOUBLE:
printf ("%s=%f\n", key_name,
*(double*)value);
break;
case CONFDB_VALUETYPE_STRING:
printf ("%s=%s\n", key_name, (char*)value);
break;
default:
case CONFDB_VALUETYPE_ANY:
if (!show_binary) {
printf ("%s=**binary**(%d)\n", key_name, type);
} else {
printf ("%s=", key_name);
print_binary_key ((char *)value, value_len);
}
break;
}
}
/* Recursively dump the object tree */
static void print_config_tree(confdb_handle_t handle, hdb_handle_t parent_object_handle, char * parent_name)
{
hdb_handle_t object_handle;
char object_name[OBJ_NAME_SIZE];
size_t object_name_len;
char key_name[OBJ_NAME_SIZE];
- char key_value[OBJ_NAME_SIZE];
+ char output_string[OBJ_NAME_SIZE];
+ char *key_value=NULL;/* Dynamically allocated value */
size_t key_value_len;
cs_error_t res;
int children_printed;
confdb_value_types_t type;
/* Show the keys */
res = confdb_key_iter_start(handle, parent_object_handle);
if (res != CS_OK) {
fprintf(stderr, "error resetting key iterator for object "HDB_X_FORMAT" %d\n", parent_object_handle, res);
exit(EXIT_FAILURE);
}
children_printed = 0;
- while ( (res = confdb_key_iter_typed(handle,
+ while ( (res = confdb_key_iter_typed2(handle,
parent_object_handle,
key_name,
- key_value,
+ (void**)&key_value,
&key_value_len,
&type)) == CS_OK) {
key_value[key_value_len] = '\0';
if (parent_name != NULL)
printf("%s%c", parent_name, SEPERATOR);
print_key(key_name, key_value, key_value_len, type);
+ free(key_value);
+ key_value = NULL;
children_printed++;
}
/* Show sub-objects */
res = confdb_object_iter_start(handle, parent_object_handle);
if (res != CS_OK) {
fprintf(stderr, "error resetting object iterator for object "HDB_X_FORMAT" %d\n", parent_object_handle, res);
exit(EXIT_FAILURE);
}
while ( (res = confdb_object_iter(handle,
parent_object_handle,
&object_handle,
object_name,
&object_name_len)) == CS_OK) {
object_name[object_name_len] = '\0';
if (parent_name != NULL) {
- snprintf(key_value, OBJ_NAME_SIZE, "%s%c%s", parent_name, SEPERATOR, object_name);
+ snprintf(output_string, OBJ_NAME_SIZE, "%s%c%s", parent_name, SEPERATOR, object_name);
} else {
if ((action == ACTION_PRINT_DEFAULT) && strcmp(object_name, "internal_configuration") == 0) continue;
- snprintf(key_value, OBJ_NAME_SIZE, "%s", object_name);
+ snprintf(output_string, OBJ_NAME_SIZE, "%s", object_name);
}
- print_config_tree(handle, object_handle, key_value);
+ print_config_tree(handle, object_handle, output_string);
children_printed++;
}
if (children_printed == 0 && parent_name != NULL) {
printf("%s\n", parent_name);
}
}
static cs_error_t reload_db(confdb_handle_t handle)
{
char error[1024];
cs_error_t ret;
ret = confdb_reload(handle, 0, error, sizeof(error) - 1);
if (ret != CONFDB_OK) {
fprintf (stderr, "Error reloading DB %d\n", ret);
}
return ret;
}
static int read_in_config_file (char * filename)
{
confdb_handle_t handle;
int result;
int ignore;
int c;
FILE* fh;
char buf[1024];
char * line;
char * end;
char parent_name[OBJ_NAME_SIZE];
if (access (filename, R_OK) != 0) {
perror ("Couldn't access file.");
return -1;
}
fh = fopen(filename, "r");
if (fh == NULL) {
perror ("Couldn't open file.");
return -1;
}
result = confdb_initialize (&handle, &callbacks);
if (result != CONFDB_OK) {
fprintf (stderr, "Could not initialize objdb library. Error %d\n", result);
fclose (fh);
return -1;
}
while (fgets (buf, 1024, fh) != NULL) {
/* find the first real character, if it is
* a '#' then ignore this line.
* else process.
* if no real characters then also ignore.
*/
ignore = 1;
for (c = 0; c < 1024; c++) {
if (isblank (buf[c]))
continue;
if (buf[c] == '#' || buf[c] == '\n') {
ignore = 1;
break;
}
ignore = 0;
line = &buf[c];
break;
}
if (ignore == 1)
continue;
/* kill the \n */
end = strchr (line, '\n');
if (end != NULL)
*end = '\0';
if (debug == 2)
printf ("%d: %s\n", __LINE__, line);
/* find the parent object */
get_parent_name(line, parent_name);
if (debug == 2)
printf ("%d: %s\n", __LINE__, parent_name);
/* create the object */
create_object (handle, parent_name);
/* write the attribute */
write_key (handle, line);
}
reload_db(handle);
confdb_finalize (handle);
fclose (fh);
return 0;
}
static int print_all(void)
{
confdb_handle_t handle;
int result;
result = confdb_initialize (&handle, &callbacks);
if (result != CS_OK) {
fprintf (stderr, "Could not initialize objdb library. Error %d\n", result);
return 1;
}
print_config_tree(handle, OBJECT_PARENT_HANDLE, NULL);
result = confdb_finalize (handle);
return 0;
}
static int print_help(void)
{
printf("\n");
printf ("usage: corosync-objctl [-b] object%ckey ... Print an object\n", SEPERATOR);
printf (" corosync-objctl -c object%cchild_obj ... Create Object\n", SEPERATOR);
printf (" corosync-objctl -d object%cchild_obj ... Delete object\n", SEPERATOR);
printf (" corosync-objctl -w object%cchild_obj.key=value ... Create a key\n", SEPERATOR);
printf (" corosync-objctl -n object%cchild_obj.key=value ... Create a new object with the key\n", SEPERATOR);
printf (" corosync-objctl -t object%cchild_obj ... Track changes\n", SEPERATOR);
printf (" corosync-objctl [-b] -a Print all objects\n");
printf (" corosync-objctl -p <filename> Load in config from the specified file.\n");
printf("\n");
return 0;
}
static cs_error_t validate_name(char * obj_name_pt)
{
if ((strchr (obj_name_pt, SEPERATOR) == NULL) &&
(strchr (obj_name_pt, '=') == NULL))
return CS_OK;
else
return CS_ERR_INVALID_PARAM;
}
static void get_parent_name(const char * name_pt, char * parent_name)
{
char * tmp;
strcpy(parent_name, name_pt);
/* first remove the value (it could be a file path */
tmp = strchr(parent_name, '=');
if (tmp != NULL) {
*tmp = '\0';
tmp--;
while (isblank (*tmp)) {
*tmp = '\0';
tmp--;
}
}
/* then truncate the child name */
tmp = strrchr(parent_name, SEPERATOR);
if (tmp != NULL) *tmp = '\0';
}
static void get_key(const char * name_pt, char * key_name, char * key_value)
{
char * tmp = (char*)name_pt;
char str_copy[OBJ_NAME_SIZE];
char * copy_tmp = str_copy;
int equals_seen = 0;
int in_quotes = 0;
/* strip out spaces when not in quotes */
while (*tmp != '\0') {
if (*tmp == '=')
equals_seen = 1;
if (equals_seen && *tmp == '"') {
if (in_quotes)
in_quotes = 0;
else
in_quotes = 1;
}
if (*tmp != ' ' || in_quotes) {
*copy_tmp = *tmp;
copy_tmp++;
}
tmp++;
}
*copy_tmp = '\0';
/* first remove the value (it could have a SEPERATOR in it */
tmp = strchr(str_copy, '=');
if (tmp != NULL && strlen(tmp) > 0) {
strcpy(key_value, tmp+1);
*tmp = '\0';
} else {
key_value[0] = '\0';
}
/* then remove the name */
tmp = strrchr(str_copy, SEPERATOR);
if (tmp == NULL) tmp = str_copy;
strcpy(key_name, tmp+1);
}
static cs_error_t find_object (confdb_handle_t handle,
char * name_pt,
find_object_of_type_t type,
hdb_handle_t * out_handle)
{
char * obj_name_pt;
char * save_pt;
hdb_handle_t obj_handle;
confdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE;
char tmp_name[OBJ_NAME_SIZE];
cs_error_t res = CS_OK;
strncpy (tmp_name, name_pt, sizeof (tmp_name));
tmp_name[sizeof (tmp_name) - 1] = '\0';
obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt);
while (obj_name_pt != NULL) {
res = confdb_object_find_start(handle, parent_object_handle);
if (res != CS_OK) {
fprintf (stderr, "Could not start object_find %d\n", res);
exit (EXIT_FAILURE);
}
res = confdb_object_find(handle, parent_object_handle,
obj_name_pt, strlen (obj_name_pt), &obj_handle);
if (res != CS_OK) {
return res;
}
parent_object_handle = obj_handle;
obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt);
}
*out_handle = parent_object_handle;
return res;
}
static void read_object(confdb_handle_t handle, char * name_pt)
{
char parent_name[OBJ_NAME_SIZE];
hdb_handle_t obj_handle;
cs_error_t res;
get_parent_name(name_pt, parent_name);
res = find_object (handle, name_pt, FIND_OBJECT_OR_KEY, &obj_handle);
if (res == CS_OK) {
print_config_tree(handle, obj_handle, parent_name);
}
}
static void write_key(confdb_handle_t handle, char * path_pt)
{
hdb_handle_t obj_handle;
char parent_name[OBJ_NAME_SIZE];
char key_name[OBJ_NAME_SIZE];
char key_value[OBJ_NAME_SIZE];
char old_key_value[OBJ_NAME_SIZE];
+ char *old_key_value_ptr = old_key_value;
size_t old_key_value_len;
cs_error_t res;
confdb_value_types_t type;
/* find the parent object */
get_parent_name(path_pt, parent_name);
get_key(path_pt, key_name, key_value);
if (debug == 1)
printf ("%d: key:\"%s\", value:\"%s\"\n",
__LINE__, key_name, key_value);
if (validate_name(key_name) != CS_OK) {
fprintf(stderr, "Incorrect key name, can not have \"=\" or \"%c\"\n", SEPERATOR);
exit(EXIT_FAILURE);
}
res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle);
if (res != CS_OK) {
fprintf(stderr, "Can't find parent object of \"%s\"\n", path_pt);
exit(EXIT_FAILURE);
}
/* get the current key */
- res = confdb_key_get_typed (handle,
+ res = confdb_key_get_typed2 (handle,
obj_handle,
key_name,
- old_key_value,
+ (void**)&old_key_value_ptr,
&old_key_value_len, &type);
+ if (debug == 1 && res==CS_OK)
+ printf ("%d: key:\"%s\", old value:\"%s\"\n",
+ __LINE__, key_name, old_key_value);
+
if (res == CS_OK) {
/* replace the current value */
res = confdb_key_replace (handle,
obj_handle,
key_name,
strlen(key_name),
old_key_value,
old_key_value_len,
key_value,
strlen(key_value)+1);
if (res != CS_OK)
fprintf(stderr, "Failed to replace the key %s=%s. Error %d\n", key_name, key_value, res);
} else {
/* not there, create a new key */
res = confdb_key_create_typed (handle,
obj_handle,
key_name,
key_value,
strlen(key_value)+1,
CONFDB_VALUETYPE_STRING);
if (res != CS_OK)
fprintf(stderr, "Failed to create the key %s=%s. Error %d\n", key_name, key_value, res);
}
}
static void create_object(confdb_handle_t handle, char * name_pt)
{
char * obj_name_pt;
char * save_pt;
hdb_handle_t obj_handle;
hdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE;
char tmp_name[OBJ_NAME_SIZE];
cs_error_t res;
strncpy (tmp_name, name_pt, sizeof (tmp_name));
tmp_name[sizeof (tmp_name) - 1] = '\0';
obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt);
while (obj_name_pt != NULL) {
res = confdb_object_find_start(handle, parent_object_handle);
if (res != CS_OK) {
fprintf (stderr, "Could not start object_find %d\n", res);
exit (EXIT_FAILURE);
}
res = confdb_object_find(handle, parent_object_handle,
obj_name_pt, strlen (obj_name_pt), &obj_handle);
if (res != CS_OK) {
if (validate_name(obj_name_pt) != CS_OK) {
fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n",
obj_name_pt);
exit(EXIT_FAILURE);
}
if (debug)
printf ("%s:%d: %s\n", __func__,__LINE__, obj_name_pt);
res = confdb_object_create (handle,
parent_object_handle,
obj_name_pt,
strlen (obj_name_pt),
&obj_handle);
if (res != CS_OK)
fprintf(stderr, "Failed to create object \"%s\". Error %d.\n",
obj_name_pt, res);
}
parent_object_handle = obj_handle;
obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt);
}
}
static void create_object_key(confdb_handle_t handle, char *name_pt)
{
char * obj_name_pt;
char * new_obj_name_pt;
char * save_pt;
hdb_handle_t obj_handle;
hdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE;
char tmp_name[OBJ_NAME_SIZE];
cs_error_t res;
char parent_name[OBJ_NAME_SIZE];
char key_name[OBJ_NAME_SIZE];
char key_value[OBJ_NAME_SIZE];
get_parent_name(name_pt, parent_name);
get_key(name_pt, key_name, key_value);
strncpy (tmp_name, parent_name, sizeof (tmp_name));
tmp_name[sizeof (tmp_name) - 1] = '\0';
obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt);
/*
* Create parent object tree
*/
while (obj_name_pt != NULL) {
res = confdb_object_find_start(handle, parent_object_handle);
if (res != CS_OK) {
fprintf (stderr, "Could not start object_find %d\n", res);
exit (EXIT_FAILURE);
}
new_obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt);
res = confdb_object_find(handle, parent_object_handle,
obj_name_pt, strlen (obj_name_pt), &obj_handle);
if (res != CS_OK || new_obj_name_pt == NULL) {
if (validate_name(obj_name_pt) != CS_OK) {
fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n",
obj_name_pt);
exit(EXIT_FAILURE);
}
if (debug)
printf ("%s:%d: %s\n", __func__,__LINE__, obj_name_pt);
res = confdb_object_create (handle,
parent_object_handle,
obj_name_pt,
strlen (obj_name_pt),
&obj_handle);
if (res != CS_OK) {
fprintf(stderr, "Failed to create object \"%s\". Error %d.\n",
obj_name_pt, res);
}
}
parent_object_handle = obj_handle;
obj_name_pt = new_obj_name_pt;
}
/*
* Create key
*/
res = confdb_key_create_typed (handle,
obj_handle,
key_name,
key_value,
strlen(key_value)+1,
CONFDB_VALUETYPE_STRING);
if (res != CS_OK) {
fprintf(stderr,
"Failed to create the key %s=%s. Error %d\n",
key_name, key_value, res);
}
}
/* Print "?" in place of any non-printable byte of OBJ. */
static void print_name (FILE *fp, const void *obj, size_t obj_len)
{
const char *p = obj;
size_t i;
for (i = 0; i < obj_len; i++) {
int c = *p++;
if (!isprint (c)) {
c = '?';
}
fputc (c, fp);
}
}
static void tail_key_changed(confdb_handle_t handle,
confdb_change_type_t change_type,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *object_name_pt,
size_t object_name_len,
const void *key_name_pt,
size_t key_name_len,
const void *key_value_pt,
size_t key_value_len)
{
/* printf("key_changed> %.*s.%.*s=%.*s\n", */
fputs("key_changed> ", stdout);
print_name (stdout, object_name_pt, object_name_len);
fputs(".", stdout);
print_name (stdout, key_name_pt, key_name_len);
fputs("=", stdout);
print_name (stdout, key_value_pt, key_value_len);
fputs("\n", stdout);
}
static void tail_object_created(confdb_handle_t handle,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *name_pt,
size_t name_len)
{
fputs("object_created>", stdout);
print_name(stdout, name_pt, name_len);
fputs("\n", stdout);
}
static void tail_object_deleted(confdb_handle_t handle,
hdb_handle_t parent_object_handle,
const void *name_pt,
size_t name_len)
{
fputs("object_deleted>", stdout);
print_name(stdout, name_pt, name_len);
fputs("\n", stdout);
}
static void listen_for_object_changes(confdb_handle_t handle)
{
int result;
fd_set read_fds;
int select_fd;
int quit = CS_FALSE;
FD_ZERO (&read_fds);
if (confdb_fd_get (handle, &select_fd) != CS_OK) {
printf ("can't get the confdb selector object.\n");
return;
}
printf ("Type \"q\" to finish\n");
do {
FD_SET (select_fd, &read_fds);
FD_SET (STDIN_FILENO, &read_fds);
result = select (select_fd + 1, &read_fds, 0, 0, 0);
if (result == -1) {
perror ("select\n");
}
if (FD_ISSET (STDIN_FILENO, &read_fds)) {
char inbuf[3];
if (fgets(inbuf, sizeof(inbuf), stdin) == NULL)
quit = CS_TRUE;
else if (strncmp(inbuf, "q", 1) == 0)
quit = CS_TRUE;
}
if (FD_ISSET (select_fd, &read_fds)) {
if (confdb_dispatch (handle, CONFDB_DISPATCH_ALL) != CS_OK)
exit(1);
}
} while (result && quit == CS_FALSE);
(void)confdb_stop_track_changes(handle);
}
static void track_object(confdb_handle_t handle, char * name_pt)
{
cs_error_t res;
hdb_handle_t obj_handle;
res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle);
if (res != CS_OK) {
fprintf (stderr, "Could not find object \"%s\". Error %d\n",
name_pt, res);
return;
}
res = confdb_track_changes (handle, obj_handle, CONFDB_TRACK_DEPTH_RECURSIVE);
if (res != CS_OK) {
fprintf (stderr, "Could not enable tracking on object \"%s\". Error %d\n",
name_pt, res);
return;
}
}
static void stop_tracking(confdb_handle_t handle)
{
cs_error_t res;
res = confdb_stop_track_changes (handle);
if (res != CS_OK) {
fprintf (stderr, "Could not stop tracking. Error %d\n", res);
return;
}
}
static void delete_object(confdb_handle_t handle, char * name_pt)
{
cs_error_t res;
hdb_handle_t obj_handle;
res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle);
if (res == CS_OK) {
res = confdb_object_destroy (handle, obj_handle);
if (res != CS_OK)
fprintf(stderr, "Failed to find object \"%s\" to delete. Error %d\n", name_pt, res);
} else {
char parent_name[OBJ_NAME_SIZE];
char key_name[OBJ_NAME_SIZE];
char key_value[OBJ_NAME_SIZE];
/* find the parent object */
get_parent_name(name_pt, parent_name);
get_key(name_pt, key_name, key_value);
res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle);
if (res != CS_OK) {
fprintf(stderr, "Failed to find the key's parent object \"%s\". Error %d\n", parent_name, res);
exit (EXIT_FAILURE);
}
res = confdb_key_delete (handle,
obj_handle,
key_name,
strlen(key_name),
key_value,
strlen(key_value));
if (res != CS_OK)
fprintf(stderr, "Failed to delete key \"%s=%s\" from object \"%s\". Error %d\n",
key_name, key_value, parent_name, res);
}
}
int main (int argc, char *argv[]) {
confdb_handle_t handle;
cs_error_t result;
int c;
action = ACTION_READ;
for (;;){
c = getopt (argc,argv,"habwncvdtp:");
if (c==-1) {
break;
}
switch (c) {
case 'v':
debug++;
break;
case 'h':
return print_help();
break;
case 'a':
action = ACTION_PRINT_ALL;
break;
case 'b':
show_binary++;
break;
case 'p':
return read_in_config_file (optarg);
break;
case 'c':
action = ACTION_CREATE;
break;
case 'd':
action = ACTION_DELETE;
break;
case 'w':
action = ACTION_WRITE;
break;
case 'n':
action = ACTION_CREATE_KEY;
break;
case 't':
action = ACTION_TRACK;
break;
default :
action = ACTION_READ;
break;
}
}
if (argc == 1) {
action = ACTION_PRINT_DEFAULT;
return print_all();
} else if (action == ACTION_PRINT_ALL) {
return print_all();
} else if (optind >= argc) {
fprintf(stderr, "Expected an object path after options\n");
exit(EXIT_FAILURE);
}
result = confdb_initialize (&handle, &callbacks);
if (result != CS_OK) {
fprintf (stderr, "Failed to initialize the objdb API. Error %d\n", result);
exit (EXIT_FAILURE);
}
while (optind < argc) {
switch (action) {
case ACTION_READ:
read_object(handle, argv[optind++]);
break;
case ACTION_WRITE:
write_key(handle, argv[optind++]);
break;
case ACTION_CREATE:
create_object(handle, argv[optind++]);
break;
case ACTION_CREATE_KEY:
create_object_key(handle, argv[optind++]);
break;
case ACTION_DELETE:
delete_object(handle, argv[optind++]);
break;
case ACTION_TRACK:
track_object(handle, argv[optind++]);
break;
}
}
if (action == ACTION_TRACK) {
listen_for_object_changes(handle);
stop_tracking(handle);
} else {
reload_db(handle);
}
result = confdb_finalize (handle);
if (result != CS_OK) {
fprintf (stderr, "Error finalizing objdb API. Error %d\n", result);
exit(EXIT_FAILURE);
}
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Sep 22, 11:00 PM (15 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2403365
Default Alt Text
(159 KB)

Event Timeline