Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F7989027
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
164 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/exec/apidef.c b/exec/apidef.c
index 8105a519..c04c586c 100644
--- a/exec/apidef.c
+++ b/exec/apidef.c
@@ -1,110 +1,112 @@
/*
* Copyright (c) 2008 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@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.
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "swab.h"
#include "totem.h"
#include "util.h"
#include "logsys.h"
#include "timer.h"
#include "totempg.h"
#include "totemip.h"
#include "main.h"
#include "ipc.h"
#include "../include/coroapi.h"
#include "service.h"
LOGSYS_DECLARE_SUBSYS ("APIDEF", LOG_INFO);
static struct corosync_api_v1 apidef_corosync_api_v1 = {
.timer_add_duration = openais_timer_add_duration,
.timer_add_absolute = openais_timer_add_absolute,
.timer_delete = openais_timer_delete,
.timer_time_get = NULL,
.ipc_source_set = message_source_set,
.ipc_source_is_local = message_source_is_local,
.ipc_private_data_get = openais_conn_private_data_get,
.ipc_response_send = NULL,
.ipc_dispatch_send = NULL,
.ipc_conn_send_response = openais_conn_send_response,
.ipc_conn_partner_get = openais_conn_partner_get,
.ipc_refcnt_inc = openais_ipc_flow_control_local_increment,
.ipc_refcnt_dec = openais_ipc_flow_control_local_decrement,
.ipc_fc_create = openais_ipc_flow_control_create,
.ipc_fc_destroy = openais_ipc_flow_control_destroy,
.totem_nodeid_get = totempg_my_nodeid_get,
.totem_family_get = totempg_my_family_get,
.totem_ring_reenable = totempg_ring_reenable,
.totem_mcast = main_mcast,
.totem_send_ok = main_send_ok,
.totem_ifaces_get = totempg_ifaces_get,
.totem_ifaces_print = totempg_ifaces_print,
.totem_ip_print = totemip_print,
.service_link_and_init = openais_service_link_and_init,
.service_unlink_and_exit = openais_service_unlink_and_exit,
.error_memory_failure = NULL
};
void apidef_init (struct objdb_iface_ver0 *objdb) {
apidef_corosync_api_v1.object_create = objdb->object_create;
apidef_corosync_api_v1.object_priv_set = objdb->object_priv_set;
apidef_corosync_api_v1.object_key_create = objdb->object_key_create;
apidef_corosync_api_v1.object_destroy = objdb->object_destroy;
apidef_corosync_api_v1.object_valid_set = objdb->object_valid_set;
apidef_corosync_api_v1.object_key_valid_set = objdb->object_key_valid_set;
apidef_corosync_api_v1.object_find_create = objdb->object_find_create;
apidef_corosync_api_v1.object_find_next = objdb->object_find_next;
apidef_corosync_api_v1.object_find_destroy = objdb->object_find_destroy;
apidef_corosync_api_v1.object_key_get = objdb->object_key_get;
apidef_corosync_api_v1.object_priv_get = objdb->object_priv_get;
apidef_corosync_api_v1.object_key_replace = objdb->object_key_replace;
apidef_corosync_api_v1.object_key_delete = objdb->object_key_delete;
apidef_corosync_api_v1.object_iter_reset = objdb->object_iter_reset;
apidef_corosync_api_v1.object_iter = objdb->object_iter;
apidef_corosync_api_v1.object_key_iter = objdb->object_key_iter;
apidef_corosync_api_v1.object_parent_get = objdb->object_parent_get;
apidef_corosync_api_v1.object_dump = objdb->object_dump;
apidef_corosync_api_v1.object_find_from = objdb->object_find_from;
apidef_corosync_api_v1.object_iter_from = objdb->object_iter_from;
apidef_corosync_api_v1.object_key_iter_from = objdb->object_key_iter_from;
+ apidef_corosync_api_v1.object_track_start = objdb->object_track_start;
+ apidef_corosync_api_v1.object_track_stop = objdb->object_track_stop;
apidef_corosync_api_v1.object_write_config = objdb->object_write_config;
}
struct corosync_api_v1 *apidef_get (void)
{
return (&apidef_corosync_api_v1);
}
diff --git a/exec/objdb.c b/exec/objdb.c
index 785aff97..a2cc8886 100644
--- a/exec/objdb.c
+++ b/exec/objdb.c
@@ -1,1210 +1,1472 @@
/*
* Copyright (c) 2006 MontaVista Software, Inc.
* Copyright (c) 2007-2008 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@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.
*/
#include <stdio.h>
#include <errno.h>
#include "objdb.h"
#include "config.h"
#include "main.h"
#include "../lcr/lcr_comp.h"
#include "../include/hdb.h"
#include "../include/list.h"
struct object_key {
void *key_name;
int key_len;
void *value;
int value_len;
struct list_head list;
};
+struct object_tracker {
+ unsigned int object_handle;
+ void * data_pt;
+ object_track_depth_t depth;
+ object_key_change_notify_fn_t key_change_notify_fn;
+ object_create_notify_fn_t object_create_notify_fn;
+ object_destroy_notify_fn_t object_destroy_notify_fn;
+ struct list_head tracker_list;
+ struct list_head object_list;
+};
+
struct object_instance {
void *object_name;
int object_name_len;
unsigned int object_handle;
unsigned int parent_handle;
struct list_head key_head;
struct list_head child_head;
struct list_head child_list;
struct list_head *find_child_list;
struct list_head *iter_key_list;
struct list_head *iter_list;
void *priv;
struct object_valid *object_valid_list;
int object_valid_list_entries;
struct object_key_valid *object_key_valid_list;
int object_key_valid_list_entries;
+ struct list_head track_head;
};
struct object_find_instance {
struct list_head *find_child_list;
struct list_head *child_head;
void *object_name;
int object_len;
};
struct objdb_iface_ver0 objdb_iface;
+struct list_head objdb_trackers_head;
static struct hdb_handle_database object_instance_database = {
.handle_count = 0,
.handles = 0,
.iterator = 0,
.mutex = PTHREAD_MUTEX_INITIALIZER
};
static struct hdb_handle_database object_find_instance_database = {
.handle_count = 0,
.handles = 0,
.iterator = 0,
.mutex = PTHREAD_MUTEX_INITIALIZER
};
static int objdb_init (void)
{
unsigned int handle;
struct object_instance *instance;
unsigned int res;
res = hdb_handle_create (&object_instance_database,
sizeof (struct object_instance), &handle);
if (res != 0) {
goto error_exit;
}
res = hdb_handle_get (&object_instance_database,
handle, (void *)&instance);
if (res != 0) {
goto error_destroy;
}
instance->find_child_list = &instance->child_head;
instance->object_name = "parent";
instance->object_name_len = strlen ("parent");
instance->object_handle = handle;
instance->priv = NULL;
instance->object_valid_list = NULL;
instance->object_valid_list_entries = 0;
list_init (&instance->key_head);
list_init (&instance->child_head);
list_init (&instance->child_list);
+ list_init (&instance->track_head);
+ list_init (&objdb_trackers_head);
hdb_handle_put (&object_instance_database, handle);
return (0);
error_destroy:
hdb_handle_destroy (&object_instance_database, handle);
error_exit:
return (-1);
}
+static int _object_notify_deleted_children(struct object_instance *parent_pt)
+{
+ struct list_head *list;
+ struct list_head *notify_list;
+ int res;
+ struct object_instance *obj_pt = NULL;
+ struct object_tracker * tracker_pt;
+
+ for (list = parent_pt->child_head.next;
+ list != &parent_pt->child_head; list = list->next) {
+
+ obj_pt = list_entry(list, struct object_instance,
+ child_list);
+ res = _object_notify_deleted_children(obj_pt);
+ if (res)
+ return res;
+
+ for (notify_list = obj_pt->track_head.next;
+ notify_list != &obj_pt->track_head;
+ notify_list = notify_list->next) {
+
+ tracker_pt = list_entry (notify_list, struct object_tracker, object_list);
+
+ if ((tracker_pt != NULL) &&
+ (tracker_pt->object_destroy_notify_fn != NULL))
+ tracker_pt->object_destroy_notify_fn(parent_pt->object_handle,
+ obj_pt->object_name,
+ obj_pt->object_name_len,
+ tracker_pt->data_pt);
+ }
+ }
+
+ return 0;
+}
+
+static void object_created_notification(unsigned int object_handle,
+ unsigned int parent_object_handle,
+ void *name_pt, int name_len)
+{
+ struct list_head * list;
+ struct object_instance * obj_pt;
+ struct object_tracker * tracker_pt;
+ unsigned int obj_handle = object_handle;
+ unsigned int res;
+
+ do {
+ res = hdb_handle_get (&object_instance_database,
+ obj_handle, (void *)&obj_pt);
+
+ for (list = obj_pt->track_head.next;
+ list != &obj_pt->track_head; list = list->next) {
+
+ tracker_pt = list_entry (list, struct object_tracker, object_list);
+
+ if (((obj_handle == parent_object_handle) ||
+ (tracker_pt->depth == OBJECT_TRACK_DEPTH_RECURSIVE)) &&
+ (tracker_pt->object_create_notify_fn != NULL)) {
+ tracker_pt->object_create_notify_fn(object_handle, parent_object_handle,
+ name_pt, name_len,
+ tracker_pt->data_pt);
+ }
+ }
+
+ hdb_handle_put (&object_instance_database, obj_handle);
+ obj_handle = obj_pt->parent_handle;
+
+ } while (obj_pt->object_handle != OBJECT_PARENT_HANDLE);
+
+}
+
+static void object_pre_deletion_notification(unsigned int object_handle,
+ unsigned int parent_object_handle,
+ void *name_pt, int name_len)
+{
+ struct list_head * list;
+ struct object_instance * obj_pt;
+ struct object_tracker * tracker_pt;
+ unsigned int obj_handle = object_handle;
+ unsigned int res;
+
+ do {
+ res = hdb_handle_get (&object_instance_database,
+ obj_handle, (void *)&obj_pt);
+
+ for (list = obj_pt->track_head.next;
+ list != &obj_pt->track_head; list = list->next) {
+
+ tracker_pt = list_entry (list, struct object_tracker, object_list);
+
+ if (((obj_handle == parent_object_handle) ||
+ (tracker_pt->depth == OBJECT_TRACK_DEPTH_RECURSIVE)) &&
+ (tracker_pt->object_destroy_notify_fn != NULL)) {
+ tracker_pt->object_destroy_notify_fn(parent_object_handle,
+ name_pt, name_len,
+ tracker_pt->data_pt);
+ }
+ }
+ /* notify child object listeners */
+ if (obj_handle == object_handle)
+ _object_notify_deleted_children(obj_pt);
+
+ hdb_handle_put (&object_instance_database, obj_handle);
+ obj_handle = obj_pt->parent_handle;
+
+ } while (obj_pt->object_handle != OBJECT_PARENT_HANDLE);
+
+}
+
+static void object_key_changed_notification(unsigned int object_handle,
+ void *name_pt, int name_len,
+ void *value_pt, int value_len,
+ object_change_type_t type)
+{
+ struct list_head * list;
+ struct object_instance * obj_pt;
+ struct object_instance * owner_pt = NULL;
+ struct object_tracker * tracker_pt;
+ unsigned int obj_handle = object_handle;
+ unsigned int res;
+
+ do {
+ res = hdb_handle_get (&object_instance_database,
+ obj_handle, (void *)&obj_pt);
+ if (owner_pt == NULL)
+ owner_pt = obj_pt;
+
+ for (list = obj_pt->track_head.next;
+ list != &obj_pt->track_head; list = list->next) {
+
+ tracker_pt = list_entry (list, struct object_tracker, object_list);
+
+ if (((obj_handle == object_handle) ||
+ (tracker_pt->depth == OBJECT_TRACK_DEPTH_RECURSIVE)) &&
+ (tracker_pt->key_change_notify_fn != NULL))
+ tracker_pt->key_change_notify_fn(type, obj_pt->parent_handle, object_handle,
+ owner_pt->object_name, owner_pt->object_name_len,
+ name_pt, name_len,
+ value_pt, value_len,
+ tracker_pt->data_pt);
+ }
+
+ hdb_handle_put (&object_instance_database, obj_handle);
+ obj_handle = obj_pt->parent_handle;
+
+ } while (obj_pt->object_handle != OBJECT_PARENT_HANDLE);
+}
+
/*
* object db create/destroy/set
*/
static int object_create (
unsigned int parent_object_handle,
unsigned int *object_handle,
void *object_name,
unsigned int object_name_len)
{
struct object_instance *object_instance;
struct object_instance *parent_instance;
unsigned int res;
int found = 0;
int i;
res = hdb_handle_get (&object_instance_database,
parent_object_handle, (void *)&parent_instance);
if (res != 0) {
goto error_exit;
}
/*
* Do validation check if validation is configured for the parent object
*/
if (parent_instance->object_valid_list_entries) {
for (i = 0; i < parent_instance->object_valid_list_entries; i++) {
if ((object_name_len ==
parent_instance->object_valid_list[i].object_len) &&
(memcmp (object_name,
parent_instance->object_valid_list[i].object_name,
object_name_len) == 0)) {
found = 1;
break;
}
}
/*
* Item not found in validation list
*/
if (found == 0) {
goto error_object_put;
}
}
res = hdb_handle_create (&object_instance_database,
sizeof (struct object_instance), object_handle);
if (res != 0) {
goto error_object_put;
}
res = hdb_handle_get (&object_instance_database,
*object_handle, (void *)&object_instance);
if (res != 0) {
goto error_destroy;
}
list_init (&object_instance->key_head);
list_init (&object_instance->child_head);
list_init (&object_instance->child_list);
+ list_init (&object_instance->track_head);
object_instance->object_name = malloc (object_name_len);
if (object_instance->object_name == 0) {
goto error_put_destroy;
}
memcpy (object_instance->object_name, object_name, object_name_len);
object_instance->object_name_len = object_name_len;
list_add (&object_instance->child_list, &parent_instance->child_head);
object_instance->object_handle = *object_handle;
object_instance->find_child_list = &object_instance->child_head;
object_instance->iter_key_list = &object_instance->key_head;
object_instance->iter_list = &object_instance->child_head;
object_instance->priv = NULL;
object_instance->object_valid_list = NULL;
object_instance->object_valid_list_entries = 0;
object_instance->parent_handle = parent_object_handle;
hdb_handle_put (&object_instance_database, *object_handle);
hdb_handle_put (&object_instance_database, parent_object_handle);
+ object_created_notification(object_instance->object_handle,
+ object_instance->parent_handle,
+ object_instance->object_name,
+ object_instance->object_name_len);
return (0);
error_put_destroy:
hdb_handle_put (&object_instance_database, *object_handle);
error_destroy:
hdb_handle_destroy (&object_instance_database, *object_handle);
error_object_put:
hdb_handle_put (&object_instance_database, parent_object_handle);
error_exit:
return (-1);
}
static int object_priv_set (
unsigned int object_handle,
void *priv)
{
int res;
struct object_instance *object_instance;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&object_instance);
if (res != 0) {
goto error_exit;
}
object_instance->priv = priv;
hdb_handle_put (&object_instance_database, object_handle);
return (0);
error_exit:
return (-1);
}
static int object_key_create (
unsigned int object_handle,
void *key_name,
int key_len,
void *value,
int value_len)
{
struct object_instance *instance;
struct object_key *object_key;
unsigned int res;
int found = 0;
int i;
unsigned int val;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
/*
* Do validation check if validation is configured for the parent object
*/
if (instance->object_key_valid_list_entries) {
for (i = 0; i < instance->object_key_valid_list_entries; i++) {
if ((key_len ==
instance->object_key_valid_list[i].key_len) &&
(memcmp (key_name,
instance->object_key_valid_list[i].key_name,
key_len) == 0)) {
found = 1;
break;
}
}
/*
* Item not found in validation list
*/
if (found == 0) {
goto error_put;
} else {
if (instance->object_key_valid_list[i].validate_callback) {
res = instance->object_key_valid_list[i].validate_callback (
key_name, key_len, value, value_len);
if (res != 0) {
goto error_put;
}
}
}
}
object_key = malloc (sizeof (struct object_key));
if (object_key == 0) {
goto error_put;
}
object_key->key_name = malloc (key_len);
if (object_key->key_name == 0) {
goto error_put_object;
}
memcpy (&val, value, 4);
object_key->value = malloc (value_len);
if (object_key->value == 0) {
goto error_put_key;
}
memcpy (object_key->key_name, key_name, key_len);
memcpy (object_key->value, value, value_len);
object_key->key_len = key_len;
object_key->value_len = value_len;
list_init (&object_key->list);
list_add (&object_key->list, &instance->key_head);
+ object_key_changed_notification(object_handle, key_name, key_len,
+ value, value_len, OBJECT_KEY_CREATED);
return (0);
error_put_key:
free (object_key->key_name);
error_put_object:
free (object_key);
error_put:
hdb_handle_put (&object_instance_database, object_handle);
error_exit:
return (-1);
}
-
static int _clear_object(struct object_instance *instance)
{
struct list_head *list;
int res;
struct object_instance *find_instance = NULL;
struct object_key *object_key = NULL;
for (list = instance->key_head.next;
list != &instance->key_head; ) {
object_key = list_entry (list, struct object_key,
list);
list = list->next;
list_del(&object_key->list);
free(object_key->key_name);
free(object_key->value);
}
for (list = instance->child_head.next;
list != &instance->child_head; ) {
find_instance = list_entry (list, struct object_instance,
child_list);
res = _clear_object(find_instance);
if (res)
return res;
list = list->next;
list_del(&find_instance->child_list);
free(find_instance->object_name);
free(find_instance);
}
return 0;
}
static int object_destroy (
unsigned int object_handle)
{
struct object_instance *instance;
unsigned int res;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
return (res);
}
+ object_pre_deletion_notification(object_handle,
+ instance->parent_handle,
+ instance->object_name,
+ instance->object_name_len);
+
/* Recursively clear sub-objects & keys */
res = _clear_object(instance);
list_del(&instance->child_list);
free(instance->object_name);
free(instance);
return (res);
}
static int object_valid_set (
unsigned int object_handle,
struct object_valid *object_valid_list,
unsigned int object_valid_list_entries)
{
struct object_instance *instance;
unsigned int res;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
instance->object_valid_list = object_valid_list;
instance->object_valid_list_entries = object_valid_list_entries;
hdb_handle_put (&object_instance_database, object_handle);
return (0);
error_exit:
return (-1);
}
static int object_key_valid_set (
unsigned int object_handle,
struct object_key_valid *object_key_valid_list,
unsigned int object_key_valid_list_entries)
{
struct object_instance *instance;
unsigned int res;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
instance->object_key_valid_list = object_key_valid_list;
instance->object_key_valid_list_entries = object_key_valid_list_entries;
hdb_handle_put (&object_instance_database, object_handle);
return (0);
error_exit:
return (-1);
}
/*
* object db reading
*/
static int object_find_create (
unsigned int object_handle,
void *object_name,
int object_len,
unsigned int *object_find_handle)
{
unsigned int res;
struct object_instance *object_instance;
struct object_find_instance *object_find_instance;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&object_instance);
if (res != 0) {
goto error_exit;
}
res = hdb_handle_create (&object_find_instance_database,
sizeof (struct object_find_instance), object_find_handle);
if (res != 0) {
goto error_put;
}
res = hdb_handle_get (&object_find_instance_database,
*object_find_handle, (void *)&object_find_instance);
if (res != 0) {
goto error_destroy;
}
object_find_instance->find_child_list = &object_instance->child_head;
object_find_instance->child_head = &object_instance->child_head;
object_find_instance->object_name = object_name;
object_find_instance->object_len = object_len;
hdb_handle_put (&object_instance_database, object_handle);
hdb_handle_put (&object_find_instance_database, *object_find_handle);
return (0);
error_destroy:
hdb_handle_destroy (&object_instance_database, *object_find_handle);
error_put:
hdb_handle_put (&object_instance_database, object_handle);
error_exit:
return (-1);
}
static int object_find_next (
unsigned int object_find_handle,
unsigned int *object_handle)
{
unsigned int res;
struct object_find_instance *object_find_instance;
struct object_instance *object_instance = NULL;
struct list_head *list;
unsigned int found = 0;
res = hdb_handle_get (&object_find_instance_database,
object_find_handle, (void *)&object_find_instance);
if (res != 0) {
goto error_exit;
}
res = -1;
for (list = object_find_instance->find_child_list->next;
list != object_find_instance->child_head; list = list->next) {
object_instance = list_entry (list, struct object_instance,
child_list);
if ((object_instance->object_name_len ==
object_find_instance->object_len) &&
(memcmp (object_instance->object_name,
object_find_instance->object_name,
object_find_instance->object_len) == 0)) {
found = 1;
break;
}
}
object_find_instance->find_child_list = list;
hdb_handle_put (&object_find_instance_database, object_find_handle);
if (found) {
*object_handle = object_instance->object_handle;
res = 0;
}
return (res);
error_exit:
return (-1);
}
static int object_find_destroy (
unsigned int object_find_handle)
{
return (0);
}
static int object_key_get (
unsigned int object_handle,
void *key_name,
int key_len,
void **value,
int *value_len)
{
unsigned int res = 0;
struct object_instance *instance;
struct object_key *object_key = NULL;
struct list_head *list;
int found = 0;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
for (list = instance->key_head.next;
list != &instance->key_head; list = list->next) {
object_key = list_entry (list, struct object_key, list);
if ((object_key->key_len == key_len) &&
(memcmp (object_key->key_name, key_name, key_len) == 0)) {
found = 1;
break;
}
}
if (found) {
*value = object_key->value;
if (value_len) {
*value_len = object_key->value_len;
}
}
else {
res = -1;
}
hdb_handle_put (&object_instance_database, object_handle);
return (res);
error_exit:
return (-1);
}
static int object_key_delete (
unsigned int object_handle,
void *key_name,
int key_len,
void *value,
int value_len)
{
unsigned int res;
int ret = 0;
struct object_instance *instance;
struct object_key *object_key = NULL;
struct list_head *list;
int found = 0;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
for (list = instance->key_head.next;
list != &instance->key_head; list = list->next) {
object_key = list_entry (list, struct object_key, list);
if ((object_key->key_len == key_len) &&
(memcmp (object_key->key_name, key_name, key_len) == 0) &&
(value == NULL ||
(object_key->value_len == value_len &&
(memcmp (object_key->value, value, value_len) == 0)))) {
found = 1;
break;
}
}
if (found) {
list_del(&object_key->list);
free(object_key->key_name);
free(object_key->value);
free(object_key);
}
else {
ret = -1;
errno = ENOENT;
}
hdb_handle_put (&object_instance_database, object_handle);
+ if (ret == 0)
+ object_key_changed_notification(object_handle, key_name, key_len,
+ value, value_len, OBJECT_KEY_DELETED);
return (ret);
error_exit:
return (-1);
}
static int object_key_replace (
unsigned int object_handle,
void *key_name,
int key_len,
void *old_value,
int old_value_len,
void *new_value,
int new_value_len)
{
unsigned int res;
int ret = 0;
struct object_instance *instance;
struct object_key *object_key = NULL;
struct list_head *list;
int found = 0;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
for (list = instance->key_head.next;
list != &instance->key_head; list = list->next) {
object_key = list_entry (list, struct object_key, list);
if ((object_key->key_len == key_len) &&
(memcmp (object_key->key_name, key_name, key_len) == 0) &&
(old_value == NULL ||
(object_key->value_len == old_value_len &&
(memcmp (object_key->value, old_value, old_value_len) == 0)))) {
found = 1;
break;
}
}
if (found) {
int i;
/*
* Do validation check if validation is configured for the parent object
*/
if (instance->object_key_valid_list_entries) {
for (i = 0; i < instance->object_key_valid_list_entries; i++) {
if ((key_len ==
instance->object_key_valid_list[i].key_len) &&
(memcmp (key_name,
instance->object_key_valid_list[i].key_name,
key_len) == 0)) {
found = 1;
break;
}
}
/*
* Item not found in validation list
*/
if (found == 0) {
goto error_put;
} else {
if (instance->object_key_valid_list[i].validate_callback) {
res = instance->object_key_valid_list[i].validate_callback (
key_name, key_len, new_value, new_value_len);
if (res != 0) {
goto error_put;
}
}
}
}
if (new_value_len <= object_key->value_len) {
void *replacement_value;
replacement_value = malloc(new_value_len);
if (!replacement_value)
goto error_exit;
free(object_key->value);
object_key->value = replacement_value;
}
memcpy(object_key->value, new_value, new_value_len);
object_key->value_len = new_value_len;
}
else {
ret = -1;
errno = ENOENT;
}
hdb_handle_put (&object_instance_database, object_handle);
+ if (ret == 0)
+ object_key_changed_notification(object_handle, key_name, key_len,
+ new_value, new_value_len, OBJECT_KEY_REPLACED);
return (ret);
error_put:
hdb_handle_put (&object_instance_database, object_handle);
error_exit:
return (-1);
}
static int object_priv_get (
unsigned int object_handle,
void **priv)
{
int res;
struct object_instance *object_instance;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&object_instance);
if (res != 0) {
goto error_exit;
}
*priv = object_instance->priv;
hdb_handle_put (&object_instance_database, object_handle);
return (0);
error_exit:
return (-1);
}
static int _dump_object(struct object_instance *instance, FILE *file, int depth)
{
struct list_head *list;
int res;
int i;
struct object_instance *find_instance = NULL;
struct object_key *object_key = NULL;
char stringbuf1[1024];
char stringbuf2[1024];
memcpy(stringbuf1, instance->object_name, instance->object_name_len);
stringbuf1[instance->object_name_len] = '\0';
for (i=0; i<depth; i++)
fprintf(file, " ");
if (instance->object_handle != OBJECT_PARENT_HANDLE)
fprintf(file, "%s {\n", stringbuf1);
for (list = instance->key_head.next;
list != &instance->key_head; list = list->next) {
object_key = list_entry (list, struct object_key,
list);
memcpy(stringbuf1, object_key->key_name, object_key->key_len);
stringbuf1[object_key->key_len] = '\0';
memcpy(stringbuf2, object_key->value, object_key->value_len);
stringbuf2[object_key->value_len] = '\0';
for (i=0; i<depth+1; i++)
fprintf(file, " ");
fprintf(file, "%s: %s\n", stringbuf1, stringbuf2);
}
for (list = instance->child_head.next;
list != &instance->child_head; list = list->next) {
find_instance = list_entry (list, struct object_instance,
child_list);
res = _dump_object(find_instance, file, depth+1);
if (res)
return res;
}
for (i=0; i<depth; i++)
fprintf(file, " ");
if (instance->object_handle != OBJECT_PARENT_HANDLE)
fprintf(file, "}\n");
return 0;
}
static int object_key_iter_reset(unsigned int object_handle)
{
unsigned int res;
struct object_instance *instance;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
instance->iter_key_list = &instance->key_head;
hdb_handle_put (&object_instance_database, object_handle);
return (0);
error_exit:
return (-1);
}
static int object_key_iter(unsigned int parent_object_handle,
void **key_name,
int *key_len,
void **value,
int *value_len)
{
unsigned int res;
struct object_instance *instance;
struct object_key *find_key = NULL;
struct list_head *list;
unsigned int found = 0;
res = hdb_handle_get (&object_instance_database,
parent_object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
res = -ENOENT;
list = instance->iter_key_list->next;
if (list != &instance->key_head) {
find_key = list_entry (list, struct object_key, list);
found = 1;
}
instance->iter_key_list = list;
if (found) {
*key_name = find_key->key_name;
if (key_len)
*key_len = find_key->key_len;
*value = find_key->value;
if (value_len)
*value_len = find_key->value_len;
res = 0;
}
else {
res = -1;
}
hdb_handle_put (&object_instance_database, parent_object_handle);
return (res);
error_exit:
return (-1);
}
static int object_iter_reset(unsigned int parent_object_handle)
{
unsigned int res;
struct object_instance *instance;
res = hdb_handle_get (&object_instance_database,
parent_object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
instance->iter_list = &instance->child_head;
hdb_handle_put (&object_instance_database, parent_object_handle);
return (0);
error_exit:
return (-1);
}
static int object_iter(unsigned int parent_object_handle,
void **object_name,
int *name_len,
unsigned int *object_handle)
{
unsigned int res;
struct object_instance *instance;
struct object_instance *find_instance = NULL;
struct list_head *list;
unsigned int found = 0;
res = hdb_handle_get (&object_instance_database,
parent_object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
res = -ENOENT;
list = instance->iter_list->next;
if (list != &instance->child_head) {
find_instance = list_entry (list, struct object_instance,
child_list);
found = 1;
}
instance->iter_list = list;
if (found) {
*object_handle = find_instance->object_handle;
*object_name = find_instance->object_name;
*name_len = find_instance->object_name_len;
res = 0;
}
else {
res = -1;
}
return (res);
error_exit:
return (-1);
}
static int object_find_from(unsigned int parent_object_handle,
unsigned int start_pos,
void *object_name,
int object_name_len,
unsigned int *object_handle,
unsigned int *next_pos)
{
unsigned int res;
unsigned int pos = 0;
struct object_instance *instance;
struct object_instance *find_instance = NULL;
struct list_head *list;
unsigned int found = 0;
res = hdb_handle_get (&object_instance_database,
parent_object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
res = -ENOENT;
for (list = instance->child_head.next;
list != &instance->child_head; list = list->next) {
find_instance = list_entry (list, struct object_instance,
child_list);
if ((find_instance->object_name_len == object_name_len) &&
(memcmp (find_instance->object_name, object_name,
object_name_len) == 0)) {
if (pos++ == start_pos) {
found = 1;
break;
}
}
}
hdb_handle_put (&object_instance_database, parent_object_handle);
if (found) {
*object_handle = find_instance->object_handle;
res = 0;
}
*next_pos = pos;
return (res);
error_exit:
return (-1);
}
static int object_iter_from(unsigned int parent_object_handle,
unsigned int start_pos,
void **object_name,
int *name_len,
unsigned int *object_handle)
{
unsigned int res;
unsigned int pos = 0;
struct object_instance *instance;
struct object_instance *find_instance = NULL;
struct list_head *list;
unsigned int found = 0;
res = hdb_handle_get (&object_instance_database,
parent_object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
res = -ENOENT;
for (list = instance->child_head.next;
list != &instance->child_head; list = list->next) {
find_instance = list_entry (list, struct object_instance,
child_list);
if (pos++ == start_pos) {
found = 1;
break;
}
}
if (found) {
*object_handle = find_instance->object_handle;
*object_name = find_instance->object_name;
*name_len = find_instance->object_name_len;
res = 0;
}
else {
res = -1;
}
return (res);
error_exit:
return (-1);
}
static int object_key_iter_from(unsigned int parent_object_handle,
unsigned int start_pos,
void **key_name,
int *key_len,
void **value,
int *value_len)
{
unsigned int pos = 0;
unsigned int res;
struct object_instance *instance;
struct object_key *find_key = NULL;
struct list_head *list;
unsigned int found = 0;
res = hdb_handle_get (&object_instance_database,
parent_object_handle, (void *)&instance);
if (res != 0) {
goto error_exit;
}
res = -ENOENT;
for (list = instance->key_head.next;
list != &instance->key_head; list = list->next) {
find_key = list_entry (list, struct object_key, list);
if (pos++ == start_pos) {
found = 1;
break;
}
}
if (found) {
*key_name = find_key->key_name;
if (key_len)
*key_len = find_key->key_len;
*value = find_key->value;
if (value_len)
*value_len = find_key->value_len;
res = 0;
}
else {
res = -1;
}
hdb_handle_put (&object_instance_database, parent_object_handle);
return (res);
error_exit:
return (-1);
}
-
-
static int object_parent_get(unsigned int object_handle,
unsigned int *parent_handle)
{
struct object_instance *instance;
unsigned int res;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
return (res);
}
if (object_handle == OBJECT_PARENT_HANDLE)
*parent_handle = 0;
else
*parent_handle = instance->parent_handle;
hdb_handle_put (&object_instance_database, object_handle);
return (0);
}
+static int object_track_start(unsigned int object_handle,
+ object_track_depth_t depth,
+ object_key_change_notify_fn_t key_change_notify_fn,
+ object_create_notify_fn_t object_create_notify_fn,
+ object_destroy_notify_fn_t object_destroy_notify_fn,
+ void * priv_data_pt)
+{
+ struct object_instance *instance;
+ unsigned int res;
+ struct object_tracker * tracker_pt;
+
+ res = hdb_handle_get (&object_instance_database,
+ object_handle, (void *)&instance);
+ if (res != 0) {
+ return (res);
+ }
+ tracker_pt = malloc(sizeof(struct object_tracker));
+
+ tracker_pt->depth = depth;
+ tracker_pt->object_handle = object_handle;
+ tracker_pt->key_change_notify_fn = key_change_notify_fn;
+ tracker_pt->object_create_notify_fn = object_create_notify_fn;
+ tracker_pt->object_destroy_notify_fn = object_destroy_notify_fn;
+ tracker_pt->data_pt = priv_data_pt;
+
+ list_init(&tracker_pt->object_list);
+ list_init(&tracker_pt->tracker_list);
+
+ list_add(&tracker_pt->object_list, &instance->track_head);
+ list_add(&tracker_pt->tracker_list, &objdb_trackers_head);
+
+ hdb_handle_put (&object_instance_database, object_handle);
+
+ return (res);
+}
+
+static void object_track_stop(object_key_change_notify_fn_t key_change_notify_fn,
+ object_create_notify_fn_t object_create_notify_fn,
+ object_destroy_notify_fn_t object_destroy_notify_fn,
+ void * priv_data_pt)
+{
+ struct object_instance *instance;
+ struct object_tracker * tracker_pt = NULL;
+ struct object_tracker * obj_tracker_pt = NULL;
+ struct list_head *list, *tmp_list;
+ struct list_head *obj_list, *tmp_obj_list;
+ unsigned int res;
+
+ /* go through the global list and find all the trackers to stop */
+ for (list = objdb_trackers_head.next, tmp_list = list->next;
+ list != &objdb_trackers_head; list = tmp_list, tmp_list = tmp_list->next) {
+
+ tracker_pt = list_entry (list, struct object_tracker, tracker_list);
+
+ if (tracker_pt && (tracker_pt->data_pt == priv_data_pt) &&
+ (tracker_pt->object_create_notify_fn == object_create_notify_fn) &&
+ (tracker_pt->object_destroy_notify_fn == object_destroy_notify_fn) &&
+ (tracker_pt->key_change_notify_fn == key_change_notify_fn)) {
+
+ /* get the object & take this tracker off of it's list. */
+
+ res = hdb_handle_get (&object_instance_database,
+ tracker_pt->object_handle, (void *)&instance);
+ if (res != 0) continue;
+
+ for (obj_list = instance->track_head.next, tmp_obj_list = obj_list->next;
+ obj_list != &instance->track_head; obj_list = tmp_obj_list, tmp_obj_list = tmp_obj_list->next) {
+
+ obj_tracker_pt = list_entry (obj_list, struct object_tracker, object_list);
+ if (obj_tracker_pt == tracker_pt) {
+ /* this is the tracker we are after. */
+ list_del(obj_list);
+ }
+ }
+ hdb_handle_put (&object_instance_database, tracker_pt->object_handle);
+
+ /* remove the tracker off of the global list */
+ list_del(list);
+ free(tracker_pt);
+ }
+ }
+}
+
static int object_dump(unsigned int object_handle,
FILE *file)
{
struct object_instance *instance;
unsigned int res;
res = hdb_handle_get (&object_instance_database,
object_handle, (void *)&instance);
if (res != 0) {
return (res);
}
res = _dump_object(instance, file, -1);
hdb_handle_put (&object_instance_database, object_handle);
return (res);
}
static int object_write_config(char **error_string)
{
struct config_iface_ver0 **modules;
int num_modules;
int i;
int res;
main_get_config_modules(&modules, &num_modules);
for (i=0; i<num_modules; i++) {
if (modules[i]->config_writeconfig) {
res = modules[i]->config_writeconfig(&objdb_iface, error_string);
if (res)
return res;
}
}
return 0;
}
struct objdb_iface_ver0 objdb_iface = {
.objdb_init = objdb_init,
.object_create = object_create,
.object_priv_set = object_priv_set,
.object_key_create = object_key_create,
.object_key_delete = object_key_delete,
.object_key_replace = object_key_replace,
.object_destroy = object_destroy,
.object_valid_set = object_valid_set,
.object_key_valid_set = object_key_valid_set,
.object_find_create = object_find_create,
.object_find_next = object_find_next,
.object_find_destroy = object_find_destroy,
.object_find_from = object_find_from,
.object_key_get = object_key_get,
.object_key_iter = object_key_iter,
.object_key_iter_reset = object_key_iter_reset,
.object_key_iter_from = object_key_iter_from,
.object_iter = object_iter,
.object_iter_reset = object_iter_reset,
.object_iter_from = object_iter_from,
.object_priv_get = object_priv_get,
.object_parent_get = object_parent_get,
+ .object_track_start = object_track_start,
+ .object_track_stop = object_track_stop,
.object_dump = object_dump,
.object_write_config = object_write_config,
};
struct lcr_iface objdb_iface_ver0[1] = {
{
.name = "objdb",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = NULL,
}
};
struct lcr_comp objdb_comp_ver0 = {
.iface_count = 1,
.ifaces = objdb_iface_ver0
};
__attribute__ ((constructor)) static void objdb_comp_register (void) {
lcr_interfaces_set (&objdb_iface_ver0[0], &objdb_iface);
lcr_component_register (&objdb_comp_ver0);
}
diff --git a/exec/objdb.h b/exec/objdb.h
index 9656eaac..608bd421 100644
--- a/exec/objdb.h
+++ b/exec/objdb.h
@@ -1,180 +1,222 @@
/*
* Copyright (c) 2006 MontaVista Software, Inc.
* Copyright (c) 2007-2008 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@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 OBJDB_H_DEFINED
#define OBJDB_H_DEFINED
#define OBJECT_PARENT_HANDLE 0
#include <stdio.h>
+typedef enum {
+ OBJECT_TRACK_DEPTH_ONE,
+ OBJECT_TRACK_DEPTH_RECURSIVE
+} object_track_depth_t;
+
+typedef enum {
+ OBJECT_KEY_CREATED,
+ OBJECT_KEY_REPLACED,
+ OBJECT_KEY_DELETED
+} object_change_type_t;
+
+typedef void (*object_key_change_notify_fn_t)(object_change_type_t change_type,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ void *object_name_pt, int object_name_len,
+ void *key_name_pt, int key_len,
+ void *key_value_pt, int key_value_len,
+ void *priv_data_pt);
+
+typedef void (*object_create_notify_fn_t) (unsigned int parent_object_handle,
+ unsigned int object_handle,
+ void *name_pt, int name_len,
+ void *priv_data_pt);
+
+typedef void (*object_destroy_notify_fn_t) (unsigned int parent_object_handle,
+ void *name_pt, int name_len,
+ void *priv_data_pt);
+
struct object_valid {
char *object_name;
int object_len;
};
-
+
struct object_key_valid {
char *key_name;
int key_len;
int (*validate_callback) (void *key, int key_len, void *value, int value_len);
};
struct objdb_iface_ver0 {
int (*objdb_init) (void);
int (*object_create) (
unsigned int parent_object_handle,
unsigned int *object_handle,
void *object_name,
unsigned int object_name_len);
int (*object_priv_set) (
unsigned int object_handle,
void *priv);
int (*object_key_create) (
unsigned int object_handle,
void *key_name,
int key_len,
void *value,
int value_len);
int (*object_destroy) (
unsigned int object_handle);
int (*object_valid_set) (
unsigned int object_handle,
struct object_valid *object_valid_list,
unsigned int object_valid_list_entries);
int (*object_key_valid_set) (
unsigned int object_handle,
struct object_key_valid *object_key_valid_list,
unsigned int object_key_valid_list_entries);
int (*object_find_create) (
unsigned int parent_object_handle,
void *object_name,
int object_name_len,
unsigned int *object_find_handle);
int (*object_find_next) (
unsigned int object_find_handle,
unsigned int *object_handle);
int (*object_find_destroy) (
unsigned int object_find_handle);
int (*object_key_get) (
unsigned int object_handle,
void *key_name,
int key_len,
void **value,
int *value_len);
int (*object_priv_get) (
unsigned int jobject_handle,
void **priv);
int (*object_key_replace) (
unsigned int object_handle,
void *key_name,
int key_len,
void *old_value,
int old_value_len,
void *new_value,
int new_value_len);
int (*object_key_delete) (
unsigned int object_handle,
void *key_name,
int key_len,
void *value,
int value_len);
int (*object_iter_reset) (
unsigned int parent_object_handle);
int (*object_iter) (
unsigned int parent_object_handle,
void **object_name,
int *name_len,
unsigned int *object_handle);
int (*object_key_iter_reset) (
unsigned int object_handle);
int (*object_key_iter) (
unsigned int parent_object_handle,
void **key_name,
int *key_len,
void **value,
int *value_len);
int (*object_parent_get) (
unsigned int object_handle,
unsigned int *parent_handle);
int (*object_dump) (
unsigned int object_handle,
FILE *file);
int (*object_find_from) (
unsigned int parent_object_handle,
unsigned int start_pos,
void *object_name,
int object_name_len,
unsigned int *object_handle,
unsigned int *next_pos);
int (*object_iter_from) (
unsigned int parent_object_handle,
unsigned int start_pos,
void **object_name,
int *name_len,
unsigned int *object_handle);
int (*object_key_iter_from) (
unsigned int parent_object_handle,
unsigned int start_pos,
void **key_name,
int *key_len,
void **value,
int *value_len);
+ int (*object_track_start) (
+ unsigned int object_handle,
+ object_track_depth_t depth,
+ object_key_change_notify_fn_t key_change_notify_fn,
+ object_create_notify_fn_t object_create_notify_fn,
+ object_destroy_notify_fn_t object_destroy_notify_fn,
+ void * priv_data_pt);
+
+ void (*object_track_stop) (
+ object_key_change_notify_fn_t key_change_notify_fn,
+ object_create_notify_fn_t object_create_notify_fn,
+ object_destroy_notify_fn_t object_destroy_notify_fn,
+ void * priv_data_pt);
+
int (*object_write_config) (char **error_string);
};
#endif /* OBJDB_H_DEFINED */
diff --git a/include/confdb.h b/include/confdb.h
index 831d9826..7e1b9eec 100644
--- a/include/confdb.h
+++ b/include/confdb.h
@@ -1,237 +1,262 @@
/*
* Copyright (c) 2008 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 OPENAIS_CONFDB_H_DEFINED
#define OPENAIS_CONFDB_H_DEFINED
/**
* @addtogroup confdb_openais
*
* @{
*/
typedef uint64_t confdb_handle_t;
#define OBJECT_PARENT_HANDLE 0
typedef enum {
CONFDB_DISPATCH_ONE,
CONFDB_DISPATCH_ALL,
CONFDB_DISPATCH_BLOCKING
} confdb_dispatch_t;
+typedef enum {
+ CONFDB_TRACK_DEPTH_ONE,
+ CONFDB_TRACK_DEPTH_RECURSIVE
+} confdb_track_depth_t;
+
typedef enum {
CONFDB_OK = 1,
CONFDB_ERR_LIBRARY = 2,
CONFDB_ERR_TIMEOUT = 5,
CONFDB_ERR_TRY_AGAIN = 6,
CONFDB_ERR_INVALID_PARAM = 7,
CONFDB_ERR_NO_MEMORY = 8,
CONFDB_ERR_BAD_HANDLE = 9,
CONFDB_ERR_ACCESS = 11,
CONFDB_ERR_NOT_EXIST = 12,
CONFDB_ERR_EXIST = 14,
CONFDB_ERR_CONTEXT_NOT_FOUND = 17,
CONFDB_ERR_NOT_SUPPORTED = 20,
CONFDB_ERR_SECURITY = 29,
} confdb_error_t;
+typedef enum {
+ OBJECT_KEY_CREATED,
+ OBJECT_KEY_REPLACED,
+ OBJECT_KEY_DELETED
+} confdb_change_type_t;
-typedef void (*confdb_change_notify_fn_t) (
+typedef void (*confdb_key_change_notify_fn_t) (
confdb_handle_t handle,
+ confdb_change_type_t change_type,
unsigned int parent_object_handle,
unsigned int object_handle,
void *object_name,
int object_name_len,
void *key_name,
int key_name_len,
void *key_value,
int key_value_len);
+typedef void (*confdb_object_create_notify_fn_t) (
+ confdb_handle_t handle,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ uint8_t *name_pt,
+ int name_len);
+
+typedef void (*confdb_object_delete_notify_fn_t) (
+ confdb_handle_t handle,
+ unsigned int parent_object_handle,
+ uint8_t *name_pt,
+ int name_len);
+
typedef struct {
- confdb_change_notify_fn_t confdb_change_notify_fn;
+ 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_callbacks_t;
/** @} */
/*
* Create a new confdb connection
*/
confdb_error_t confdb_initialize (
confdb_handle_t *handle,
confdb_callbacks_t *callbacks);
/*
* Close the confdb handle
*/
confdb_error_t confdb_finalize (
confdb_handle_t handle);
/*
* Write back the configuration
*/
confdb_error_t confdb_write (
confdb_handle_t handle,
char *error_text);
/*
* Get a file descriptor on which to poll. confdb_handle_t is NOT a
* file descriptor and may not be used directly.
*/
confdb_error_t confdb_fd_get (
confdb_handle_t handle,
int *fd);
/*
* Dispatch configuration changes
*/
confdb_error_t confdb_dispatch (
confdb_handle_t handle,
confdb_dispatch_t dispatch_types);
-
/*
* Change notification
*/
confdb_error_t confdb_track_changes (
confdb_handle_t handle,
unsigned int object_handle,
unsigned int flags);
confdb_error_t confdb_stop_track_changes (
confdb_handle_t handle);
/*
* Manipulate objects
*/
confdb_error_t confdb_object_create (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *object_name,
int object_name_len,
unsigned int *object_handle);
confdb_error_t confdb_object_destroy (
confdb_handle_t handle,
unsigned int object_handle);
confdb_error_t confdb_object_parent_get (
confdb_handle_t handle,
unsigned int object_handle,
unsigned int *parent_object_handle);
/*
* Manipulate keys
*/
confdb_error_t confdb_key_create (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *value,
int value_len);
confdb_error_t confdb_key_delete (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *value,
int value_len);
/*
* Key queries
*/
confdb_error_t confdb_key_get (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *value,
int *value_len);
confdb_error_t confdb_key_replace (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *old_value,
int old_value_len,
void *new_value,
int new_value_len);
/*
* Object queries
* "find" loops through all objects of a given name and is also
* a quick way of finding a specific object,
- * "iter" returns ech object in sequence.
+ * "iter" returns each object in sequence.
*/
confdb_error_t confdb_object_find_start (
confdb_handle_t handle,
unsigned int parent_object_handle);
confdb_error_t confdb_object_find (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *object_name,
int object_name_len,
unsigned int *object_handle);
confdb_error_t confdb_object_iter_start (
confdb_handle_t handle,
unsigned int parent_object_handle);
confdb_error_t confdb_object_iter (
confdb_handle_t handle,
unsigned int parent_object_handle,
unsigned int *object_handle,
void *object_name,
int *object_name_len);
/*
* Key iterator
*/
confdb_error_t confdb_key_iter_start (
confdb_handle_t handle,
unsigned int object_handle);
confdb_error_t confdb_key_iter (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int *key_name_len,
void *value,
int *value_len);
#endif /* OPENAIS_CONFDB_H_DEFINED */
diff --git a/include/coroapi.h b/include/coroapi.h
index 0cd23354..aa9baa85 100644
--- a/include/coroapi.h
+++ b/include/coroapi.h
@@ -1,380 +1,427 @@
/*
* Copyright (c) 2008 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@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 COROAPI_H_DEFINED
#define COROAPI_H_DEFINED
#include <stdio.h>
typedef void * corosync_timer_handle_t;
#define TOTEMIP_ADDRLEN (sizeof(struct in6_addr))
#define PROCESSOR_COUNT_MAX 384
#define INTERFACE_MAX 2
#define MESSAGE_SIZE_MAX 1024*1024 /* (1MB) */
#define TOTEM_AGREED 0
#define TOTEM_SAFE 1
#if !defined(TOTEM_IP_ADDRESS)
struct totem_ip_address {
unsigned int nodeid;
unsigned short family;
unsigned char addr[TOTEMIP_ADDRLEN];
} __attribute__((packed));
#endif
#if !defined(MEMB_RING_ID)
struct memb_ring_id {
struct totem_ip_address rep;
unsigned long long seq;
} __attribute__((packed));
#endif
#if !defined(TOTEM_CONFIGURATION_TYPE)
enum totem_configuration_type {
TOTEM_CONFIGURATION_REGULAR,
TOTEM_CONFIGURATION_TRANSITIONAL
};
#endif
enum corosync_lib_flow_control {
COROSYNC_LIB_FLOW_CONTROL_REQUIRED = 1,
COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED = 2
};
#if !defined (COROSYNC_FLOW_CONTROL_STATE)
enum corosync_flow_control_state {
COROSYNC_FLOW_CONTROL_STATE_DISABLED,
COROSYNC_FLOW_CONTROL_STATE_ENABLED
};
#endif
#ifndef OBJECT_PARENT_HANDLE
#define OBJECT_PARENT_HANDLE 0
struct object_valid {
char *object_name;
int object_len;
};
-
+
struct object_key_valid {
char *key_name;
int key_len;
int (*validate_callback) (void *key, int key_len, void *value, int value_len);
};
+typedef enum {
+ OBJECT_TRACK_DEPTH_ONE,
+ OBJECT_TRACK_DEPTH_RECURSIVE
+} object_track_depth_t;
+
+typedef enum {
+ OBJECT_KEY_CREATED,
+ OBJECT_KEY_REPLACED,
+ OBJECT_KEY_DELETED
+} object_change_type_t;
+
+typedef void (*object_key_change_notify_fn_t)(object_change_type_t change_type,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ void *object_name_pt, int object_name_len,
+ void *key_name_pt, int key_len,
+ void *key_value_pt, int key_value_len,
+ void *priv_data_pt);
+
+typedef void (*object_create_notify_fn_t) (unsigned int parent_object_handle,
+ unsigned int object_handle,
+ uint8_t *name_pt, int name_len,
+ void *priv_data_pt);
+
+typedef void (*object_destroy_notify_fn_t) (unsigned int parent_object_handle,
+ uint8_t *name_pt, int name_len,
+ void *priv_data_pt);
+typedef void (*object_notify_callback_fn_t)(unsigned int object_handle,
+ void *key_name, int key_len,
+ void *value, int value_len,
+ object_change_type_t type,
+ void * priv_data_pt);
+
#endif /* OBJECT_PARENT_HANDLE_DEFINED */
struct corosync_api_v1 {
/*
* Object and configuration APIs
*/
int (*object_create) (
unsigned int parent_object_handle,
unsigned int *object_handle,
void *object_name, unsigned int object_name_len);
int (*object_priv_set) (
unsigned int object_handle,
void *priv);
int (*object_key_create) (
unsigned int object_handle,
void *key_name,
int key_len,
void *value,
int value_len);
int (*object_destroy) (
unsigned int object_handle);
int (*object_valid_set) (
unsigned int object_handle,
struct object_valid *object_valid_list,
unsigned int object_valid_list_entries);
int (*object_key_valid_set) (
unsigned int object_handle,
struct object_key_valid *object_key_valid_list,
unsigned int object_key_valid_list_entries);
int (*object_find_create) (
unsigned int parent_object_handle,
void *object_name,
int object_name_len,
unsigned int *object_find_handle);
int (*object_find_next) (
unsigned int object_find_handle,
unsigned int *object_handle);
int (*object_find_destroy) (
unsigned int object_find_handle);
int (*object_key_get) (
unsigned int object_handle,
void *key_name,
int key_len,
void **value,
int *value_len);
int (*object_priv_get) (
unsigned int jobject_handle,
void **priv);
int (*object_key_replace) (
unsigned int object_handle,
void *key_name,
int key_len,
void *old_value,
int old_value_len,
void *new_value,
int new_value_len);
int (*object_key_delete) (
unsigned int object_handle,
void *key_name,
int key_len,
void *value,
int value_len);
int (*object_iter_reset) (
unsigned int parent_object_handle);
int (*object_iter) (
unsigned int parent_object_handle,
void **object_name,
int *name_len,
unsigned int *object_handle);
int (*object_key_iter_reset) (
unsigned int object_handle);
int (*object_key_iter) (
unsigned int parent_object_handle,
void **key_name,
int *key_len,
void **value,
int *value_len);
int (*object_parent_get) (
unsigned int object_handle,
unsigned int *parent_handle);
int (*object_dump) (
unsigned int object_handle,
FILE *file);
int (*object_find_from) (
unsigned int parent_object_handle,
unsigned int start_pos,
void *object_name,
int object_name_len,
unsigned int *object_handle,
unsigned int *next_pos);
int (*object_iter_from) (
unsigned int parent_object_handle,
unsigned int start_pos,
void **object_name,
int *name_len,
unsigned int *object_handle);
int (*object_key_iter_from) (
unsigned int parent_object_handle,
unsigned int start_pos,
void **key_name,
int *key_len,
void **value,
int *value_len);
+ int (*object_track_start) (
+ unsigned int object_handle,
+ object_track_depth_t depth,
+ object_key_change_notify_fn_t key_change_notify_fn,
+ object_create_notify_fn_t object_create_notify_fn,
+ object_destroy_notify_fn_t object_destroy_notify_fn,
+ void * priv_data_pt);
+
+ void (*object_track_stop) (
+ object_key_change_notify_fn_t key_change_notify_fn,
+ object_create_notify_fn_t object_create_notify_fn,
+ object_destroy_notify_fn_t object_destroy_notify_fn,
+ void * priv_data_pt);
+
int (*object_write_config) (char **error_string);
/*
* Time and timer APIs
*/
int (*timer_add_duration) (
unsigned long long nanoseconds_in_future,
void *data,
void (*timer_nf) (void *data),
corosync_timer_handle_t *handle);
int (*timer_add_absolute) (
unsigned long long nanoseconds_from_epoch,
void *data,
void (*timer_fn) (void *data),
corosync_timer_handle_t *handle);
void (*timer_delete) (
corosync_timer_handle_t timer_handle);
unsigned long long (*timer_time_get) (void);
/*
* IPC APIs
*/
void (*ipc_source_set) (mar_message_source_t *source, void *conn);
int (*ipc_source_is_local) (mar_message_source_t *source);
void *(*ipc_private_data_get) (void *conn);
int (*ipc_response_send) (void *conn, void *msg, int mlen);
int (*ipc_dispatch_send) (void *conn, void *msg, int mlen);
/*
* DEPRECATED
*/
int (*ipc_conn_send_response) (void *conn, void *msg, int mlen);
/*
* DEPRECATED
*/
void *(*ipc_conn_partner_get) (void *conn);
void (*ipc_fc_create) (
void *conn,
unsigned int service,
char *id,
int id_len,
void (*flow_control_state_set_fn)
(void *context,
enum corosync_flow_control_state flow_control_state_set),
void *context);
void (*ipc_fc_destroy) (
void *conn,
unsigned int service,
unsigned char *id,
int id_len);
void (*ipc_refcnt_inc) (void *conn);
void (*ipc_refcnt_dec) (void *conn);
/*
* Totem APIs
*/
int (*totem_nodeid_get) (void);
int (*totem_family_get) (void);
int (*totem_ring_reenable) (void);
int (*totem_mcast) (struct iovec *iovec, int iov_len, unsigned int guarantee);
int (*totem_send_ok) (struct iovec *iovec, int iov_len);
int (*totem_ifaces_get) (
unsigned int nodeid,
struct totem_ip_address *interfaces,
char ***status,
unsigned int *iface_count);
char *(*totem_ifaces_print) (unsigned int nodeid);
char *(*totem_ip_print) (struct totem_ip_address *addr);
/*
* Service loading and unloading APIs
*/
unsigned int (*service_link_and_init) (
struct corosync_api_v1 *corosync_api_v1,
char *service_name,
unsigned int service_ver);
unsigned int (*service_unlink_and_exit) (
struct corosync_api_v1 *corosync_api_v1,
char *service_name,
unsigned int service_ver);
/*
* Error handling APIs
*/
void (*error_memory_failure) (void);
};
#define SERVICE_ID_MAKE(a,b) ( ((a)<<16) | (b) )
#define SERVICE_HANDLER_MAXIMUM_COUNT 64
struct corosync_lib_handler {
void (*lib_handler_fn) (void *conn, void *msg);
int response_size;
int response_id;
enum corosync_lib_flow_control flow_control;
};
struct corosync_exec_handler {
void (*exec_handler_fn) (void *msg, unsigned int nodeid);
void (*exec_endian_convert_fn) (void *msg);
};
struct corosync_service_engine_iface_ver0 {
struct corosync_service_engine *(*corosync_get_service_engine_ver0) (void);
};
struct corosync_service_engine {
char *name;
unsigned short id;
unsigned int private_data_size;
enum corosync_lib_flow_control flow_control;
int (*exec_init_fn) (struct corosync_api_v1 *);
int (*exec_exit_fn) (void);
void (*exec_dump_fn) (void);
int (*lib_init_fn) (void *conn);
int (*lib_exit_fn) (void *conn);
struct corosync_lib_handler *lib_engine;
int lib_engine_count;
struct corosync_exec_handler *exec_engine;
int exec_engine_count;
int (*config_init_fn) (struct corosync_api_v1 *);
void (*confchg_fn) (
enum totem_configuration_type configuration_type,
unsigned int *member_list, int member_list_entries,
unsigned int *left_list, int left_list_entries,
unsigned int *joined_list, int joined_list_entries,
struct memb_ring_id *ring_id);
void (*sync_init) (void);
int (*sync_process) (void);
void (*sync_activate) (void);
void (*sync_abort) (void);
};
#endif /* COROAPI_H_DEFINED */
diff --git a/include/ipc_confdb.h b/include/ipc_confdb.h
index acc0871b..ab01a6f0 100644
--- a/include/ipc_confdb.h
+++ b/include/ipc_confdb.h
@@ -1,187 +1,209 @@
/*
* Copyright (c) 2008 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 "saAis.h"
#include "ipc_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_XPATH_EVAL_EXPRESSION = 12,
+ MESSAGE_REQ_CONFDB_WRITE = 13
};
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_CHANGE_CALLBACK = 12,
- MESSAGE_RES_CONFDB_WRITE = 13
+ 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
};
struct req_lib_confdb_object_create {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_t parent_object_handle __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
};
struct res_lib_confdb_object_create {
mar_res_header_t header __attribute__((aligned(8)));
mar_uint32_t object_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_object_destroy {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_t object_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_object_parent_get {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_t object_handle __attribute__((aligned(8)));
};
struct res_lib_confdb_object_parent_get {
mar_res_header_t header __attribute__((aligned(8)));
mar_uint32_t parent_object_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_key_create {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_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_delete {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_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 {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_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 {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_t parent_object_handle __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
mar_uint32_t next_entry __attribute__((aligned(8)));
};
struct res_lib_confdb_object_find {
mar_res_header_t header __attribute__((aligned(8)));
mar_uint32_t object_handle __attribute__((aligned(8)));
mar_uint32_t next_entry __attribute__((aligned(8)));
};
struct req_lib_confdb_object_iter {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_t parent_object_handle __attribute__((aligned(8)));
mar_uint32_t next_entry __attribute__((aligned(8)));
};
struct res_lib_confdb_object_iter {
mar_res_header_t header __attribute__((aligned(8)));
mar_name_t object_name __attribute__((aligned(8)));
mar_uint32_t object_handle __attribute__((aligned(8)));
};
struct req_lib_confdb_key_iter {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_t parent_object_handle __attribute__((aligned(8)));
mar_uint32_t next_entry __attribute__((aligned(8)));
};
struct res_lib_confdb_key_iter {
mar_res_header_t header __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
};
struct req_lib_confdb_key_get {
mar_req_header_t header __attribute__((aligned(8)));
mar_uint32_t parent_object_handle __attribute__((aligned(8)));
mar_name_t key_name __attribute__((aligned(8)));
};
struct res_lib_confdb_key_get {
mar_res_header_t header __attribute__((aligned(8)));
mar_name_t value __attribute__((aligned(8)));
};
struct res_lib_confdb_write {
mar_res_header_t header __attribute__((aligned(8)));
mar_name_t error __attribute__((aligned(8)));
};
-struct res_lib_confdb_change_callback {
+struct res_lib_confdb_key_change_callback {
mar_res_header_t header __attribute__((aligned(8)));
+ mar_uint32_t change_type __attribute__((aligned(8)));
mar_uint32_t parent_object_handle __attribute__((aligned(8)));
mar_uint32_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_object_create_callback {
+ mar_res_header_t header __attribute__((aligned(8)));
+ mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+ mar_uint32_t object_handle __attribute__((aligned(8)));
+ mar_name_t name __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_object_destroy_callback {
+ mar_res_header_t header __attribute__((aligned(8)));
+ mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+ mar_name_t name __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_object_track_start {
+ mar_req_header_t header __attribute__((aligned(8)));
+ mar_uint32_t object_handle __attribute__((aligned(8)));
+ mar_uint32_t flags __attribute__((aligned(8)));
+};
#endif /* IPC_CONFDB_H_DEFINED */
diff --git a/lib/confdb.c b/lib/confdb.c
index 7e22c03c..8ff8cb20 100644
--- a/lib/confdb.c
+++ b/lib/confdb.c
@@ -1,1200 +1,1310 @@
/*
* Copyright (c) 2008 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 openais object database
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <errno.h>
#include <saAis.h>
#include <confdb.h>
#include <ipc_confdb.h>
#include <mar_gen.h>
#include <ais_util.h>
#include <list.h>
#include "sa-confdb.h"
/* 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;
uint32_t parent_object_handle;
uint32_t context;
};
struct confdb_inst {
int response_fd;
int dispatch_fd;
int finalize;
int standalone;
confdb_callbacks_t callbacks;
void *context;
pthread_mutex_t response_mutex;
pthread_mutex_t dispatch_mutex;
struct list_head object_find_head;
struct list_head object_iter_head;
struct list_head key_iter_head;
};
static void confdb_instance_destructor (void *instance);
static struct saHandleDatabase confdb_handle_t_db = {
.handleCount = 0,
.handles = 0,
.mutex = PTHREAD_MUTEX_INITIALIZER,
.handleInstanceDestructor = confdb_instance_destructor
};
/* Safely tidy one iterator context list */
static void free_context_list(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);
free(context);
}
}
/*
* Clean up function for a confdb instance (confdb_initialize) handle
*/
static void confdb_instance_destructor (void *instance)
{
struct confdb_inst *confdb_inst = instance;
pthread_mutex_destroy (&confdb_inst->response_mutex);
pthread_mutex_destroy (&confdb_inst->dispatch_mutex);
}
static struct iter_context *find_iter_context(struct list_head *list, unsigned int 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_openais
* @ingroup openais
*
* @{
*/
confdb_error_t confdb_initialize (
confdb_handle_t *handle,
confdb_callbacks_t *callbacks)
{
SaAisErrorT error;
struct confdb_inst *confdb_inst;
error = saHandleCreate (&confdb_handle_t_db, sizeof (struct confdb_inst), handle);
if (error != SA_AIS_OK) {
goto error_no_destroy;
}
error = saHandleInstanceGet (&confdb_handle_t_db, *handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
goto error_destroy;
}
if (getenv("OPENAIS_DEFAULT_CONFIG_IFACE")) {
error = confdb_sa_init();
confdb_inst->standalone = 1;
}
else {
error = saServiceConnect (&confdb_inst->dispatch_fd,
&confdb_inst->response_fd,
CONFDB_SERVICE);
}
if (error != SA_AIS_OK)
goto error_put_destroy;
memcpy (&confdb_inst->callbacks, callbacks, sizeof (confdb_callbacks_t));
pthread_mutex_init (&confdb_inst->response_mutex, NULL);
pthread_mutex_init (&confdb_inst->dispatch_mutex, NULL);
list_init (&confdb_inst->object_find_head);
list_init (&confdb_inst->object_iter_head);
list_init (&confdb_inst->key_iter_head);
saHandleInstancePut (&confdb_handle_t_db, *handle);
return (SA_AIS_OK);
error_put_destroy:
saHandleInstancePut (&confdb_handle_t_db, *handle);
error_destroy:
saHandleDestroy (&confdb_handle_t_db, *handle);
error_no_destroy:
return (error);
}
confdb_error_t confdb_finalize (
confdb_handle_t handle)
{
struct confdb_inst *confdb_inst;
SaAisErrorT error;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
pthread_mutex_lock (&confdb_inst->response_mutex);
/*
* Another thread has already started finalizing
*/
if (confdb_inst->finalize) {
pthread_mutex_unlock (&confdb_inst->response_mutex);
saHandleInstancePut (&confdb_handle_t_db, handle);
return (CONFDB_ERR_BAD_HANDLE);
}
confdb_inst->finalize = 1;
pthread_mutex_unlock (&confdb_inst->response_mutex);
saHandleDestroy (&confdb_handle_t_db, handle);
/* Free saved context handles */
free_context_list(&confdb_inst->object_find_head);
free_context_list(&confdb_inst->object_iter_head);
free_context_list(&confdb_inst->key_iter_head);
if (!confdb_inst->standalone) {
/*
* Disconnect from the server
*/
if (confdb_inst->response_fd != -1) {
shutdown(confdb_inst->response_fd, 0);
close(confdb_inst->response_fd);
}
if (confdb_inst->dispatch_fd != -1) {
shutdown(confdb_inst->dispatch_fd, 0);
close(confdb_inst->dispatch_fd);
}
}
saHandleInstancePut (&confdb_handle_t_db, handle);
return (CONFDB_OK);
}
confdb_error_t confdb_fd_get (
confdb_handle_t handle,
int *fd)
{
SaAisErrorT error;
struct confdb_inst *confdb_inst;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
*fd = confdb_inst->dispatch_fd;
saHandleInstancePut (&confdb_handle_t_db, handle);
return (SA_AIS_OK);
}
confdb_error_t confdb_context_get (
confdb_handle_t handle,
void **context)
{
SaAisErrorT error;
struct confdb_inst *confdb_inst;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
*context = confdb_inst->context;
saHandleInstancePut (&confdb_handle_t_db, handle);
return (SA_AIS_OK);
}
confdb_error_t confdb_context_set (
confdb_handle_t handle,
void *context)
{
SaAisErrorT error;
struct confdb_inst *confdb_inst;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
confdb_inst->context = context;
saHandleInstancePut (&confdb_handle_t_db, handle);
return (SA_AIS_OK);
}
struct res_overlay {
mar_res_header_t header __attribute__((aligned(8)));
char data[512000];
};
confdb_error_t confdb_dispatch (
confdb_handle_t handle,
confdb_dispatch_t dispatch_types)
{
struct pollfd ufds;
int timeout = -1;
SaAisErrorT error;
int cont = 1; /* always continue do loop except when set to 0 */
int dispatch_avail;
struct confdb_inst *confdb_inst;
- struct res_lib_confdb_change_callback *res_confdb_change_callback;
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_overlay dispatch_data;
int ignore_dispatch = 0;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = CONFDB_ERR_NOT_SUPPORTED;
goto error_unlock;
}
/*
* Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and
* wait indefinately for SA_DISPATCH_BLOCKING
*/
if (dispatch_types == CONFDB_DISPATCH_ALL) {
timeout = 0;
}
do {
ufds.fd = confdb_inst->dispatch_fd;
ufds.events = POLLIN;
ufds.revents = 0;
error = saPollRetry (&ufds, 1, timeout);
if (error != SA_AIS_OK) {
goto error_nounlock;
}
pthread_mutex_lock (&confdb_inst->dispatch_mutex);
/*
* Regather poll data in case ufds has changed since taking lock
*/
error = saPollRetry (&ufds, 1, timeout);
if (error != SA_AIS_OK) {
goto error_nounlock;
}
/*
* Handle has been finalized in another thread
*/
if (confdb_inst->finalize == 1) {
error = CONFDB_OK;
pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
goto error_unlock;
}
dispatch_avail = ufds.revents & POLLIN;
if (dispatch_avail == 0 && dispatch_types == CONFDB_DISPATCH_ALL) {
pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
break; /* exit do while cont is 1 loop */
} else
if (dispatch_avail == 0) {
pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
continue; /* next poll */
}
if (ufds.revents & POLLIN) {
/*
* Queue empty, read response from socket
*/
error = saRecvRetry (confdb_inst->dispatch_fd, &dispatch_data.header,
sizeof (mar_res_header_t));
if (error != SA_AIS_OK) {
goto error_unlock;
}
if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
error = saRecvRetry (confdb_inst->dispatch_fd, &dispatch_data.data,
dispatch_data.header.size - sizeof (mar_res_header_t));
if (error != SA_AIS_OK) {
goto error_unlock;
}
}
} else {
pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
continue;
}
/*
* 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));
pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
/*
* Dispatch incoming message
*/
switch (dispatch_data.header.id) {
- case MESSAGE_RES_CONFDB_CHANGE_CALLBACK:
- res_confdb_change_callback = (struct res_lib_confdb_change_callback *)&dispatch_data;
-
- callbacks.confdb_change_notify_fn (handle,
- res_confdb_change_callback->parent_object_handle,
- res_confdb_change_callback->object_handle,
- res_confdb_change_callback->object_name.value,
- res_confdb_change_callback->object_name.length,
- res_confdb_change_callback->key_name.value,
- res_confdb_change_callback->key_name.length,
- res_confdb_change_callback->key_value.value,
- res_confdb_change_callback->key_value.length);
- break;
-
- default:
- error = SA_AIS_ERR_LIBRARY;
- goto error_nounlock;
- break;
+ case MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK:
+ 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:
+ 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:
+ 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;
+
+ default:
+ error = SA_AIS_ERR_LIBRARY;
+ goto error_nounlock;
+ break;
}
/*
* Determine if more messages should be processed
* */
switch (dispatch_types) {
case CONFDB_DISPATCH_ONE:
if (ignore_dispatch) {
ignore_dispatch = 0;
} else {
cont = 0;
}
break;
case CONFDB_DISPATCH_ALL:
if (ignore_dispatch) {
ignore_dispatch = 0;
}
break;
case CONFDB_DISPATCH_BLOCKING:
break;
}
} while (cont);
error_unlock:
saHandleInstancePut (&confdb_handle_t_db, handle);
error_nounlock:
return (error);
}
confdb_error_t confdb_object_create (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *object_name,
int object_name_len,
unsigned int *object_handle)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
struct req_lib_confdb_object_create req_lib_confdb_object_create;
struct res_lib_confdb_object_create res_lib_confdb_object_create;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_object_create(parent_object_handle,
object_name, object_name_len,
object_handle))
error = SA_AIS_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[0].iov_base = (char *)&req_lib_confdb_object_create;
iov[0].iov_len = sizeof (struct req_lib_confdb_object_create);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res_lib_confdb_object_create, sizeof (struct res_lib_confdb_object_create));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res_lib_confdb_object_create.header.error;
*object_handle = res_lib_confdb_object_create.object_handle;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_object_destroy (
confdb_handle_t handle,
unsigned int object_handle)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
struct req_lib_confdb_object_destroy req_lib_confdb_object_destroy;
mar_res_header_t res;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_object_destroy(object_handle))
error = SA_AIS_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[0].iov_base = (char *)&req_lib_confdb_object_destroy;
iov[0].iov_len = sizeof (struct req_lib_confdb_object_destroy);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res, sizeof ( mar_res_header_t));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res.error;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_object_parent_get (
confdb_handle_t handle,
unsigned int object_handle,
unsigned int *parent_object_handle)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
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 = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_object_parent_get(object_handle, parent_object_handle))
error = SA_AIS_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[0].iov_base = (char *)&req_lib_confdb_object_parent_get;
iov[0].iov_len = sizeof (struct req_lib_confdb_object_parent_get);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res_lib_confdb_object_parent_get, sizeof (struct res_lib_confdb_object_parent_get));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_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:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_key_create (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *value,
int value_len)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
struct req_lib_confdb_key_create req_lib_confdb_key_create;
mar_res_header_t res;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_key_create(parent_object_handle,
key_name, key_name_len,
value, value_len))
error = SA_AIS_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[0].iov_base = (char *)&req_lib_confdb_key_create;
iov[0].iov_len = sizeof (struct req_lib_confdb_key_create);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res, sizeof (res));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res.error;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_key_delete (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *value,
int value_len)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
struct req_lib_confdb_key_delete req_lib_confdb_key_delete;
mar_res_header_t res;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_key_delete(parent_object_handle,
key_name, key_name_len,
value, value_len))
error = SA_AIS_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[0].iov_base = (char *)&req_lib_confdb_key_delete;
iov[0].iov_len = sizeof (struct req_lib_confdb_key_delete);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res, sizeof (res));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res.error;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_key_get (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *value,
int *value_len)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
struct req_lib_confdb_key_get req_lib_confdb_key_get;
struct res_lib_confdb_key_get res_lib_confdb_key_get;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_key_get(parent_object_handle,
key_name, key_name_len,
value, value_len))
error = SA_AIS_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[0].iov_base = (char *)&req_lib_confdb_key_get;
iov[0].iov_len = sizeof (struct req_lib_confdb_key_get);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res_lib_confdb_key_get, sizeof (struct res_lib_confdb_key_get));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res_lib_confdb_key_get.header.error;
if (error == SA_AIS_OK) {
*value_len = res_lib_confdb_key_get.value.length;
memcpy(value, res_lib_confdb_key_get.value.value, *value_len);
}
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_key_replace (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int key_name_len,
void *old_value,
int old_value_len,
void *new_value,
int new_value_len)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
struct req_lib_confdb_key_replace req_lib_confdb_key_replace;
mar_res_header_t res;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_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 = SA_AIS_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[0].iov_base = (char *)&req_lib_confdb_key_replace;
iov[0].iov_len = sizeof (struct req_lib_confdb_key_replace);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res, sizeof (res));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res.error;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_object_iter_start (
confdb_handle_t handle,
unsigned int object_handle)
{
struct confdb_inst *confdb_inst;
confdb_error_t error = SA_AIS_OK;
struct iter_context *context;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_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 = CONFDB_ERR_NO_MEMORY;
goto ret;
}
context->parent_object_handle = object_handle;
list_add(&context->list, &confdb_inst->object_iter_head);
}
context->context = 0;
saHandleInstancePut (&confdb_handle_t_db, handle);
ret:
return error;
}
confdb_error_t confdb_key_iter_start (
confdb_handle_t handle,
unsigned int object_handle)
{
struct confdb_inst *confdb_inst;
confdb_error_t error = SA_AIS_OK;
struct iter_context *context;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_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 = CONFDB_ERR_NO_MEMORY;
goto ret;
}
context->parent_object_handle = object_handle;
list_add(&context->list, &confdb_inst->key_iter_head);
}
context->context = 0;
saHandleInstancePut (&confdb_handle_t_db, handle);
ret:
return error;
}
confdb_error_t confdb_object_find_start (
confdb_handle_t handle,
unsigned int parent_object_handle)
{
struct confdb_inst *confdb_inst;
confdb_error_t error = SA_AIS_OK;
struct iter_context *context;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_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 = CONFDB_ERR_NO_MEMORY;
goto ret;
}
context->parent_object_handle = parent_object_handle;
list_add(&context->list, &confdb_inst->object_find_head);
}
context->context = 0;
saHandleInstancePut (&confdb_handle_t_db, handle);
ret:
return error;
}
confdb_error_t confdb_object_find (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *object_name,
int object_name_len,
unsigned int *object_handle)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
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 = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_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 = CONFDB_ERR_CONTEXT_NOT_FOUND;
goto error_exit;
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_object_find(parent_object_handle,
context->context,
object_name, object_name_len,
object_handle,
&context->context))
error = SA_AIS_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.next_entry = context->context;
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[0].iov_base = (char *)&req_lib_confdb_object_find;
iov[0].iov_len = sizeof (struct req_lib_confdb_object_find);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res_lib_confdb_object_find, sizeof (struct res_lib_confdb_object_find));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res_lib_confdb_object_find.header.error;
*object_handle = res_lib_confdb_object_find.object_handle;
context->context = res_lib_confdb_object_find.next_entry;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_object_iter (
confdb_handle_t handle,
unsigned int parent_object_handle,
unsigned int *object_handle,
void *object_name,
int *object_name_len)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
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 = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_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 = CONFDB_ERR_CONTEXT_NOT_FOUND;
goto error_exit;
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_object_iter(parent_object_handle,
context->context,
object_handle,
object_name, object_name_len))
error = SA_AIS_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.next_entry = context->context;
iov[0].iov_base = (char *)&req_lib_confdb_object_iter;
iov[0].iov_len = sizeof (struct req_lib_confdb_object_iter);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res_lib_confdb_object_iter, sizeof (struct res_lib_confdb_object_iter));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res_lib_confdb_object_iter.header.error;
if (error == SA_AIS_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;
}
sa_exit:
context->context++;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_key_iter (
confdb_handle_t handle,
unsigned int parent_object_handle,
void *key_name,
int *key_name_len,
void *value,
int *value_len)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
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 = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_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 = CONFDB_ERR_CONTEXT_NOT_FOUND;
goto error_exit;
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_key_iter(parent_object_handle,
context->context,
key_name, key_name_len,
value, value_len))
error = SA_AIS_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->context;
iov[0].iov_base = (char *)&req_lib_confdb_key_iter;
iov[0].iov_len = sizeof (struct req_lib_confdb_key_iter);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res_lib_confdb_key_iter, sizeof (struct res_lib_confdb_key_iter));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
goto error_exit;
}
error = res_lib_confdb_key_iter.header.error;
if (error == SA_AIS_OK) {
*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);
*value_len = res_lib_confdb_key_iter.value.length;
memcpy(value, res_lib_confdb_key_iter.value.value, *value_len);
}
sa_exit:
context->context++;
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
confdb_error_t confdb_write (
confdb_handle_t handle,
char *error_text)
{
confdb_error_t error;
struct confdb_inst *confdb_inst;
struct iovec iov[2];
mar_req_header_t req;
struct res_lib_confdb_write res_lib_confdb_write;
error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
if (error != SA_AIS_OK) {
return (error);
}
if (confdb_inst->standalone) {
error = SA_AIS_OK;
if (confdb_sa_write(error_text))
error = SA_AIS_ERR_ACCESS;
goto error_exit;
}
req.size = sizeof (mar_req_header_t);
req.id = MESSAGE_REQ_CONFDB_WRITE;
iov[0].iov_base = (char *)&req;
iov[0].iov_len = sizeof (mar_req_header_t);
pthread_mutex_lock (&confdb_inst->response_mutex);
error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
&res_lib_confdb_write, sizeof ( struct res_lib_confdb_write));
pthread_mutex_unlock (&confdb_inst->response_mutex);
if (error != SA_AIS_OK) {
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, res_lib_confdb_write.error.length);
error_exit:
saHandleInstancePut (&confdb_handle_t_db, handle);
return (error);
}
+confdb_error_t confdb_track_changes (
+ confdb_handle_t handle,
+ unsigned int object_handle,
+ unsigned int flags)
+{
+ confdb_error_t error;
+ struct confdb_inst *confdb_inst;
+ struct iovec iov[2];
+ struct req_lib_confdb_object_track_start req;
+ mar_res_header_t res;
+
+ error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+ if (error != SA_AIS_OK) {
+ return (error);
+ }
+
+ if (confdb_inst->standalone) {
+ error = CONFDB_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[0].iov_base = (char *)&req;
+ iov[0].iov_len = sizeof (struct req_lib_confdb_object_track_start);
+
+ pthread_mutex_lock (&confdb_inst->response_mutex);
+
+ error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+ &res, sizeof ( mar_res_header_t));
+
+ pthread_mutex_unlock (&confdb_inst->response_mutex);
+ if (error != SA_AIS_OK) {
+ goto error_exit;
+ }
+
+ error = res.error;
+
+error_exit:
+ saHandleInstancePut (&confdb_handle_t_db, handle);
+
+ return (error);
+}
+
+confdb_error_t confdb_stop_track_changes (confdb_handle_t handle)
+{
+ confdb_error_t error;
+ struct confdb_inst *confdb_inst;
+ struct iovec iov[2];
+ mar_req_header_t req;
+ mar_res_header_t res;
+
+ error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+ if (error != SA_AIS_OK) {
+ return (error);
+ }
+
+ if (confdb_inst->standalone) {
+ error = CONFDB_ERR_NOT_SUPPORTED;
+ goto error_exit;
+ }
+
+ req.size = sizeof (mar_req_header_t);
+ req.id = MESSAGE_REQ_CONFDB_TRACK_STOP;
+
+ iov[0].iov_base = (char *)&req;
+ iov[0].iov_len = sizeof (mar_req_header_t);
+
+ pthread_mutex_lock (&confdb_inst->response_mutex);
+
+ error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+ &res, sizeof ( mar_res_header_t));
+
+ pthread_mutex_unlock (&confdb_inst->response_mutex);
+ if (error != SA_AIS_OK) {
+ goto error_exit;
+ }
+
+ error = res.error;
+
+error_exit:
+ saHandleInstancePut (&confdb_handle_t_db, handle);
+
+ return (error);
+}
diff --git a/man/corosync-objctl.8 b/man/corosync-objctl.8
index f230008f..250a99c5 100644
--- a/man/corosync-objctl.8
+++ b/man/corosync-objctl.8
@@ -1,113 +1,117 @@
.\"/*
.\" * Copyright (c) 2008 Allied Telesis Labs NZ.
.\" *
.\" * 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.
.\" */
.TH COROSYNC-OBJCTL 8 2008-07-29
.SH NAME
corosync-objctl \- Configure objects in the Object Database
.SH SYNOPSIS
-.B "corosync-objctl [\-c|\-w|\-d|\-a|\-h] <OBJECT-SPEC>..."
+.B "corosync-objctl [\-c|\-w|\-d|\-a|\-t\-h] <OBJECT-SPEC>..."
.SH DESCRIPTION
.B corosync-objctl
is used to configure objects within the object database at runtime.
.SH OBJECT-SPEC
.TP
There are two types of entities
.B Objects
and
.B Key=Value pairs
.TP
.B Objects
Objects are container like entities that can hold other entities.
They are specified as "objectA"."objectB".
An example is logging.logger.
.TP
.B Key=Value pairs
These are the entities that actually hold values (read database "fields").
They are specified as object.key=value or just object.key if you are reading.
.SH OPTIONS
.TP
.B -c
Create a new object.
.TP
.B -d
Delete an existing object.
.TP
-.B "-w"
+.B -w
Use this option when you want to write a new value to a key.
.TP
-.B "-a"
+.B -a
Display all values currently available.
.TP
+.B -t
+Track changes to an object and it's children. As changes are made to the object
+they are printed out. this is kind of like a "tail -f" for the object database.
+.TP
.B -h
Print basic usage.
.SH EXAMPLES
.TP
Print the objOne object (shouldn't exist yet).
$ corosync-objctl objOne
.TP
Create the objOne object.
$ corosync-objctl -c objOne
.TP
Print the objOne object (empty).
$ corosync-objctl objOne
.br
objOne
.TP
Write two new keys to the objOne object.
$ corosync-objctl -w objOne.max=3000 objOne.min=100
.TP
Print the objOne object (with the two new keys).
$ corosync-objctl objOne
.br
objOne.min=100
.br
objOne.max=3000
.TP
Delete the objOne.min key
$ corosync-objctl -d objOne.min=100
.TP
Prove that is gone.
$ corosync-objctl objOne
.br
objOne.max=3000
.TP
Delete the whole objOne object.
$ corosync-objctl -d objOne
.TP
Prove that is gone.
$ corosync-objctl objOne
.SH SEE ALSO
.BR confdb_initialize (3),
.SH AUTHOR
Angus Salkeld
.PP
diff --git a/services/confdb.c b/services/confdb.c
index 2b56b00a..440e44b0 100644
--- a/services/confdb.c
+++ b/services/confdb.c
@@ -1,493 +1,587 @@
/*
* Copyright (c) 2008 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 <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include "../include/saAis.h"
#include "../include/ipc_gen.h"
#include "../include/ipc_confdb.h"
#include "../include/mar_gen.h"
#include "../lcr/lcr_comp.h"
#include "../exec/logsys.h"
#include "../include/coroapi.h"
-LOGSYS_DECLARE_SUBSYS ("CONFDB", LOG_INFO);
+LOGSYS_DECLARE_SUBSYS ("CONFDB", LOG_DEBUG);
static struct corosync_api_v1 *api;
static int confdb_exec_init_fn (
struct corosync_api_v1 *corosync_api);
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, void *message);
static void message_handler_req_lib_confdb_object_destroy (void *conn, void *message);
static void message_handler_req_lib_confdb_key_create (void *conn, void *message);
static void message_handler_req_lib_confdb_key_get (void *conn, void *message);
static void message_handler_req_lib_confdb_key_replace (void *conn, void *message);
static void message_handler_req_lib_confdb_key_delete (void *conn, void *message);
static void message_handler_req_lib_confdb_key_iter (void *conn, void *message);
static void message_handler_req_lib_confdb_object_iter (void *conn, void *message);
static void message_handler_req_lib_confdb_object_find (void *conn, void *message);
static void message_handler_req_lib_confdb_object_parent_get (void *conn, void *message);
static void message_handler_req_lib_confdb_write (void *conn, void *message);
static void message_handler_req_lib_confdb_track_start (void *conn, void *message);
static void message_handler_req_lib_confdb_track_stop (void *conn, void *message);
-
+static void confdb_notify_lib_of_key_change(object_change_type_t change_type,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ void *object_name_pt, int object_name_len,
+ void *key_name_pt, int key_name_len,
+ void *key_value_pt, int key_value_len,
+ void *priv_data_pt);
+
+static void confdb_notify_lib_of_new_object(unsigned int parent_object_handle,
+ unsigned int object_handle,
+ uint8_t *name_pt, int name_len,
+ void *priv_data_pt);
+static void confdb_notify_lib_of_destroyed_object(unsigned int parent_object_handle,
+ uint8_t *name_pt, int name_len,
+ 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,
.response_size = sizeof (mar_res_header_t),
.response_id = MESSAGE_RES_CONFDB_OBJECT_CREATE,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 1 */
.lib_handler_fn = message_handler_req_lib_confdb_object_destroy,
.response_size = sizeof (mar_res_header_t),
.response_id = MESSAGE_RES_CONFDB_OBJECT_DESTROY,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 2 */
.lib_handler_fn = message_handler_req_lib_confdb_object_find,
.response_size = sizeof (struct res_lib_confdb_object_find),
.response_id = MESSAGE_RES_CONFDB_OBJECT_FIND,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 3 */
.lib_handler_fn = message_handler_req_lib_confdb_key_create,
.response_size = sizeof (mar_res_header_t),
.response_id = MESSAGE_RES_CONFDB_KEY_CREATE,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 4 */
.lib_handler_fn = message_handler_req_lib_confdb_key_get,
.response_size = sizeof (struct res_lib_confdb_key_get),
.response_id = MESSAGE_RES_CONFDB_KEY_GET,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 5 */
.lib_handler_fn = message_handler_req_lib_confdb_key_replace,
.response_size = sizeof (mar_res_header_t),
.response_id = MESSAGE_RES_CONFDB_KEY_REPLACE,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 6 */
.lib_handler_fn = message_handler_req_lib_confdb_key_delete,
.response_size = sizeof (mar_res_header_t),
.response_id = MESSAGE_RES_CONFDB_KEY_DELETE,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 7 */
.lib_handler_fn = message_handler_req_lib_confdb_object_iter,
.response_size = sizeof (struct res_lib_confdb_object_iter),
.response_id = MESSAGE_RES_CONFDB_OBJECT_ITER,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 8 */
.lib_handler_fn = message_handler_req_lib_confdb_object_parent_get,
.response_size = sizeof (struct res_lib_confdb_object_parent_get),
.response_id = MESSAGE_RES_CONFDB_OBJECT_PARENT_GET,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 9 */
.lib_handler_fn = message_handler_req_lib_confdb_key_iter,
.response_size = sizeof (struct res_lib_confdb_key_iter),
.response_id = MESSAGE_RES_CONFDB_KEY_ITER,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 10 */
.lib_handler_fn = message_handler_req_lib_confdb_track_start,
.response_size = sizeof (mar_res_header_t),
.response_id = MESSAGE_RES_CONFDB_TRACK_START,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 11 */
.lib_handler_fn = message_handler_req_lib_confdb_track_stop,
.response_size = sizeof (mar_res_header_t),
- .response_id = MESSAGE_RES_CONFDB_TRACK_START,
+ .response_id = MESSAGE_RES_CONFDB_TRACK_STOP,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
{ /* 12 */
.lib_handler_fn = message_handler_req_lib_confdb_write,
.response_size = sizeof (struct res_lib_confdb_write),
.response_id = MESSAGE_RES_CONFDB_WRITE,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
},
};
struct corosync_service_engine confdb_service_engine = {
.name = "corosync cluster config database access v1.01",
.id = CONFDB_SERVICE,
.private_data_size = 0,
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
.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,
};
/*
* 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);
}
__attribute__ ((constructor)) static void confdb_comp_register (void) {
lcr_interfaces_set (&corosync_confdb_ver0[0], &confdb_service_engine_iface);
lcr_component_register (&confdb_comp_ver0);
}
static int confdb_exec_init_fn (
struct corosync_api_v1 *corosync_api)
{
api = corosync_api;
return 0;
}
static int confdb_lib_init_fn (void *conn)
{
log_printf(LOG_LEVEL_DEBUG, "lib_init_fn: conn=%p\n", conn);
return (0);
}
static int confdb_lib_exit_fn (void *conn)
{
log_printf(LOG_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,
+ api->ipc_conn_partner_get (conn));
return (0);
}
static void message_handler_req_lib_confdb_object_create (void *conn, void *message)
{
struct req_lib_confdb_object_create *req_lib_confdb_object_create = (struct req_lib_confdb_object_create *)message;
struct res_lib_confdb_object_create res_lib_confdb_object_create;
unsigned int object_handle;
int ret = SA_AIS_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 = SA_AIS_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_conn_send_response(conn, &res_lib_confdb_object_create, sizeof(res_lib_confdb_object_create));
}
static void message_handler_req_lib_confdb_object_destroy (void *conn, void *message)
{
struct req_lib_confdb_object_destroy *req_lib_confdb_object_destroy = (struct req_lib_confdb_object_destroy *)message;
mar_res_header_t res;
int ret = SA_AIS_OK;
if (api->object_destroy(req_lib_confdb_object_destroy->object_handle))
ret = SA_AIS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_OBJECT_CREATE;
res.error = ret;
api->ipc_conn_send_response(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_key_create (void *conn, void *message)
{
struct req_lib_confdb_key_create *req_lib_confdb_key_create = (struct req_lib_confdb_key_create *)message;
mar_res_header_t res;
int ret = SA_AIS_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 = SA_AIS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_KEY_CREATE;
res.error = ret;
api->ipc_conn_send_response(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_key_get (void *conn, void *message)
{
struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message;
struct res_lib_confdb_key_get res_lib_confdb_key_get;
int value_len;
void *value;
int ret = SA_AIS_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 = SA_AIS_ERR_ACCESS;
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_conn_send_response(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get));
}
static void message_handler_req_lib_confdb_key_replace (void *conn, void *message)
{
struct req_lib_confdb_key_replace *req_lib_confdb_key_replace = (struct req_lib_confdb_key_replace *)message;
mar_res_header_t res;
int ret = SA_AIS_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->old_value.value,
req_lib_confdb_key_replace->old_value.length,
req_lib_confdb_key_replace->new_value.value,
req_lib_confdb_key_replace->new_value.length))
ret = SA_AIS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_KEY_REPLACE;
res.error = ret;
api->ipc_conn_send_response(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_key_delete (void *conn, void *message)
{
struct req_lib_confdb_key_delete *req_lib_confdb_key_delete = (struct req_lib_confdb_key_delete *)message;
mar_res_header_t res;
int ret = SA_AIS_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,
req_lib_confdb_key_delete->value.value,
req_lib_confdb_key_delete->value.length))
ret = SA_AIS_ERR_ACCESS;
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_KEY_DELETE;
res.error = ret;
api->ipc_conn_send_response(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_object_parent_get (void *conn, void *message)
{
struct req_lib_confdb_object_parent_get *req_lib_confdb_object_parent_get = (struct req_lib_confdb_object_parent_get *)message;
struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get;
unsigned int object_handle;
int ret = SA_AIS_OK;
if (api->object_parent_get(req_lib_confdb_object_parent_get->object_handle,
&object_handle))
ret = SA_AIS_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_conn_send_response(conn, &res_lib_confdb_object_parent_get, sizeof(res_lib_confdb_object_parent_get));
}
static void message_handler_req_lib_confdb_key_iter (void *conn, void *message)
{
struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = (struct req_lib_confdb_key_iter *)message;
struct res_lib_confdb_key_iter res_lib_confdb_key_iter;
void *key_name;
int key_name_len;
void *value;
int value_len;
int ret = SA_AIS_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 = SA_AIS_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);
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_conn_send_response(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter));
}
static void message_handler_req_lib_confdb_object_iter (void *conn, void *message)
{
struct req_lib_confdb_object_iter *req_lib_confdb_object_iter = (struct req_lib_confdb_object_iter *)message;
struct res_lib_confdb_object_iter res_lib_confdb_object_iter;
void *object_name;
int object_name_len;
int ret = SA_AIS_OK;
if (api->object_iter_from(req_lib_confdb_object_iter->parent_object_handle,
req_lib_confdb_object_iter->next_entry,
&object_name,
&object_name_len,
&res_lib_confdb_object_iter.object_handle))
ret = SA_AIS_ERR_ACCESS;
else {
res_lib_confdb_object_iter.object_name.length = object_name_len;
memcpy(res_lib_confdb_object_iter.object_name.value, object_name, object_name_len);
}
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_conn_send_response(conn, &res_lib_confdb_object_iter, sizeof(res_lib_confdb_object_iter));
}
static void message_handler_req_lib_confdb_object_find (void *conn, void *message)
{
struct req_lib_confdb_object_find *req_lib_confdb_object_find = (struct req_lib_confdb_object_find *)message;
struct res_lib_confdb_object_find res_lib_confdb_object_find;
int ret = SA_AIS_OK;
if (api->object_find_from(req_lib_confdb_object_find->parent_object_handle,
req_lib_confdb_object_find->next_entry,
req_lib_confdb_object_find->object_name.value,
req_lib_confdb_object_find->object_name.length,
&res_lib_confdb_object_find.object_handle,
&res_lib_confdb_object_find.next_entry))
ret = SA_AIS_ERR_ACCESS;
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_conn_send_response(conn, &res_lib_confdb_object_find, sizeof(res_lib_confdb_object_find));
}
static void message_handler_req_lib_confdb_write (void *conn, void *message)
{
struct res_lib_confdb_write res_lib_confdb_write;
int ret = SA_AIS_OK;
char *error_string = NULL;
if (api->object_write_config(&error_string))
ret = SA_AIS_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_conn_send_response(conn, &res_lib_confdb_write, sizeof(res_lib_confdb_write));
}
-/* TODO: when we have notification in the objdb. */
+static void confdb_notify_lib_of_key_change(object_change_type_t change_type,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ void *object_name_pt, int object_name_len,
+ void *key_name_pt, int key_name_len,
+ void *key_value_pt, int key_value_len,
+ void *priv_data_pt)
+{
+ struct res_lib_confdb_key_change_callback res;
+
+ res.header.size = sizeof(res);
+ res.header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK;
+ res.header.error = SA_AIS_OK;
+// handle & type
+ 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;
+//key name
+ 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;
+
+ api->ipc_conn_send_response(priv_data_pt, &res, sizeof(res));
+}
+
+static void confdb_notify_lib_of_new_object(unsigned int parent_object_handle,
+ unsigned int object_handle,
+ uint8_t *name_pt, int 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 = SA_AIS_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;
+
+ api->ipc_conn_send_response(priv_data_pt, &res, sizeof(res));
+}
+
+static void confdb_notify_lib_of_destroyed_object(unsigned int parent_object_handle,
+ uint8_t *name_pt, int 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 = SA_AIS_OK;
+ res.parent_object_handle = parent_object_handle;
+ memcpy(res.name.value, name_pt, name_len);
+ res.name.length = name_len;
+
+ api->ipc_conn_send_response(priv_data_pt, &res, sizeof(res));
+}
+
+
static void message_handler_req_lib_confdb_track_start (void *conn, void *message)
{
+ struct req_lib_confdb_object_track_start *req = (struct req_lib_confdb_object_track_start *)message;
mar_res_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,
+ api->ipc_conn_partner_get (conn));
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_TRACK_START;
- res.error = SA_AIS_ERR_NOT_SUPPORTED;
+ res.error = SA_AIS_OK;
api->ipc_conn_send_response(conn, &res, sizeof(res));
}
static void message_handler_req_lib_confdb_track_stop (void *conn, void *message)
{
mar_res_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,
+ api->ipc_conn_partner_get (conn));
+
res.size = sizeof(res);
res.id = MESSAGE_RES_CONFDB_TRACK_STOP;
- res.error = SA_AIS_ERR_NOT_SUPPORTED;
+ res.error = SA_AIS_OK;
api->ipc_conn_send_response(conn, &res, sizeof(res));
}
diff --git a/test/testconfdb.c b/test/testconfdb.c
index 8ecbf469..90ab3c58 100644
--- a/test/testconfdb.c
+++ b/test/testconfdb.c
@@ -1,218 +1,220 @@
/*
* Copyright (c) 2008 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/un.h>
#include "saAis.h"
#include "confdb.h"
/* Callbacks are not supported yet */
confdb_callbacks_t callbacks = {
- .confdb_change_notify_fn = NULL,
+ .confdb_key_change_notify_fn = NULL,
+ .confdb_object_create_change_notify_fn = NULL,
+ .confdb_object_delete_change_notify_fn = NULL
};
/* Recursively dump the object tree */
static void print_config_tree(confdb_handle_t handle, unsigned int parent_object_handle, int depth)
{
unsigned int object_handle;
char object_name[1024];
int object_name_len;
char key_name[1024];
int key_name_len;
char key_value[1024];
int key_value_len;
int res;
int i;
/* Show the keys */
res = confdb_key_iter_start(handle, parent_object_handle);
if (res != SA_AIS_OK) {
printf( "error resetting key iterator for object %d: %d\n", parent_object_handle, res);
return;
}
while ( (res = confdb_key_iter(handle, parent_object_handle, key_name, &key_name_len,
key_value, &key_value_len)) == SA_AIS_OK) {
key_name[key_name_len] = '\0';
key_value[key_value_len] = '\0';
for (i=0; i<depth; i++) printf(" ");
printf(" KEY %s=%s\n", key_name, key_value);
}
/* Show sub-objects */
res = confdb_object_iter_start(handle, parent_object_handle);
if (res != SA_AIS_OK) {
printf( "error resetting object iterator for object %d: %d\n", parent_object_handle, res);
return;
}
while ( (res = confdb_object_iter(handle, parent_object_handle, &object_handle, object_name, &object_name_len)) == SA_AIS_OK) {
unsigned int parent;
res = confdb_object_parent_get(handle, object_handle, &parent);
if (res != SA_AIS_OK) {
printf( "error getting parent for object %d: %d\n", object_handle, res);
return;
}
for (i=0; i<depth; i++) printf(" ");
object_name[object_name_len] = '\0';
printf("OBJECT: %s (%u, parent: %u)\n", object_name, object_handle, parent);
/* Down we go ... */
print_config_tree(handle, object_handle, depth+1);
}
}
static void do_write_tests(confdb_handle_t handle)
{
int res;
unsigned int object_handle;
char error_string[1024];
/* Add a scratch object and put some keys into it */
res = confdb_object_create(handle, OBJECT_PARENT_HANDLE, (void *)"testconfdb", strlen("testconfdb"), &object_handle);
if (res != SA_AIS_OK) {
printf( "error creating 'testconfdb' object: %d\n", res);
return;
}
res = confdb_key_create(handle, object_handle, "testkey", strlen("testkey"), "one", strlen("one"));
if (res != SA_AIS_OK) {
printf( "error creating 'testconfdb' key 1: %d\n", res);
return;
}
res = confdb_key_create(handle, object_handle, "testkey", strlen("testkey"), "two", strlen("two"));
if (res != SA_AIS_OK) {
printf( "error creating 'testconfdb' key 2: %d\n", res);
return;
}
res = confdb_key_create(handle, object_handle, "grot", strlen("grot"), "perrins", strlen("perrins"));
if (res != SA_AIS_OK) {
printf( "error creating 'testconfdb' key 3: %d\n", res);
return;
}
res = confdb_key_replace(handle, object_handle, "testkey", strlen("testkey"), "two", strlen("two"),
"newtwo", strlen("newtwo"));
if (res != SA_AIS_OK) {
printf( "error replace 'testconfdb' key 2: %d\n", res);
return;
}
/* Print it for verification */
print_config_tree(handle, object_handle, 0);
printf("-------------------------\n");
/* Remove it.
Check that it doesn't exist when the full tree dump runs next */
res = confdb_object_destroy(handle, object_handle);
if (res != SA_AIS_OK) {
printf( "error destroying 'testconfdb' object: %d\n", res);
return;
}
res = confdb_write(handle, error_string);
printf("confdb_write returned %d: %s\n", res, error_string);
}
int main (int argc, char *argv[]) {
confdb_handle_t handle;
int result;
unsigned int totem_handle;
char key_value[256];
int value_len;
result = confdb_initialize (&handle, &callbacks);
if (result != SA_AIS_OK) {
printf ("Could not initialize Cluster Configuration Database API instance error %d\n", result);
exit (1);
}
if (argv[1] && strcmp(argv[1], "write")==0)
do_write_tests(handle);
/* Test iterators */
print_config_tree(handle, OBJECT_PARENT_HANDLE, 0);
/* Find "totem" and dump bits of it again, to test the direct APIs */
result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
if (result != SA_AIS_OK) {
printf ("Could not start object_find %d\n", result);
exit (1);
}
result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, "totem", strlen("totem"), &totem_handle);
if (result != SA_AIS_OK) {
printf ("Could not object_find \"totem\": %d\n", result);
exit (1);
}
result = confdb_key_get(handle, totem_handle, "version", strlen("version"), key_value, &value_len);
if (result != SA_AIS_OK) {
printf ("Could not get \"version\" key: %d\n", result);
exit (1);
}
key_value[value_len] = '\0';
printf("totem/version = '%s'\n", key_value);
result = confdb_key_get(handle, totem_handle, "secauth", strlen("secauth"), key_value, &value_len);
if (result != SA_AIS_OK) {
printf ("Could not get \"secauth\" key: %d\n", result);
exit (1);
}
key_value[value_len] = '\0';
printf("totem/secauth = '%s'\n", key_value);
/* Try a call that fails */
result = confdb_key_get(handle, totem_handle, "grot", strlen("grot"), key_value, &value_len);
printf ("Get \"grot\" key returned: %d (should fail)\n", result);
result = confdb_finalize (handle);
printf ("Finalize result is %d (should be 1)\n", result);
return (0);
}
diff --git a/tools/corosync-objctl.c b/tools/corosync-objctl.c
index 84f356cd..d59c2f63 100644
--- a/tools/corosync-objctl.c
+++ b/tools/corosync-objctl.c
@@ -1,499 +1,642 @@
/*
* Copyright (c) 2008 Allied Telesis Labs NZ
*
* 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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/un.h>
#include "saAis.h"
#include "confdb.h"
#define SEPERATOR '.'
#define SEPERATOR_STR "."
#define OBJ_NAME_SIZE 512
typedef enum {
ACTION_READ,
ACTION_WRITE,
ACTION_CREATE,
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,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ void *object_name,
+ int object_name_len,
+ void *key_name,
+ int key_name_len,
+ void *key_value,
+ int key_value_len);
+
+static void tail_object_created(confdb_handle_t handle,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ uint8_t *name_pt,
+ int name_len);
+
+static void tail_object_deleted(confdb_handle_t handle,
+ unsigned int parent_object_handle,
+ uint8_t *name_pt,
+ int name_len);
+
confdb_callbacks_t callbacks = {
- .confdb_change_notify_fn = NULL,
+ .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 action;
/* Recursively dump the object tree */
static void print_config_tree(confdb_handle_t handle, unsigned int parent_object_handle, char * parent_name)
{
unsigned int object_handle;
char object_name[OBJ_NAME_SIZE];
int object_name_len;
char key_name[OBJ_NAME_SIZE];
int key_name_len;
char key_value[OBJ_NAME_SIZE];
int key_value_len;
confdb_error_t res;
int children_printed;
/* Show the keys */
res = confdb_key_iter_start(handle, parent_object_handle);
if (res != CONFDB_OK) {
fprintf(stderr, "error resetting key iterator for object %d: %d\n", parent_object_handle, res);
exit(EXIT_FAILURE);
}
children_printed = 0;
while ( (res = confdb_key_iter(handle,
parent_object_handle,
key_name,
&key_name_len,
key_value,
&key_value_len)) == CONFDB_OK) {
key_name[key_name_len] = '\0';
key_value[key_value_len] = '\0';
if (parent_name != NULL)
printf("%s%c%s=%s\n", parent_name, SEPERATOR,key_name, key_value);
else
printf("%s=%s\n", key_name, key_value);
children_printed++;
}
/* Show sub-objects */
res = confdb_object_iter_start(handle, parent_object_handle);
if (res != CONFDB_OK) {
fprintf(stderr, "error resetting object iterator for object %d: %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)) == CONFDB_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);
} else {
if ((action == ACTION_PRINT_DEFAULT) && strcmp(object_name, "internal_configuration") == 0) continue;
snprintf(key_value, OBJ_NAME_SIZE, "%s", object_name);
}
print_config_tree(handle, object_handle, key_value);
children_printed++;
}
if (children_printed == 0 && parent_name != NULL) {
printf("%s\n", parent_name);
}
}
static int print_all(void)
{
confdb_handle_t handle;
int result;
result = confdb_initialize (&handle, &callbacks);
if (result != CONFDB_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 object%ckey ...\n", SEPERATOR);
printf (" corosync-objctl -c object%cchild_obj ...\n", SEPERATOR);
printf (" corosync-objctl -d object%cchild_obj ...\n", SEPERATOR);
printf (" corosync-objctl -w object%cchild_obj.key=value ...\n", SEPERATOR);
printf (" corosync-objctl -a (print all objects)\n");
printf("\n");
return 0;
}
static confdb_error_t validate_name(char * obj_name_pt)
{
if ((strchr (obj_name_pt, SEPERATOR) == NULL) &&
(strchr (obj_name_pt, '=') == NULL))
return CONFDB_OK;
else
return CONFDB_ERR_INVALID_PARAM;
}
void get_child_name(char * name_pt, char * child_name)
{
char * tmp;
char str_copy[OBJ_NAME_SIZE];
strcpy(str_copy, name_pt);
/* first remove the value (it could be a file path */
tmp = strchr(str_copy, '=');
if (tmp != NULL) *tmp = '\0';
/* truncate the */
tmp = strrchr(str_copy, SEPERATOR);
if (tmp == NULL) tmp = str_copy;
strcpy(child_name, tmp+1);
}
void get_parent_name(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';
/* then truncate the child name */
tmp = strrchr(parent_name, SEPERATOR);
if (tmp != NULL) *tmp = '\0';
}
void get_key(char * name_pt, char * key_name, char * key_value)
{
char * tmp;
char str_copy[OBJ_NAME_SIZE];
strcpy(str_copy, name_pt);
/* 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 confdb_error_t find_object (confdb_handle_t handle,
char * name_pt,
find_object_of_type_t type,
uint32_t * out_handle)
{
char * obj_name_pt;
char * save_pt;
uint32_t obj_handle;
confdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE;
char tmp_name[OBJ_NAME_SIZE];
confdb_error_t res;
strncpy (tmp_name, name_pt, OBJ_NAME_SIZE);
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 != CONFDB_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 != CONFDB_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];
uint32_t obj_handle;
confdb_error_t res;
get_parent_name(name_pt, parent_name);
res = find_object (handle, name_pt, FIND_OBJECT_OR_KEY, &obj_handle);
if (res == CONFDB_OK) {
print_config_tree(handle, obj_handle, parent_name);
}
}
static void write_key(confdb_handle_t handle, char * path_pt)
{
uint32_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];
int old_key_value_len;
confdb_error_t res;
/* find the parent object */
get_parent_name(path_pt, parent_name);
get_key(path_pt, key_name, key_value);
if (validate_name(key_name) != CONFDB_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 != CONFDB_OK) {
fprintf(stderr, "Can't find parent object of \"%s\"\n", path_pt);
exit(EXIT_FAILURE);
}
/* get the current key */
res = confdb_key_get (handle,
obj_handle,
key_name,
strlen(key_name),
old_key_value,
&old_key_value_len);
if (res == CONFDB_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));
if (res != CONFDB_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 (handle,
obj_handle,
key_name,
strlen(key_name),
key_value,
strlen(key_value));
if (res != CONFDB_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;
uint32_t obj_handle;
uint32_t parent_object_handle = OBJECT_PARENT_HANDLE;
char tmp_name[OBJ_NAME_SIZE];
confdb_error_t res;
strncpy (tmp_name, name_pt, OBJ_NAME_SIZE);
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 != CONFDB_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 != CONFDB_OK) {
if (validate_name(obj_name_pt) != CONFDB_OK) {
fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n",
obj_name_pt);
exit(EXIT_FAILURE);
}
res = confdb_object_create (handle,
parent_object_handle,
obj_name_pt,
strlen (obj_name_pt),
&obj_handle);
if (res != CONFDB_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 tail_key_changed(confdb_handle_t handle,
+ confdb_change_type_t change_type,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ void *object_name_pt,
+ int object_name_len,
+ void *key_name_pt,
+ int key_name_len,
+ void *key_value_pt,
+ int key_value_len)
+{
+ char * on = (char*)object_name_pt;
+ char * kn = (char*)key_name_pt;
+ char * kv = (char*)key_value_pt;
+
+ on[object_name_len] = '\0';
+ kv[key_value_len] = '\0';
+ kn[key_name_len] = '\0';
+ printf("key_changed> %s.%s=%s\n", on, kn, kv);
+}
+
+static void tail_object_created(confdb_handle_t handle,
+ unsigned int parent_object_handle,
+ unsigned int object_handle,
+ uint8_t *name_pt,
+ int name_len)
+{
+ name_pt[name_len] = '\0';
+ printf("object_created> %s\n", name_pt);
+}
+
+static void tail_object_deleted(confdb_handle_t handle,
+ unsigned int parent_object_handle,
+ uint8_t *name_pt,
+ int name_len)
+{
+ name_pt[name_len] = '\0';
+
+ printf("object_deleted> %s\n", name_pt);
+}
+
+static void listen_for_object_changes(confdb_handle_t handle)
+{
+ int result;
+ fd_set read_fds;
+ int select_fd;
+ SaBoolT quit = SA_FALSE;
+
+ FD_ZERO (&read_fds);
+ confdb_fd_get(handle, &select_fd);
+ 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];
+
+ fgets(inbuf, sizeof(inbuf), stdin);
+ if (strncmp(inbuf, "q", 1) == 0)
+ quit = SA_TRUE;
+ }
+ if (FD_ISSET (select_fd, &read_fds)) {
+ if (confdb_dispatch (handle, CONFDB_DISPATCH_ALL) != CONFDB_OK)
+ exit(1);
+ }
+ } while (result && quit == SA_FALSE);
+
+ confdb_stop_track_changes(handle);
+
+}
+
+static void track_object(confdb_handle_t handle, char * name_pt)
+{
+ confdb_error_t res;
+ uint32_t obj_handle;
+
+ res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle);
+
+ if (res != CONFDB_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 != CONFDB_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)
+{
+ confdb_error_t res;
+
+ res = confdb_stop_track_changes (handle);
+ if (res != CONFDB_OK) {
+ fprintf (stderr, "Could not stop tracking. Error %d\n", res);
+ return;
+ }
+}
+
static void delete_object(confdb_handle_t handle, char * name_pt)
{
confdb_error_t res;
uint32_t obj_handle;
res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle);
if (res == CONFDB_OK) {
res = confdb_object_destroy (handle, obj_handle);
if (res != CONFDB_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 != CONFDB_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 != CONFDB_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;
confdb_error_t result;
char c;
action = ACTION_READ;
for (;;){
- c = getopt (argc,argv,"hawcdp:");
+ c = getopt (argc,argv,"hawcdtp:");
if (c==-1) {
break;
}
switch (c) {
case 'h':
return print_help();
break;
case 'a':
action = ACTION_PRINT_ALL;
break;
case 'p':
printf("%s:%d NOT Implemented yet.\n", __FUNCTION__, __LINE__);
return -1;
//return read_in_config_file();
break;
case 'c':
action = ACTION_CREATE;
break;
case 'd':
action = ACTION_DELETE;
break;
case 'w':
action = ACTION_WRITE;
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 != CONFDB_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_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);
+ }
+
result = confdb_finalize (handle);
if (result != CONFDB_OK) {
fprintf (stderr, "Error finalizing objdb API. Error %d\n", result);
exit(EXIT_FAILURE);
}
return 0;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 25, 2:10 AM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2619965
Default Alt Text
(164 KB)
Attached To
Mode
rC Corosync
Attached
Detach File
Event Timeline
Log In to Comment