diff --git a/exec/objdb.c b/exec/objdb.c index 7c4af4d2..609fe5de 100644 --- a/exec/objdb.c +++ b/exec/objdb.c @@ -1,1619 +1,1619 @@ /* * Copyright (c) 2006 MontaVista Software, Inc. * Copyright (c) 2007-2009 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 #include #include #include #include #include #include #include #include "main.h" struct object_key { void *key_name; - int key_len; + size_t key_len; void *value; - int value_len; + size_t value_len; struct list_head list; }; struct object_tracker { hdb_handle_t 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; object_reload_notify_fn_t object_reload_notify_fn; struct list_head tracker_list; struct list_head object_list; }; struct object_instance { void *object_name; - int object_name_len; + size_t object_name_len; hdb_handle_t object_handle; hdb_handle_t 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; + size_t object_len; }; struct objdb_iface_ver0 objdb_iface; struct list_head objdb_trackers_head; static pthread_rwlock_t reload_lock; static pthread_t lock_thread; static pthread_mutex_t meta_lock; 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 void objdb_wrlock(void) { pthread_mutex_lock(&meta_lock); pthread_rwlock_wrlock(&reload_lock); lock_thread = pthread_self(); pthread_mutex_unlock(&meta_lock); } static void objdb_rdlock(void) { pthread_mutex_lock(&meta_lock); if (lock_thread != pthread_self()) pthread_rwlock_rdlock(&reload_lock); pthread_mutex_unlock(&meta_lock); } static void objdb_rdunlock(void) { pthread_mutex_lock(&meta_lock); if (lock_thread != pthread_self()) pthread_rwlock_unlock(&reload_lock); pthread_mutex_unlock(&meta_lock); } static void objdb_wrunlock(void) { pthread_mutex_lock(&meta_lock); pthread_rwlock_unlock(&reload_lock); lock_thread = 0; pthread_mutex_unlock(&meta_lock); } static int objdb_init (void) { hdb_handle_t 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->parent_handle = OBJECT_PARENT_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); pthread_rwlock_init(&reload_lock, NULL); pthread_mutex_init(&meta_lock, NULL); 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( hdb_handle_t object_handle, hdb_handle_t parent_object_handle, - void *name_pt, int name_len) + const void *name_pt, size_t name_len) { struct list_head * list; struct object_instance * obj_pt; struct object_tracker * tracker_pt; hdb_handle_t 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_handle != OBJECT_PARENT_HANDLE); } static void object_pre_deletion_notification(hdb_handle_t object_handle, hdb_handle_t parent_object_handle, - void *name_pt, int name_len) + const void *name_pt, size_t name_len) { struct list_head * list; struct object_instance * obj_pt; struct object_tracker * tracker_pt; hdb_handle_t 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); obj_handle = obj_pt->parent_handle; hdb_handle_put (&object_instance_database, obj_pt->object_handle); } while (obj_handle != OBJECT_PARENT_HANDLE); } static void object_key_changed_notification(hdb_handle_t object_handle, - const void *name_pt, int name_len, - const void *value_pt, int value_len, + const void *name_pt, size_t name_len, + const void *value_pt, size_t 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; hdb_handle_t 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); } obj_handle = obj_pt->parent_handle; hdb_handle_put (&object_instance_database, obj_pt->object_handle); } while (obj_handle != OBJECT_PARENT_HANDLE); } static void object_reload_notification(int startstop, int flush) { struct list_head * list; struct object_instance * obj_pt; struct object_tracker * tracker_pt; unsigned int res; res = hdb_handle_get (&object_instance_database, OBJECT_PARENT_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 (tracker_pt->object_reload_notify_fn != NULL) { tracker_pt->object_reload_notify_fn(startstop, flush, tracker_pt->data_pt); } } hdb_handle_put (&object_instance_database, OBJECT_PARENT_HANDLE); } /* * object db create/destroy/set */ static int object_create ( hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, const void *object_name, - unsigned int object_name_len) + size_t object_name_len) { struct object_instance *object_instance; struct object_instance *parent_instance; unsigned int res; int found = 0; int i; objdb_rdlock(); 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_tail (&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); objdb_rdunlock(); 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: objdb_rdunlock(); return (-1); } static int object_priv_set ( hdb_handle_t object_handle, void *priv) { int res; struct object_instance *object_instance; objdb_rdlock(); 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); objdb_rdunlock(); return (0); error_exit: objdb_rdunlock(); return (-1); } static int object_key_create ( hdb_handle_t object_handle, const void *key_name, - int key_len, + size_t key_len, const void *value, - int value_len) + size_t value_len) { struct object_instance *instance; struct object_key *object_key; unsigned int res; struct list_head *list; int found = 0; int i; objdb_rdlock(); 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; } } } } /* See if it already exists */ found = 0; 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) { free(object_key->value); } else { 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 (object_key->key_name, key_name, key_len); list_init (&object_key->list); list_add_tail (&object_key->list, &instance->key_head); } object_key->value = malloc (value_len); if (object_key->value == 0) { goto error_put_key; } memcpy (object_key->value, value, value_len); object_key->key_len = key_len; object_key->value_len = value_len; object_key_changed_notification(object_handle, key_name, key_len, value, value_len, OBJECT_KEY_CREATED); objdb_rdunlock(); 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: objdb_rdunlock(); 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 ( hdb_handle_t object_handle) { struct object_instance *instance; unsigned int res; objdb_rdlock(); res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { objdb_rdunlock(); 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); objdb_rdunlock(); return (res); } static int object_valid_set ( hdb_handle_t object_handle, struct object_valid *object_valid_list, unsigned int object_valid_list_entries) { struct object_instance *instance; unsigned int res; objdb_rdlock(); 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); objdb_rdunlock(); return (0); error_exit: objdb_rdunlock(); return (-1); } static int object_key_valid_set ( hdb_handle_t object_handle, struct object_key_valid *object_key_valid_list, unsigned int object_key_valid_list_entries) { struct object_instance *instance; unsigned int res; objdb_rdlock(); 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); objdb_rdunlock(); return (0); error_exit: objdb_rdunlock(); return (-1); } /* * object db reading */ static int object_find_create ( hdb_handle_t object_handle, const void *object_name, - int object_len, + size_t object_len, hdb_handle_t *object_find_handle) { unsigned int res; struct object_instance *object_instance; struct object_find_instance *object_find_instance; objdb_rdlock(); 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); objdb_rdunlock(); 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: objdb_rdunlock(); return (-1); } static int object_find_next ( hdb_handle_t object_find_handle, hdb_handle_t *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; objdb_rdlock(); 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_find_instance->object_len == 0 || ((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; } objdb_rdunlock(); return (res); error_exit: objdb_rdunlock(); return (-1); } static int object_find_destroy ( hdb_handle_t object_find_handle) { struct object_find_instance *object_find_instance; unsigned int res; objdb_rdlock(); res = hdb_handle_get (&object_find_instance_database, object_find_handle, (void *)&object_find_instance); if (res != 0) { goto error_exit; } hdb_handle_put(&object_find_instance_database, object_find_handle); hdb_handle_destroy(&object_find_instance_database, object_find_handle); objdb_rdunlock(); return (0); error_exit: objdb_rdunlock(); return (-1); } static int object_key_get ( hdb_handle_t object_handle, const void *key_name, - int key_len, + size_t key_len, void **value, - int *value_len) + size_t *value_len) { unsigned int res = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; objdb_rdlock(); 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); objdb_rdunlock(); return (res); error_exit: objdb_rdunlock(); return (-1); } static int object_key_increment ( hdb_handle_t object_handle, const void *key_name, - int key_len, + size_t key_len, unsigned int *value) { unsigned int res = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; objdb_rdlock(); 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 && object_key->value_len == sizeof(int)) { (*(int *)object_key->value)++; *value = *(int *)object_key->value; } else { res = -1; } hdb_handle_put (&object_instance_database, object_handle); objdb_rdunlock(); return (res); error_exit: objdb_rdunlock(); return (-1); } static int object_key_decrement ( hdb_handle_t object_handle, const void *key_name, - int key_len, + size_t key_len, unsigned int *value) { unsigned int res = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; objdb_rdlock(); 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 && object_key->value_len == sizeof(int)) { (*(int *)object_key->value)--; *value = *(int *)object_key->value; } else { res = -1; } hdb_handle_put (&object_instance_database, object_handle); objdb_rdunlock(); return (res); error_exit: objdb_rdunlock(); return (-1); } static int object_key_delete ( hdb_handle_t object_handle, const void *key_name, - int key_len) + size_t key_len) { unsigned int res; int ret = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; objdb_rdlock(); 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) { 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, NULL, 0, OBJECT_KEY_DELETED); objdb_rdunlock(); return (ret); error_exit: objdb_rdunlock(); return (-1); } static int object_key_replace ( hdb_handle_t object_handle, const void *key_name, - int key_len, + size_t key_len, const void *new_value, - int new_value_len) + size_t 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; objdb_rdlock(); 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) { int i; int found_validator = 0; /* * 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_validator = 1; break; } } /* * Item not found in validation list */ if (found_validator == 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); objdb_rdunlock(); return (ret); error_put: hdb_handle_put (&object_instance_database, object_handle); error_exit: objdb_rdunlock(); return (-1); } static int object_priv_get ( hdb_handle_t object_handle, void **priv) { int res; struct object_instance *object_instance; objdb_rdunlock(); 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); objdb_rdunlock(); return (0); error_exit: objdb_rdunlock(); 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; iobject_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; ichild_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; iobject_handle != OBJECT_PARENT_HANDLE) fprintf(file, "}\n"); return 0; } static int object_key_iter_reset(hdb_handle_t object_handle) { unsigned int res; struct object_instance *instance; objdb_rdlock(); 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); objdb_rdunlock(); return (0); error_exit: objdb_rdunlock(); return (-1); } static int object_key_iter(hdb_handle_t parent_object_handle, void **key_name, - int *key_len, + size_t *key_len, void **value, - int *value_len) + size_t *value_len) { unsigned int res; struct object_instance *instance; struct object_key *find_key = NULL; struct list_head *list; unsigned int found = 0; objdb_rdlock(); 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); objdb_rdunlock(); return (res); error_exit: objdb_rdunlock(); return (-1); } static int object_key_iter_from(hdb_handle_t parent_object_handle, hdb_handle_t start_pos, void **key_name, - int *key_len, + size_t *key_len, void **value, - int *value_len) + size_t *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; objdb_rdlock(); 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); objdb_rdunlock(); return (res); error_exit: objdb_rdunlock(); return (-1); } static int object_parent_get(hdb_handle_t object_handle, hdb_handle_t *parent_handle) { struct object_instance *instance; unsigned int res; objdb_rdlock(); res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { objdb_rdunlock(); 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); objdb_rdunlock(); return (0); } static int object_name_get(hdb_handle_t object_handle, char *object_name, - int *object_name_len) + size_t *object_name_len) { struct object_instance *instance; unsigned int res; objdb_rdlock(); res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { objdb_rdunlock(); return (res); } memcpy(object_name, instance->object_name, instance->object_name_len); *object_name_len = instance->object_name_len; hdb_handle_put (&object_instance_database, object_handle); objdb_rdunlock(); return (0); } static int object_track_start(hdb_handle_t 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, object_reload_notify_fn_t object_reload_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->object_reload_notify_fn = object_reload_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, object_reload_notify_fn_t object_reload_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->object_reload_notify_fn == object_reload_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(hdb_handle_t object_handle, FILE *file) { struct object_instance *instance; unsigned int res; objdb_rdlock(); res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { objdb_rdunlock(); return (res); } res = _dump_object(instance, file, -1); hdb_handle_put (&object_instance_database, object_handle); objdb_rdunlock(); return (res); } static int object_write_config(const char **error_string) { struct config_iface_ver0 **modules; int num_modules; int i; int res; main_get_config_modules(&modules, &num_modules); objdb_wrlock(); for (i=0; iconfig_writeconfig) { res = modules[i]->config_writeconfig(&objdb_iface, error_string); if (res) { objdb_wrunlock(); return res; } } } objdb_wrunlock(); return 0; } static int object_reload_config(int flush, const char **error_string) { struct config_iface_ver0 **modules; int num_modules; int i; int res; main_get_config_modules(&modules, &num_modules); object_reload_notification(OBJDB_RELOAD_NOTIFY_START, flush); objdb_wrlock(); for (i=0; iconfig_reloadconfig) { res = modules[i]->config_reloadconfig(&objdb_iface, flush, error_string); if (res) { object_reload_notification(OBJDB_RELOAD_NOTIFY_FAILED, flush); objdb_wrunlock(); return res; } } } objdb_wrunlock(); object_reload_notification(OBJDB_RELOAD_NOTIFY_END, flush); 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_key_get = object_key_get, .object_key_iter_reset = object_key_iter_reset, .object_key_iter = object_key_iter, .object_key_iter_from = object_key_iter_from, .object_priv_get = object_priv_get, .object_parent_get = object_parent_get, .object_name_get = object_name_get, .object_track_start = object_track_start, .object_track_stop = object_track_stop, .object_dump = object_dump, .object_write_config = object_write_config, .object_reload_config = object_reload_config, .object_key_increment = object_key_increment, .object_key_decrement = object_key_decrement, }; 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/include/corosync/engine/objdb.h b/include/corosync/engine/objdb.h index 9ef6b0d9..56cd8a7c 100644 --- a/include/corosync/engine/objdb.h +++ b/include/corosync/engine/objdb.h @@ -1,239 +1,240 @@ /* * Copyright (c) 2006 MontaVista Software, Inc. * Copyright (c) 2007-2009 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 0xFFFFFFFF00000000ULL #include #include 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 enum { OBJDB_RELOAD_NOTIFY_START, OBJDB_RELOAD_NOTIFY_END, OBJDB_RELOAD_NOTIFY_FAILED } objdb_reload_notify_type_t; typedef void (*object_key_change_notify_fn_t)( object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_len, const void *key_value_pt, size_t key_value_len, void *priv_data_pt); typedef void (*object_create_notify_fn_t) (unsigned int parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len, void *priv_data_pt); typedef void (*object_destroy_notify_fn_t) (unsigned int parent_object_handle, - void *name_pt, size_t name_len, + const void *name_pt, + size_t name_len, void *priv_data_pt); typedef void (*object_reload_notify_fn_t) (objdb_reload_notify_type_t, int flush, void *priv_data_pt); struct object_valid { char *object_name; size_t object_len; }; struct object_key_valid { char *key_name; size_t key_len; int (*validate_callback) (const void *key, size_t key_len, const void *value, size_t value_len); }; struct objdb_iface_ver0 { int (*objdb_init) (void); int (*object_create) ( hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len); int (*object_priv_set) ( hdb_handle_t object_handle, void *priv); int (*object_key_create) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *value, size_t value_len); int (*object_destroy) ( hdb_handle_t object_handle); int (*object_valid_set) ( hdb_handle_t object_handle, struct object_valid *object_valid_list, unsigned int object_valid_list_entries); int (*object_key_valid_set) ( hdb_handle_t object_handle, struct object_key_valid *object_key_valid_list, unsigned int object_key_valid_list_entries); int (*object_find_create) ( hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_find_handle); int (*object_find_next) ( hdb_handle_t object_find_handle, hdb_handle_t *object_handle); int (*object_find_destroy) ( hdb_handle_t object_find_handle); int (*object_key_get) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, void **value, size_t *value_len); int (*object_priv_get) ( hdb_handle_t jobject_handle, void **priv); int (*object_key_replace) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *new_value, size_t new_value_len); int (*object_key_delete) ( hdb_handle_t object_handle, const void *key_name, size_t key_len); int (*object_iter_reset) ( hdb_handle_t parent_object_handle); int (*object_iter) ( hdb_handle_t parent_object_handle, void **object_name, size_t *name_len, hdb_handle_t *object_handle); int (*object_key_iter_reset) ( hdb_handle_t object_handle); int (*object_key_iter) ( hdb_handle_t parent_object_handle, void **key_name, size_t *key_len, void **value, size_t *value_len); int (*object_parent_get) ( hdb_handle_t object_handle, hdb_handle_t *parent_handle); int (*object_name_get) ( hdb_handle_t object_handle, char *object_name, size_t *object_name_len); int (*object_dump) ( hdb_handle_t object_handle, FILE *file); int (*object_key_iter_from) ( hdb_handle_t parent_object_handle, hdb_handle_t start_pos, void **key_name, size_t *key_len, void **value, size_t *value_len); int (*object_track_start) ( hdb_handle_t 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, object_reload_notify_fn_t object_reload_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, object_reload_notify_fn_t object_reload_notify_fn, void * priv_data_pt); int (*object_write_config) (const char **error_string); int (*object_reload_config) ( int flush, const char **error_string); int (*object_key_increment) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, unsigned int *value); int (*object_key_decrement) ( hdb_handle_t object_handle, const void *key_name, size_t key_len, unsigned int *value); }; #endif /* OBJDB_H_DEFINED */ diff --git a/lib/sa-confdb.c b/lib/sa-confdb.c index 3b7828b7..ead48d06 100644 --- a/lib/sa-confdb.c +++ b/lib/sa-confdb.c @@ -1,411 +1,411 @@ /* * Copyright (c) 2008, 2009 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfie@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* * Provides stand-alone access to data in the corosync object database * when aisexec is not running. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sa-confdb.h" static struct objdb_iface_ver0 *objdb; static int num_config_modules; static struct config_iface_ver0 *config_modules[128]; void main_get_config_modules(struct config_iface_ver0 ***modules, int *num); char *strstr_rs (const char *haystack, const char *needle); static int load_objdb(void) { hdb_handle_t objdb_handle; void *objdb_p; int res; /* * Load the object database interface */ res = lcr_ifact_reference ( &objdb_handle, "objdb", 0, &objdb_p, (void *)0); if (res == -1) { return -1; } objdb = (struct objdb_iface_ver0 *)objdb_p; objdb->objdb_init (); return CS_OK; } static int load_config(void) { char *config_iface; char *iface; int res; hdb_handle_t config_handle; hdb_handle_t config_version = 0; void *config_p; struct config_iface_ver0 *config; - char *error_string; + const char *error_string; /* User's bootstrap config service */ config_iface = getenv("COROSYNC_DEFAULT_CONFIG_IFACE"); if (!config_iface) { if ((config_iface = strdup("corosync_parser")) == NULL) { return -1; } } /* Make a copy so we can deface it with strtok */ if ((config_iface = strdup(config_iface)) == NULL) { return -1; } iface = strtok(config_iface, ":"); while (iface) { res = lcr_ifact_reference ( &config_handle, iface, config_version, &config_p, 0); config = (struct config_iface_ver0 *)config_p; if (res == -1) { return -1; } res = config->config_readconfig(objdb, &error_string); if (res == -1) { return -1; } config_modules[num_config_modules++] = config; iface = strtok(NULL, ":"); } if (config_iface) free(config_iface); return CS_OK; } /* Needed by objdb when it writes back the configuration */ void main_get_config_modules(struct config_iface_ver0 ***modules, int *num) { *modules = config_modules; *num = num_config_modules; } /* Needed by some modules ... */ char *strstr_rs (const char *haystack, const char *needle) { char *end_address; char *new_needle; new_needle = (char *)strdup (needle); new_needle[strlen (new_needle) - 1] = '\0'; end_address = strstr (haystack, new_needle); if (end_address) { end_address += strlen (new_needle); end_address = strstr (end_address, needle + strlen (new_needle)); } if (end_address) { end_address += 1; /* skip past { or = */ do { if (*end_address == '\t' || *end_address == ' ') { end_address++; } else { break; } } while (*end_address != '\0'); } free (new_needle); return (end_address); } int confdb_sa_init (void) { int res; res = load_objdb(); if (res != CS_OK) return res; res = load_config(); return res; } int confdb_sa_object_create ( hdb_handle_t parent_object_handle, const void *object_name, size_t object_name_len, hdb_handle_t *object_handle) { return objdb->object_create(parent_object_handle, object_handle, object_name, object_name_len); } int confdb_sa_object_destroy ( hdb_handle_t object_handle) { return objdb->object_destroy(object_handle); } int confdb_sa_object_parent_get ( hdb_handle_t object_handle, hdb_handle_t *parent_object_handle) { return objdb->object_parent_get(object_handle, parent_object_handle); } int confdb_sa_key_create ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { return objdb->object_key_create(parent_object_handle, key_name, key_name_len, value, value_len); } int confdb_sa_key_delete ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *value, size_t value_len) { return objdb->object_key_delete(parent_object_handle, key_name, key_name_len); } int confdb_sa_key_get ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, void *value, size_t *value_len) { int res; void *kvalue; res = objdb->object_key_get(parent_object_handle, key_name, key_name_len, &kvalue, value_len); if (!res) { memcpy(value, kvalue, *value_len); } return res; } int confdb_sa_key_increment ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { int res; res = objdb->object_key_increment(parent_object_handle, key_name, key_name_len, value); return res; } int confdb_sa_key_decrement ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, unsigned int *value) { int res; res = objdb->object_key_decrement(parent_object_handle, key_name, key_name_len, value); return res; } int confdb_sa_key_replace ( hdb_handle_t parent_object_handle, const void *key_name, size_t key_name_len, const void *old_value, size_t old_value_len, const void *new_value, size_t new_value_len) { return objdb->object_key_replace(parent_object_handle, key_name, key_name_len, new_value, new_value_len); } int confdb_sa_write (char *error_text, size_t errbuf_len) { const char *errtext; int ret; ret = objdb->object_write_config(&errtext); if (!ret) { strncpy(error_text, errtext, errbuf_len); if (errbuf_len > 0) error_text[errbuf_len-1] = '\0'; } return ret; } int confdb_sa_reload ( int flush, char *error_text, size_t errbuf_len) { char *errtext; int ret; ret = objdb->object_reload_config(flush, (const char **) &errtext); if (!ret) { strncpy(error_text, errtext, errbuf_len); if (errbuf_len > 0) error_text[errbuf_len-1] = '\0'; } return ret; } int confdb_sa_object_find ( hdb_handle_t parent_object_handle, hdb_handle_t *find_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len) { int res; if (!*find_handle) { objdb->object_find_create(parent_object_handle, object_name, object_name_len, find_handle); } res = objdb->object_find_next(*find_handle, object_handle); return res; } int confdb_sa_object_iter ( hdb_handle_t parent_object_handle, hdb_handle_t *find_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len, void *found_object_name, size_t *found_object_name_len) { int res; if (!*find_handle) { objdb->object_find_create(parent_object_handle, object_name, object_name_len, find_handle); } res = objdb->object_find_next(*find_handle, object_handle); /* Return object name if we were called as _iter */ if (!res) { objdb->object_name_get(*object_handle, found_object_name, found_object_name_len); } return res; } int confdb_sa_key_iter ( hdb_handle_t parent_object_handle, hdb_handle_t start_pos, void *key_name, size_t *key_name_len, void *value, size_t *value_len) { int res; void *kname, *kvalue; res = objdb->object_key_iter_from(parent_object_handle, start_pos, &kname, key_name_len, &kvalue, value_len); if (!res) { memcpy(key_name, kname, *key_name_len); memcpy(value, kvalue, *value_len); } return res; } int confdb_sa_find_destroy(hdb_handle_t find_handle) { return objdb->object_find_destroy(find_handle); } diff --git a/services/confdb.c b/services/confdb.c index 0a9b723b..ad19a207 100644 --- a/services/confdb.c +++ b/services/confdb.c @@ -1,718 +1,718 @@ /* * Copyright (c) 2008-2009 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOGSYS_DECLARE_SUBSYS ("CONFDB", LOG_INFO); 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_object_find_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_key_increment (void *conn, void *message); static void message_handler_req_lib_confdb_key_decrement (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_reload (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, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, - const void *object_name_pt, int object_name_len, - const void *key_name_pt, int key_name_len, - const void *key_value_pt, int key_value_len, + const void *object_name_pt, size_t object_name_len, + const void *key_name_pt, size_t key_name_len, + const void *key_value_pt, size_t key_value_len, void *priv_data_pt); static void confdb_notify_lib_of_new_object( hdb_handle_t parent_object_handle, hdb_handle_t object_handle, - const uint8_t *name_pt, int name_len, + const uint8_t *name_pt, size_t name_len, void *priv_data_pt); static void confdb_notify_lib_of_destroyed_object( hdb_handle_t parent_object_handle, - const uint8_t *name_pt, int name_len, + const uint8_t *name_pt, size_t 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 = CS_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 = CS_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 = CS_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 = CS_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 = CS_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 = CS_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 = CS_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 = CS_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 = CS_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 = CS_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 = CS_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_STOP, .flow_control = CS_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 = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 13 */ .lib_handler_fn = message_handler_req_lib_confdb_reload, .response_size = sizeof (struct res_lib_confdb_reload), .response_id = MESSAGE_RES_CONFDB_RELOAD, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 14 */ .lib_handler_fn = message_handler_req_lib_confdb_object_find_destroy, .response_size = sizeof (mar_res_header_t), .response_id = MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 15 */ .lib_handler_fn = message_handler_req_lib_confdb_key_increment, .response_size = sizeof (struct res_lib_confdb_key_incdec), .response_id = MESSAGE_RES_CONFDB_KEY_INCREMENT, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, { /* 16 */ .lib_handler_fn = message_handler_req_lib_confdb_key_decrement, .response_size = sizeof (struct res_lib_confdb_key_incdec), .response_id = MESSAGE_RES_CONFDB_KEY_DECREMENT, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED }, }; struct corosync_service_engine confdb_service_engine = { .name = "corosync cluster config database access v1.01", .id = CONFDB_SERVICE, .private_data_size = 0, .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED, .allow_inquorate = CS_LIB_ALLOW_INQUORATE, .lib_init_fn = confdb_lib_init_fn, .lib_exit_fn = confdb_lib_exit_fn, .lib_engine = confdb_lib_engine, .lib_engine_count = sizeof (confdb_lib_engine) / sizeof (struct corosync_lib_handler), .exec_init_fn = confdb_exec_init_fn, }; /* * 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, NULL, 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; hdb_handle_t object_handle; int ret = CS_OK; if (api->object_create(req_lib_confdb_object_create->parent_object_handle, &object_handle, req_lib_confdb_object_create->object_name.value, req_lib_confdb_object_create->object_name.length)) ret = CS_ERR_ACCESS; res_lib_confdb_object_create.object_handle = object_handle; res_lib_confdb_object_create.header.size = sizeof(res_lib_confdb_object_create); res_lib_confdb_object_create.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE; res_lib_confdb_object_create.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_create, sizeof(res_lib_confdb_object_create)); } static void message_handler_req_lib_confdb_object_destroy (void *conn, 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 = CS_OK; if (api->object_destroy(req_lib_confdb_object_destroy->object_handle)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_object_find_destroy (void *conn, void *message) { struct req_lib_confdb_object_find_destroy *req_lib_confdb_object_find_destroy = (struct req_lib_confdb_object_find_destroy *)message; mar_res_header_t res; int ret = CS_OK; if (api->object_find_destroy(req_lib_confdb_object_find_destroy->find_handle)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_create (void *conn, 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 = CS_OK; if (api->object_key_create(req_lib_confdb_key_create->object_handle, req_lib_confdb_key_create->key_name.value, req_lib_confdb_key_create->key_name.length, req_lib_confdb_key_create->value.value, req_lib_confdb_key_create->value.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_CREATE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_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; + size_t value_len; void *value; int ret = CS_OK; if (api->object_key_get(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &value, &value_len)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_get.value.value, value, value_len); res_lib_confdb_key_get.value.length = value_len; } res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get); res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET; res_lib_confdb_key_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get)); } static void message_handler_req_lib_confdb_key_increment (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_incdec res_lib_confdb_key_incdec; int ret = CS_OK; if (api->object_key_increment(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &res_lib_confdb_key_incdec.value)) ret = CS_ERR_ACCESS; res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_INCREMENT; res_lib_confdb_key_incdec.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec)); } static void message_handler_req_lib_confdb_key_decrement (void *conn, 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_incdec res_lib_confdb_key_incdec; int ret = CS_OK; if (api->object_key_decrement(req_lib_confdb_key_get->parent_object_handle, req_lib_confdb_key_get->key_name.value, req_lib_confdb_key_get->key_name.length, &res_lib_confdb_key_incdec.value)) ret = CS_ERR_ACCESS; res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec); res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_DECREMENT; res_lib_confdb_key_incdec.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_incdec, sizeof(res_lib_confdb_key_incdec)); } static void message_handler_req_lib_confdb_key_replace (void *conn, void *message) { const struct req_lib_confdb_key_replace *req_lib_confdb_key_replace = message; mar_res_header_t res; int ret = CS_OK; if (api->object_key_replace(req_lib_confdb_key_replace->object_handle, req_lib_confdb_key_replace->key_name.value, req_lib_confdb_key_replace->key_name.length, req_lib_confdb_key_replace->new_value.value, req_lib_confdb_key_replace->new_value.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_REPLACE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_key_delete (void *conn, 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 = CS_OK; if (api->object_key_delete(req_lib_confdb_key_delete->object_handle, req_lib_confdb_key_delete->key_name.value, req_lib_confdb_key_delete->key_name.length)) ret = CS_ERR_ACCESS; res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_KEY_DELETE; res.error = ret; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_object_parent_get (void *conn, 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; hdb_handle_t object_handle; int ret = CS_OK; if (api->object_parent_get(req_lib_confdb_object_parent_get->object_handle, &object_handle)) ret = CS_ERR_ACCESS; res_lib_confdb_object_parent_get.parent_object_handle = object_handle; res_lib_confdb_object_parent_get.header.size = sizeof(res_lib_confdb_object_parent_get); res_lib_confdb_object_parent_get.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE; res_lib_confdb_object_parent_get.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_parent_get, sizeof(res_lib_confdb_object_parent_get)); } static void message_handler_req_lib_confdb_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; + size_t key_name_len; void *value; - int value_len; + size_t value_len; int ret = CS_OK; if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle, req_lib_confdb_key_iter->next_entry, &key_name, &key_name_len, &value, &value_len)) ret = CS_ERR_ACCESS; else { memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len); memcpy(res_lib_confdb_key_iter.value.value, value, value_len); res_lib_confdb_key_iter.key_name.length = key_name_len; res_lib_confdb_key_iter.value.length = value_len; } res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter); res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER; res_lib_confdb_key_iter.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter)); } static void message_handler_req_lib_confdb_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; - int object_name_len; + size_t object_name_len; int ret = CS_OK; if (!req_lib_confdb_object_iter->find_handle) { api->object_find_create(req_lib_confdb_object_iter->parent_object_handle, NULL, 0, &res_lib_confdb_object_iter.find_handle); } else res_lib_confdb_object_iter.find_handle = req_lib_confdb_object_iter->find_handle; if (api->object_find_next(res_lib_confdb_object_iter.find_handle, &res_lib_confdb_object_iter.object_handle)) { ret = CS_ERR_ACCESS; api->object_find_destroy(res_lib_confdb_object_iter.find_handle); } else { api->object_name_get(res_lib_confdb_object_iter.object_handle, (char *)res_lib_confdb_object_iter.object_name.value, &object_name_len); res_lib_confdb_object_iter.object_name.length = 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_response_send(conn, &res_lib_confdb_object_iter, sizeof(res_lib_confdb_object_iter)); } static void message_handler_req_lib_confdb_object_find (void *conn, 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 = CS_OK; if (!req_lib_confdb_object_find->find_handle) { api->object_find_create(req_lib_confdb_object_find->parent_object_handle, req_lib_confdb_object_find->object_name.value, req_lib_confdb_object_find->object_name.length, &res_lib_confdb_object_find.find_handle); } else res_lib_confdb_object_find.find_handle = req_lib_confdb_object_find->find_handle; if (api->object_find_next(res_lib_confdb_object_find.find_handle, &res_lib_confdb_object_find.object_handle)) { ret = CS_ERR_ACCESS; api->object_find_destroy(res_lib_confdb_object_find.find_handle); } res_lib_confdb_object_find.header.size = sizeof(res_lib_confdb_object_find); res_lib_confdb_object_find.header.id = MESSAGE_RES_CONFDB_OBJECT_FIND; res_lib_confdb_object_find.header.error = ret; api->ipc_response_send(conn, &res_lib_confdb_object_find, sizeof(res_lib_confdb_object_find)); } static void message_handler_req_lib_confdb_write (void *conn, void *message) { struct res_lib_confdb_write res_lib_confdb_write; int ret = CS_OK; const char *error_string = NULL; if (api->object_write_config(&error_string)) ret = CS_ERR_ACCESS; res_lib_confdb_write.header.size = sizeof(res_lib_confdb_write); res_lib_confdb_write.header.id = MESSAGE_RES_CONFDB_WRITE; res_lib_confdb_write.header.error = ret; if (error_string) { strcpy((char *)res_lib_confdb_write.error.value, error_string); res_lib_confdb_write.error.length = strlen(error_string) + 1; } else res_lib_confdb_write.error.length = 0; api->ipc_response_send(conn, &res_lib_confdb_write, sizeof(res_lib_confdb_write)); } static void message_handler_req_lib_confdb_reload (void *conn, void *message) { struct req_lib_confdb_reload *req_lib_confdb_reload = (struct req_lib_confdb_reload *)message; struct res_lib_confdb_reload res_lib_confdb_reload; int ret = CS_OK; const char *error_string = NULL; if (api->object_reload_config(req_lib_confdb_reload->flush, &error_string)) ret = CS_ERR_ACCESS; res_lib_confdb_reload.header.size = sizeof(res_lib_confdb_reload); res_lib_confdb_reload.header.id = MESSAGE_RES_CONFDB_RELOAD; res_lib_confdb_reload.header.error = ret; if(error_string) { strcpy((char *)res_lib_confdb_reload.error.value, error_string); res_lib_confdb_reload.error.length = strlen(error_string) + 1; } else res_lib_confdb_reload.error.length = 0; api->ipc_response_send(conn, &res_lib_confdb_reload, sizeof(res_lib_confdb_reload)); } static void confdb_notify_lib_of_key_change(object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, - const void *object_name_pt, int object_name_len, - const void *key_name_pt, int key_name_len, - const void *key_value_pt, int key_value_len, + const void *object_name_pt, size_t object_name_len, + const void *key_name_pt, size_t key_name_len, + const void *key_value_pt, size_t key_value_len, void *priv_data_pt) { struct res_lib_confdb_key_change_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK; res.header.error = CS_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_dispatch_send(priv_data_pt, &res, sizeof(res)); } static void confdb_notify_lib_of_new_object(hdb_handle_t parent_object_handle, hdb_handle_t object_handle, - const uint8_t *name_pt, int name_len, + const uint8_t *name_pt, size_t name_len, void *priv_data_pt) { struct res_lib_confdb_object_create_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK; res.header.error = CS_OK; res.parent_object_handle = parent_object_handle; res.object_handle = object_handle; memcpy(res.name.value, name_pt, name_len); res.name.length = name_len; api->ipc_dispatch_send(priv_data_pt, &res, sizeof(res)); } static void confdb_notify_lib_of_destroyed_object( hdb_handle_t parent_object_handle, - const uint8_t *name_pt, int name_len, + const uint8_t *name_pt, size_t name_len, void *priv_data_pt) { struct res_lib_confdb_object_destroy_callback res; res.header.size = sizeof(res); res.header.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK; res.header.error = CS_OK; res.parent_object_handle = parent_object_handle; memcpy(res.name.value, name_pt, name_len); res.name.length = name_len; api->ipc_dispatch_send(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, NULL, conn); res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_TRACK_START; res.error = CS_OK; api->ipc_response_send(conn, &res, sizeof(res)); } static void message_handler_req_lib_confdb_track_stop (void *conn, 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, NULL, conn); res.size = sizeof(res); res.id = MESSAGE_RES_CONFDB_TRACK_STOP; res.error = CS_OK; api->ipc_response_send(conn, &res, sizeof(res)); } diff --git a/services/testquorum.c b/services/testquorum.c index d8ab6998..5bd29606 100644 --- a/services/testquorum.c +++ b/services/testquorum.c @@ -1,155 +1,155 @@ /* * Copyright (c) 2008, 2009 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 Red Hat, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOGSYS_DECLARE_SUBSYS ("TEST", LOG_INFO); static void test_init(struct corosync_api_v1 *api, quorum_set_quorate_fn_t report); /* * lcrso object definition */ static struct quorum_services_api_ver1 test_quorum_iface_ver0 = { .init = test_init }; static struct lcr_iface corosync_test_quorum_ver0[1] = { { .name = "testquorum", .version = 0, .versions_replace = 0, .versions_replace_count = 0, .dependencies = 0, .dependency_count = 0, .constructor = NULL, .destructor = NULL, .interfaces = (void **)(void *)&test_quorum_iface_ver0, }, }; static struct lcr_comp test_quorum_comp_ver0 = { .iface_count = 1, .ifaces = corosync_test_quorum_ver0 }; __attribute__ ((constructor)) static void test_quorum_comp_register (void) { lcr_interfaces_set (&corosync_test_quorum_ver0[0], &test_quorum_iface_ver0); lcr_component_register (&test_quorum_comp_ver0); } /* -------------------------------------------------- */ static quorum_set_quorate_fn_t set_quorum; static void key_change_notify(object_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, - const void *object_name_pt, int object_name_len, - const void *key_name_pt, int key_len, - const void *key_value_pt, int key_value_len, + const void *object_name_pt, size_t object_name_len, + const void *key_name_pt, size_t key_len, + const void *key_value_pt, size_t key_value_len, void *priv_data_pt) { unsigned int members[1]; struct memb_ring_id ring_id; memset(&ring_id, 0, sizeof(ring_id)); /* If the 'quorum.quorate' key changes, then that changes quorum */ if (strncmp(key_name_pt, "quorate", key_len) == 0) { set_quorum(members, 0, atoi(key_value_pt), &ring_id); } } static void quorum_callback(int quorate, void *context) { log_printf(LOG_LEVEL_DEBUG, "quorum callback: quorate = %d\n", quorate); } static void test_init(struct corosync_api_v1 *api, quorum_set_quorate_fn_t report) { hdb_handle_t find_handle; hdb_handle_t quorum_handle = 0; set_quorum = report; /* * Register for objdb changes on quorum { } */ api->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle); api->object_find_next(find_handle, &quorum_handle); api->object_find_destroy(find_handle); api->object_track_start(quorum_handle, 1, key_change_notify, NULL, // object_create_notify NULL, // object_destroy_notify NULL, // object_reload_notify NULL); // priv_data /* Register for quorum changes too! */ api->quorum_register_callback(quorum_callback, NULL); } diff --git a/test/testconfdb.c b/test/testconfdb.c index a9949e12..874e0eed 100644 --- a/test/testconfdb.c +++ b/test/testconfdb.c @@ -1,260 +1,260 @@ /* * Copyright (c) 2008, 2009 Red Hat Inc * * All rights reserved. * * Author: Christine Caulfield * * 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 #include #include #include #include #include #include #include #include #include #include #define INCDEC_VALUE 45 /* Callbacks are not supported yet */ confdb_callbacks_t callbacks = { .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, hdb_handle_t parent_object_handle, int depth) { hdb_handle_t object_handle; char object_name[1024]; - int object_name_len; + size_t object_name_len; char key_name[1024]; - int key_name_len; + size_t key_name_len; char key_value[1024]; - int key_value_len; + size_t key_value_len; int res; int i; /* Show the keys */ res = confdb_key_iter_start(handle, parent_object_handle); if (res != CS_OK) { printf( "error resetting key iterator for object %llu: %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)) == CS_OK) { key_name[key_name_len] = '\0'; key_value[key_value_len] = '\0'; for (i=0; i * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #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, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name, size_t object_name_len, const void *key_name, size_t key_name_len, const void *key_value, size_t key_value_len); static void tail_object_created(confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len); static void tail_object_deleted(confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len); static confdb_callbacks_t callbacks = { .confdb_key_change_notify_fn = tail_key_changed, .confdb_object_create_change_notify_fn = tail_object_created, .confdb_object_delete_change_notify_fn = tail_object_deleted, }; static int action; /* Recursively dump the object tree */ static void print_config_tree(confdb_handle_t handle, hdb_handle_t parent_object_handle, char * parent_name) { hdb_handle_t object_handle; char object_name[OBJ_NAME_SIZE]; - int object_name_len; + size_t object_name_len; char key_name[OBJ_NAME_SIZE]; - int key_name_len; + size_t key_name_len; char key_value[OBJ_NAME_SIZE]; - int key_value_len; + size_t key_value_len; cs_error_t res; int children_printed; /* Show the keys */ res = confdb_key_iter_start(handle, parent_object_handle); if (res != CS_OK) { fprintf(stderr, "error resetting key iterator for object %llu: %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)) == CS_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 != CS_OK) { fprintf(stderr, "error resetting object iterator for object %llu: %d\n", parent_object_handle, res); exit(EXIT_FAILURE); } while ( (res = confdb_object_iter(handle, parent_object_handle, &object_handle, object_name, &object_name_len)) == CS_OK) { object_name[object_name_len] = '\0'; if (parent_name != NULL) { snprintf(key_value, OBJ_NAME_SIZE, "%s%c%s", parent_name, SEPERATOR, object_name); } 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 != CS_OK) { fprintf (stderr, "Could not initialize objdb library. Error %d\n", result); return 1; } print_config_tree(handle, OBJECT_PARENT_HANDLE, NULL); result = confdb_finalize (handle); return 0; } static int print_help(void) { printf("\n"); printf ("usage: corosync-objctl object%ckey ... Print an object\n", SEPERATOR); printf (" corosync-objctl -c object%cchild_obj ... Create Object\n", SEPERATOR); printf (" corosync-objctl -d object%cchild_obj ... Delete object\n", SEPERATOR); printf (" corosync-objctl -w object%cchild_obj.key=value ... Create a key\n", SEPERATOR); printf (" corosync-objctl -t object%cchild_obj ... Track changes\n", SEPERATOR); printf (" corosync-objctl -a Print all objects\n"); printf("\n"); return 0; } static cs_error_t validate_name(char * obj_name_pt) { if ((strchr (obj_name_pt, SEPERATOR) == NULL) && (strchr (obj_name_pt, '=') == NULL)) return CS_OK; else return CS_ERR_INVALID_PARAM; } static void get_parent_name(const char * name_pt, char * parent_name) { char * tmp; strcpy(parent_name, name_pt); /* first remove the value (it could be a file path */ tmp = strchr(parent_name, '='); if (tmp != NULL) *tmp = '\0'; /* then truncate the child name */ tmp = strrchr(parent_name, SEPERATOR); if (tmp != NULL) *tmp = '\0'; } static void get_key(const char * name_pt, char * key_name, char * key_value) { char * tmp; char 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 cs_error_t find_object (confdb_handle_t handle, char * name_pt, find_object_of_type_t type, hdb_handle_t * out_handle) { char * obj_name_pt; char * save_pt; hdb_handle_t obj_handle; confdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE; char tmp_name[OBJ_NAME_SIZE]; cs_error_t res; 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 != CS_OK) { fprintf (stderr, "Could not start object_find %d\n", res); exit (EXIT_FAILURE); } res = confdb_object_find(handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) { return res; } parent_object_handle = obj_handle; obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt); } *out_handle = parent_object_handle; return res; } static void read_object(confdb_handle_t handle, char * name_pt) { char parent_name[OBJ_NAME_SIZE]; hdb_handle_t obj_handle; cs_error_t res; get_parent_name(name_pt, parent_name); res = find_object (handle, name_pt, FIND_OBJECT_OR_KEY, &obj_handle); if (res == CS_OK) { print_config_tree(handle, obj_handle, parent_name); } } static void write_key(confdb_handle_t handle, char * path_pt) { hdb_handle_t obj_handle; char parent_name[OBJ_NAME_SIZE]; char key_name[OBJ_NAME_SIZE]; char key_value[OBJ_NAME_SIZE]; char old_key_value[OBJ_NAME_SIZE]; - int old_key_value_len; + size_t old_key_value_len; cs_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) != CS_OK) { fprintf(stderr, "Incorrect key name, can not have \"=\" or \"%c\"\n", SEPERATOR); exit(EXIT_FAILURE); } res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle); if (res != CS_OK) { fprintf(stderr, "Can't find parent object of \"%s\"\n", path_pt); exit(EXIT_FAILURE); } /* get the current key */ res = confdb_key_get (handle, obj_handle, key_name, strlen(key_name), old_key_value, &old_key_value_len); if (res == CS_OK) { /* replace the current value */ res = confdb_key_replace (handle, obj_handle, key_name, strlen(key_name), old_key_value, old_key_value_len, key_value, strlen(key_value)); if (res != CS_OK) fprintf(stderr, "Failed to replace the key %s=%s. Error %d\n", key_name, key_value, res); } else { /* not there, create a new key */ res = confdb_key_create (handle, obj_handle, key_name, strlen(key_name), key_value, strlen(key_value)); if (res != CS_OK) fprintf(stderr, "Failed to create the key %s=%s. Error %d\n", key_name, key_value, res); } } static void create_object(confdb_handle_t handle, char * name_pt) { char * obj_name_pt; char * save_pt; hdb_handle_t obj_handle; hdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE; char tmp_name[OBJ_NAME_SIZE]; cs_error_t res; strncpy (tmp_name, name_pt, 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 != CS_OK) { fprintf (stderr, "Could not start object_find %d\n", res); exit (EXIT_FAILURE); } res = confdb_object_find(handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) { if (validate_name(obj_name_pt) != CS_OK) { fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n", obj_name_pt); exit(EXIT_FAILURE); } res = confdb_object_create (handle, parent_object_handle, obj_name_pt, strlen (obj_name_pt), &obj_handle); if (res != CS_OK) fprintf(stderr, "Failed to create object \"%s\". Error %d.\n", obj_name_pt, res); } parent_object_handle = obj_handle; obj_name_pt = strtok_r (NULL, SEPERATOR_STR, &save_pt); } } /* Print "?" in place of any non-printable byte of OBJ. */ static void print_name (FILE *fp, const void *obj, size_t obj_len) { const char *p = obj; size_t i; for (i = 0; i < obj_len; i++) { int c = *p++; if (!isprint (c)) { c = '?'; } fputc (c, fp); } } static void tail_key_changed(confdb_handle_t handle, confdb_change_type_t change_type, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *object_name_pt, size_t object_name_len, const void *key_name_pt, size_t key_name_len, const void *key_value_pt, size_t key_value_len) { /* printf("key_changed> %.*s.%.*s=%.*s\n", */ fputs("key_changed> ", stdout); print_name (stdout, object_name_pt, object_name_len); fputs(".", stdout); print_name (stdout, key_name_pt, key_name_len); fputs("=", stdout); print_name (stdout, key_value_pt, key_value_len); fputs("\n", stdout); } static void tail_object_created(confdb_handle_t handle, hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const void *name_pt, size_t name_len) { fputs("object_created>", stdout); print_name(stdout, name_pt, name_len); fputs("\n", stdout); } static void tail_object_deleted(confdb_handle_t handle, hdb_handle_t parent_object_handle, const void *name_pt, size_t name_len) { fputs("object_deleted>", stdout); print_name(stdout, name_pt, name_len); fputs("\n", stdout); } static void listen_for_object_changes(confdb_handle_t handle) { int result; fd_set read_fds; int select_fd; int quit = CS_FALSE; FD_ZERO (&read_fds); if (confdb_fd_get (handle, &select_fd) != CS_OK) { printf ("can't get the confdb selector object.\n"); return; } printf ("Type \"q\" to finish\n"); do { FD_SET (select_fd, &read_fds); FD_SET (STDIN_FILENO, &read_fds); result = select (select_fd + 1, &read_fds, 0, 0, 0); if (result == -1) { perror ("select\n"); } if (FD_ISSET (STDIN_FILENO, &read_fds)) { char inbuf[3]; if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) quit = CS_TRUE; else if (strncmp(inbuf, "q", 1) == 0) quit = CS_TRUE; } if (FD_ISSET (select_fd, &read_fds)) { if (confdb_dispatch (handle, CONFDB_DISPATCH_ALL) != CS_OK) exit(1); } } while (result && quit == CS_FALSE); (void)confdb_stop_track_changes(handle); } static void track_object(confdb_handle_t handle, char * name_pt) { cs_error_t res; hdb_handle_t obj_handle; res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle); if (res != CS_OK) { fprintf (stderr, "Could not find object \"%s\". Error %d\n", name_pt, res); return; } res = confdb_track_changes (handle, obj_handle, CONFDB_TRACK_DEPTH_RECURSIVE); if (res != CS_OK) { fprintf (stderr, "Could not enable tracking on object \"%s\". Error %d\n", name_pt, res); return; } } static void stop_tracking(confdb_handle_t handle) { cs_error_t res; res = confdb_stop_track_changes (handle); if (res != CS_OK) { fprintf (stderr, "Could not stop tracking. Error %d\n", res); return; } } static void delete_object(confdb_handle_t handle, char * name_pt) { cs_error_t res; hdb_handle_t obj_handle; res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle); if (res == CS_OK) { res = confdb_object_destroy (handle, obj_handle); if (res != CS_OK) fprintf(stderr, "Failed to find object \"%s\" to delete. Error %d\n", name_pt, res); } else { char parent_name[OBJ_NAME_SIZE]; char key_name[OBJ_NAME_SIZE]; char key_value[OBJ_NAME_SIZE]; /* find the parent object */ get_parent_name(name_pt, parent_name); get_key(name_pt, key_name, key_value); res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle); if (res != CS_OK) { fprintf(stderr, "Failed to find the key's parent object \"%s\". Error %d\n", parent_name, res); exit (EXIT_FAILURE); } res = confdb_key_delete (handle, obj_handle, key_name, strlen(key_name), key_value, strlen(key_value)); if (res != CS_OK) fprintf(stderr, "Failed to delete key \"%s=%s\" from object \"%s\". Error %d\n", key_name, key_value, parent_name, res); } } int main (int argc, char *argv[]) { confdb_handle_t handle; cs_error_t result; int c; action = ACTION_READ; for (;;){ c = getopt (argc,argv,"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 != CS_OK) { fprintf (stderr, "Failed to initialize the objdb API. Error %d\n", result); exit (EXIT_FAILURE); } while (optind < argc) { switch (action) { case ACTION_READ: read_object(handle, argv[optind++]); break; case ACTION_WRITE: write_key(handle, argv[optind++]); break; case ACTION_CREATE: create_object(handle, argv[optind++]); break; case ACTION_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 != CS_OK) { fprintf (stderr, "Error finalizing objdb API. Error %d\n", result); exit(EXIT_FAILURE); } return 0; }