Page MenuHomeClusterLabs Projects

No OneTemporary

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

Mime Type
text/x-diff
Expires
Sat, Oct 25, 2:10 AM (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2619965
Default Alt Text
(164 KB)

Event Timeline