diff --git a/exec/objdb.c b/exec/objdb.c index 609fe5de..d04f9595 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; size_t key_len; void *value; 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; 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; 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, 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, 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, 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, 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, size_t key_len, const void *value, 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) + size_t 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) + size_t 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, 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, size_t key_len, void **value, 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, 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, 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, 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, size_t key_len, const void *new_value, 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, size_t *key_len, void **value, 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, size_t *key_len, void **value, 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, 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/cpg.h b/include/corosync/cpg.h index 6e849d39..8093dfba 100644 --- a/include/corosync/cpg.h +++ b/include/corosync/cpg.h @@ -1,201 +1,201 @@ /* * Copyright (c) 2006-2009 Red Hat, Inc. * * All rights reserved. * * Author: Christine Caulfield (ccaulfi@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the MontaVista Software, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef COROSYNC_CPG_H_DEFINED #define COROSYNC_CPG_H_DEFINED #include #include /** * @addtogroup cpg_corosync * * @{ */ typedef uint64_t cpg_handle_t; typedef enum { CPG_TYPE_UNORDERED, /* not implemented */ CPG_TYPE_FIFO, /* same as agreed */ CPG_TYPE_AGREED, CPG_TYPE_SAFE /* not implemented */ } cpg_guarantee_t; typedef enum { CPG_FLOW_CONTROL_DISABLED, /* flow control is disabled - new messages may be sent */ CPG_FLOW_CONTROL_ENABLED /* flow control is enabled - new messages should not be sent */ } cpg_flow_control_state_t; typedef enum { CPG_REASON_JOIN = 1, CPG_REASON_LEAVE = 2, CPG_REASON_NODEDOWN = 3, CPG_REASON_NODEUP = 4, CPG_REASON_PROCDOWN = 5 } cpg_reason_t; struct cpg_address { uint32_t nodeid; uint32_t pid; uint32_t reason; }; #define CPG_MAX_NAME_LENGTH 128 struct cpg_name { uint32_t length; char value[CPG_MAX_NAME_LENGTH]; }; #define CPG_MEMBERS_MAX 128 typedef void (*cpg_deliver_fn_t) ( cpg_handle_t handle, const struct cpg_name *group_name, uint32_t nodeid, uint32_t pid, const void *msg, size_t msg_len); typedef void (*cpg_confchg_fn_t) ( cpg_handle_t handle, const struct cpg_name *group_name, const struct cpg_address *member_list, size_t member_list_entries, const struct cpg_address *left_list, size_t left_list_entries, const struct cpg_address *joined_list, size_t joined_list_entries); typedef void (*cpg_groups_get_fn_t) ( cpg_handle_t handle, uint32_t group_num, uint32_t group_total, const struct cpg_name *group_name, const struct cpg_address *member_list, size_t member_list_entries); typedef struct { cpg_deliver_fn_t cpg_deliver_fn; cpg_confchg_fn_t cpg_confchg_fn; cpg_groups_get_fn_t cpg_groups_get_fn; } cpg_callbacks_t; /** @} */ /* * Create a new cpg connection */ cs_error_t cpg_initialize ( cpg_handle_t *handle, cpg_callbacks_t *callbacks); /* * Close the cpg handle */ cs_error_t cpg_finalize ( cpg_handle_t handle); /* * Get a file descriptor on which to poll. cpg_handle_t is NOT a * file descriptor and may not be used directly. */ cs_error_t cpg_fd_get ( cpg_handle_t handle, int *fd); -/* +/* * Get and set contexts for a CPG handle */ cs_error_t cpg_context_get ( cpg_handle_t handle, void **context); cs_error_t cpg_context_set ( cpg_handle_t handle, void *context); /* * Dispatch messages and configuration changes */ cs_error_t cpg_dispatch ( cpg_handle_t handle, cs_dispatch_flags_t dispatch_types); /* * Join one or more groups. * messages multicasted with cpg_mcast_joined will be sent to every * group that has been joined on handle handle. Any message multicasted * to a group that has been previously joined will be delivered in cpg_dispatch */ cs_error_t cpg_join ( cpg_handle_t handle, - struct cpg_name *group); + const struct cpg_name *group); /* * Leave one or more groups */ cs_error_t cpg_leave ( cpg_handle_t handle, - struct cpg_name *group); + const struct cpg_name *group); /* * Multicast to groups joined with cpg_join. * The iovec described by iovec will be multicasted to all groups joined with * the cpg_join interface for handle. */ cs_error_t cpg_mcast_joined ( cpg_handle_t handle, cpg_guarantee_t guarantee, - struct iovec *iovec, + const struct iovec *iovec, unsigned int iov_len); /* * Get membership information from cpg */ cs_error_t cpg_membership_get ( cpg_handle_t handle, struct cpg_name *groupName, struct cpg_address *member_list, int *member_list_entries); cs_error_t cpg_local_get ( cpg_handle_t handle, unsigned int *local_nodeid); cs_error_t cpg_groups_get ( cpg_handle_t handle, unsigned int *num_groups); cs_error_t cpg_flow_control_state_get ( cpg_handle_t handle, cpg_flow_control_state_t *flow_control_enabled); #endif /* COROSYNC_CPG_H_DEFINED */ diff --git a/include/corosync/engine/coroapi.h b/include/corosync/engine/coroapi.h index 6f6c69d8..25375573 100644 --- a/include/corosync/engine/coroapi.h +++ b/include/corosync/engine/coroapi.h @@ -1,603 +1,604 @@ /* * Copyright (c) 2008, 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 COROAPI_H_DEFINED #define COROAPI_H_DEFINED #include #ifdef COROSYNC_BSD #include #endif #include typedef void * corosync_timer_handle_t; struct corosync_tpg_group { const void *group; size_t group_len; }; #define TOTEMIP_ADDRLEN (sizeof(struct in6_addr)) #define PROCESSOR_COUNT_MAX 384 #define INTERFACE_MAX 2 #ifndef MESSAGE_SIZE_MAX #define MESSAGE_SIZE_MAX 1024*1024 /* (1MB) */ #endif /* MESSAGE_SIZE_MAX */ #ifndef MESSAGE_QUEUE_MAX #define MESSAGE_QUEUE_MAX MESSAGE_SIZE_MAX / totem_config->net_mtu #endif /* MESSAGE_QUEUE_MAX */ #define TOTEM_AGREED 0 #define TOTEM_SAFE 1 #define MILLI_2_NANO_SECONDS 1000000ULL #if !defined(TOTEM_IP_ADDRESS) struct totem_ip_address { unsigned int nodeid; unsigned short family; unsigned char addr[TOTEMIP_ADDRLEN]; } __attribute__((packed)); #endif #if !defined(MEMB_RING_ID) struct memb_ring_id { struct totem_ip_address rep; unsigned long long seq; } __attribute__((packed)); #endif #if !defined(TOTEM_CONFIGURATION_TYPE) enum totem_configuration_type { TOTEM_CONFIGURATION_REGULAR, TOTEM_CONFIGURATION_TRANSITIONAL }; #endif #if !defined(TOTEM_CALLBACK_TOKEN_TYPE) enum totem_callback_token_type { TOTEM_CALLBACK_TOKEN_RECEIVED = 1, TOTEM_CALLBACK_TOKEN_SENT = 2 }; #endif enum cs_lib_flow_control { CS_LIB_FLOW_CONTROL_REQUIRED = 1, CS_LIB_FLOW_CONTROL_NOT_REQUIRED = 2 }; #define corosync_lib_flow_control cs_lib_flow_control #define COROSYNC_LIB_FLOW_CONTROL_REQUIRED CS_LIB_FLOW_CONTROL_REQUIRED #define COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED CS_LIB_FLOW_CONTROL_NOT_REQUIRED enum cs_lib_allow_inquorate { CS_LIB_DISALLOW_INQUORATE = 0, /* default */ CS_LIB_ALLOW_INQUORATE = 1 }; #if !defined (COROSYNC_FLOW_CONTROL_STATE) enum cs_flow_control_state { CS_FLOW_CONTROL_STATE_DISABLED, CS_FLOW_CONTROL_STATE_ENABLED }; #define corosync_flow_control_state cs_flow_control_state #define CS_FLOW_CONTROL_STATE_DISABLED CS_FLOW_CONTROL_STATE_DISABLED #define CS_FLOW_CONTROL_STATE_ENABLED CS_FLOW_CONTROL_STATE_ENABLED #endif /* COROSYNC_FLOW_CONTROL_STATE */ typedef enum { COROSYNC_FATAL_ERROR_EXIT = -1, COROSYNC_LIBAIS_SOCKET = -6, COROSYNC_LIBAIS_BIND = -7, COROSYNC_READKEY = -8, COROSYNC_INVALID_CONFIG = -9, COROSYNC_DYNAMICLOAD = -12, COROSYNC_OUT_OF_MEMORY = -15, COROSYNC_FATAL_ERR = -16 } cs_fatal_error_t; #define corosync_fatal_error_t cs_fatal_error_t; #ifndef OBJECT_PARENT_HANDLE #define OBJECT_PARENT_HANDLE 0xffffffff00000000ULL 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); }; /* deprecated */ 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) ( hdb_handle_t parent_object_handle, hdb_handle_t object_handle, const uint8_t *name_pt, size_t name_len, void *priv_data_pt); typedef void (*object_destroy_notify_fn_t) ( hdb_handle_t parent_object_handle, const uint8_t *name_pt, size_t name_len, void *priv_data_pt); typedef void (*object_notify_callback_fn_t)( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *value, size_t value_len, object_change_type_t type, const void * priv_data_pt); typedef void (*object_reload_notify_fn_t) ( objdb_reload_notify_type_t, int flush, void *priv_data_pt); #endif /* OBJECT_PARENT_HANDLE_DEFINED */ #ifndef QUORUM_H_DEFINED typedef void (*quorum_callback_fn_t) (int quorate, void *context); struct quorum_callin_functions { int (*quorate) (void); int (*register_callback) (quorum_callback_fn_t callback_fn, void *context); int (*unregister_callback) (quorum_callback_fn_t callback_fn, void *context); }; typedef void (*sync_callback_fn_t) ( const unsigned int *view_list, size_t view_list_entries, int primary_designated, struct memb_ring_id *ring_id); #endif /* QUORUM_H_DEFINED */ struct corosync_api_v1 { /* * Object and configuration APIs */ 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); + size_t 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); + size_t 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); /* * Time and timer APIs */ int (*timer_add_duration) ( unsigned long long nanoseconds_in_future, void *data, void (*timer_nf) (void *data), corosync_timer_handle_t *handle); int (*timer_add_absolute) ( unsigned long long nanoseconds_from_epoch, void *data, void (*timer_fn) (void *data), corosync_timer_handle_t *handle); void (*timer_delete) ( corosync_timer_handle_t timer_handle); unsigned long long (*timer_time_get) (void); unsigned long long (*timer_expire_time_get) ( corosync_timer_handle_t timer_handle); /* * IPC APIs */ void (*ipc_source_set) (mar_message_source_t *source, void *conn); int (*ipc_source_is_local) (const mar_message_source_t *source); void *(*ipc_private_data_get) (void *conn); int (*ipc_response_send) (void *conn, const void *msg, size_t mlen); int (*ipc_response_iov_send) (void *conn, const struct iovec *iov, unsigned int iov_len); int (*ipc_dispatch_send) (void *conn, const void *msg, size_t mlen); int (*ipc_dispatch_iov_send) (void *conn, const struct iovec *iov, unsigned int iov_len); void (*ipc_refcnt_inc) (void *conn); void (*ipc_refcnt_dec) (void *conn); /* * Totem APIs */ unsigned int (*totem_nodeid_get) (void); int (*totem_family_get) (void); int (*totem_ring_reenable) (void); + /* FIXME: const iovec? */ int (*totem_mcast) (struct iovec *iovec, unsigned int iov_len, unsigned int guarantee); int (*totem_ifaces_get) ( unsigned int nodeid, struct totem_ip_address *interfaces, char ***status, unsigned int *iface_count); const char *(*totem_ifaces_print) (unsigned int nodeid); const char *(*totem_ip_print) (const struct totem_ip_address *addr); int (*totem_callback_token_create) ( void **handle_out, enum totem_callback_token_type type, int delete, int (*callback_fn) (enum totem_callback_token_type type, const void *), const void *data); /* * Totem open process groups API for those service engines * wanting their own groups */ int (*tpg_init) ( hdb_handle_t *handle, void (*deliver_fn) ( unsigned int nodeid, struct iovec *iovec, unsigned int iov_len, int endian_conversion_required), void (*confchg_fn) ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id)); int (*tpg_exit) ( hdb_handle_t handle); int (*tpg_join) ( hdb_handle_t handle, struct corosync_tpg_group *groups, size_t group_cnt); int (*tpg_leave) ( hdb_handle_t handle, struct corosync_tpg_group *groups, size_t group_cnt); int (*tpg_joined_mcast) ( hdb_handle_t handle, const struct iovec *iovec, unsigned int iov_len, int guarantee); int (*tpg_joined_reserve) ( hdb_handle_t handle, const struct iovec *iovec, unsigned int iov_len); int (*tpg_joined_release) ( int reserved_msgs); int (*tpg_groups_mcast) ( hdb_handle_t handle, int guarantee, const struct corosync_tpg_group *groups, size_t groups_cnt, const struct iovec *iovec, unsigned int iov_len); int (*tpg_groups_reserve) ( hdb_handle_t handle, const struct corosync_tpg_group *groups, size_t groups_cnt, const struct iovec *iovec, unsigned int iov_len); int (*tpg_groups_release) ( int reserved_msgs); int (*sync_request) ( const char *service_name); /* * User plugin-callable functions for quorum */ int (*quorum_is_quorate) (void); int (*quorum_register_callback) (quorum_callback_fn_t callback_fn, void *context); int (*quorum_unregister_callback) (quorum_callback_fn_t callback_fn, void *context); /* * This one is for the quorum management plugin's use */ int (*quorum_initialize)(struct quorum_callin_functions *fns); /* * Plugin loading and unloading */ int (*plugin_interface_reference) ( hdb_handle_t *handle, const char *iface_name, int version, void **interface, void *context); int (*plugin_interface_release) (hdb_handle_t handle); /* * Service loading and unloading APIs */ unsigned int (*service_link_and_init) ( struct corosync_api_v1 *corosync_api_v1, const char *service_name, unsigned int service_ver); unsigned int (*service_unlink_and_exit) ( struct corosync_api_v1 *corosync_api_v1, const char *service_name, unsigned int service_ver); /* * Error handling APIs */ void (*error_memory_failure) (void); #define corosync_fatal_error(err) api->fatal_error ((err), __FILE__, __LINE__) void (*fatal_error) (cs_fatal_error_t err, const char *file, unsigned int line); }; #define SERVICE_ID_MAKE(a,b) ( ((a)<<16) | (b) ) #define SERVICE_HANDLER_MAXIMUM_COUNT 64 struct corosync_lib_handler { void (*lib_handler_fn) (void *conn, const void *msg); int response_size; int response_id; enum cs_lib_flow_control flow_control; }; struct corosync_exec_handler { void (*exec_handler_fn) (const void *msg, unsigned int nodeid); void (*exec_endian_convert_fn) (void *msg); }; struct corosync_service_engine_iface_ver0 { struct corosync_service_engine *(*corosync_get_service_engine_ver0) (void); }; struct corosync_service_engine { const char *name; unsigned short id; unsigned int private_data_size; enum cs_lib_flow_control flow_control; enum cs_lib_allow_inquorate allow_inquorate; int (*exec_init_fn) (struct corosync_api_v1 *); int (*exec_exit_fn) (void); void (*exec_dump_fn) (void); int (*lib_init_fn) (void *conn); int (*lib_exit_fn) (void *conn); struct corosync_lib_handler *lib_engine; int lib_engine_count; struct corosync_exec_handler *exec_engine; int exec_engine_count; int (*config_init_fn) (struct corosync_api_v1 *); void (*confchg_fn) ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id); void (*sync_init) (void); int (*sync_process) (void); void (*sync_activate) (void); void (*sync_abort) (void); }; #endif /* COROAPI_H_DEFINED */ diff --git a/include/corosync/engine/objdb.h b/include/corosync/engine/objdb.h index 56cd8a7c..ce401a98 100644 --- a/include/corosync/engine/objdb.h +++ b/include/corosync/engine/objdb.h @@ -1,240 +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, 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); + size_t 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); + size_t 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/cpg.c b/lib/cpg.c index 74b0e2f5..5ac35557 100644 --- a/lib/cpg.c +++ b/lib/cpg.c @@ -1,659 +1,659 @@ /* * vi: set autoindent tabstop=4 shiftwidth=4 : * - * Copyright (c) 2006-2008 Red Hat, Inc. + * Copyright (c) 2006-2009 Red Hat, Inc. * * All rights reserved. * * Author: Patrick Caulfield (pcaulfie@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 a closed process group API using the coroipcc executive */ #include #include #include #include #include #include #include #include #include #include #include #include #include struct cpg_inst { void *ipc_ctx; int finalize; cpg_callbacks_t callbacks; void *context; pthread_mutex_t response_mutex; pthread_mutex_t dispatch_mutex; }; static void cpg_instance_destructor (void *instance); static struct saHandleDatabase cpg_handle_t_db = { .handleCount = 0, .handles = 0, .mutex = PTHREAD_MUTEX_INITIALIZER, .handleInstanceDestructor = cpg_instance_destructor }; /* * Clean up function for a cpg instance (cpg_nitialize) handle */ static void cpg_instance_destructor (void *instance) { struct cpg_inst *cpg_inst = instance; pthread_mutex_destroy (&cpg_inst->response_mutex); pthread_mutex_destroy (&cpg_inst->dispatch_mutex); } /** * @defgroup cpg_coroipcc The closed process group API * @ingroup coroipcc * * @{ */ cs_error_t cpg_initialize ( cpg_handle_t *handle, cpg_callbacks_t *callbacks) { cs_error_t error; struct cpg_inst *cpg_inst; error = saHandleCreate (&cpg_handle_t_db, sizeof (struct cpg_inst), handle); if (error != CS_OK) { goto error_no_destroy; } error = saHandleInstanceGet (&cpg_handle_t_db, *handle, (void *)&cpg_inst); if (error != CS_OK) { goto error_destroy; } error = coroipcc_service_connect (IPC_SOCKET_NAME, CPG_SERVICE, &cpg_inst->ipc_ctx); if (error != CS_OK) { goto error_put_destroy; } memcpy (&cpg_inst->callbacks, callbacks, sizeof (cpg_callbacks_t)); pthread_mutex_init (&cpg_inst->response_mutex, NULL); pthread_mutex_init (&cpg_inst->dispatch_mutex, NULL); saHandleInstancePut (&cpg_handle_t_db, *handle); return (CS_OK); error_put_destroy: saHandleInstancePut (&cpg_handle_t_db, *handle); error_destroy: saHandleDestroy (&cpg_handle_t_db, *handle); error_no_destroy: return (error); } cs_error_t cpg_finalize ( cpg_handle_t handle) { struct cpg_inst *cpg_inst; cs_error_t error; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } pthread_mutex_lock (&cpg_inst->response_mutex); /* * Another thread has already started finalizing */ if (cpg_inst->finalize) { pthread_mutex_unlock (&cpg_inst->response_mutex); saHandleInstancePut (&cpg_handle_t_db, handle); return (CPG_ERR_BAD_HANDLE); } cpg_inst->finalize = 1; coroipcc_service_disconnect (cpg_inst->ipc_ctx); pthread_mutex_unlock (&cpg_inst->response_mutex); saHandleDestroy (&cpg_handle_t_db, handle); saHandleInstancePut (&cpg_handle_t_db, handle); return (CPG_OK); } cs_error_t cpg_fd_get ( cpg_handle_t handle, int *fd) { cs_error_t error; struct cpg_inst *cpg_inst; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } *fd = coroipcc_fd_get (cpg_inst->ipc_ctx); saHandleInstancePut (&cpg_handle_t_db, handle); return (CS_OK); } cs_error_t cpg_context_get ( cpg_handle_t handle, void **context) { cs_error_t error; struct cpg_inst *cpg_inst; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } *context = cpg_inst->context; saHandleInstancePut (&cpg_handle_t_db, handle); return (CS_OK); } cs_error_t cpg_context_set ( cpg_handle_t handle, void *context) { cs_error_t error; struct cpg_inst *cpg_inst; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } cpg_inst->context = context; saHandleInstancePut (&cpg_handle_t_db, handle); return (CS_OK); } struct res_overlay { mar_res_header_t header __attribute__((aligned(8))); char data[512000]; }; cs_error_t cpg_dispatch ( cpg_handle_t handle, cs_dispatch_flags_t dispatch_types) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ int dispatch_avail; struct cpg_inst *cpg_inst; struct res_lib_cpg_confchg_callback *res_cpg_confchg_callback; struct res_lib_cpg_deliver_callback *res_cpg_deliver_callback; cpg_callbacks_t callbacks; struct res_overlay dispatch_data; int ignore_dispatch = 0; struct cpg_address member_list[CPG_MEMBERS_MAX]; struct cpg_address left_list[CPG_MEMBERS_MAX]; struct cpg_address joined_list[CPG_MEMBERS_MAX]; struct cpg_name group_name; mar_cpg_address_t *left_list_start; mar_cpg_address_t *joined_list_start; unsigned int i; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } /* * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and * wait indefinately for SA_DISPATCH_BLOCKING */ if (dispatch_types == CPG_DISPATCH_ALL) { timeout = 0; } do { pthread_mutex_lock (&cpg_inst->dispatch_mutex); dispatch_avail = coroipcc_dispatch_recv (cpg_inst->ipc_ctx, (void *)&dispatch_data, sizeof (dispatch_data), timeout); pthread_mutex_unlock (&cpg_inst->dispatch_mutex); if (error != CS_OK) { goto error_put; } if (dispatch_avail == 0 && dispatch_types == CPG_DISPATCH_ALL) { pthread_mutex_unlock (&cpg_inst->dispatch_mutex); break; /* exit do while cont is 1 loop */ } else if (dispatch_avail == 0) { pthread_mutex_unlock (&cpg_inst->dispatch_mutex); continue; /* next poll */ } if (dispatch_avail == -1) { if (cpg_inst->finalize == 1) { error = CS_OK; } else { error = CS_ERR_LIBRARY; } goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that cpgFinalize has been called. */ memcpy (&callbacks, &cpg_inst->callbacks, sizeof (cpg_callbacks_t)); /* * Dispatch incoming message */ switch (dispatch_data.header.id) { case MESSAGE_RES_CPG_DELIVER_CALLBACK: res_cpg_deliver_callback = (struct res_lib_cpg_deliver_callback *)&dispatch_data; marshall_from_mar_cpg_name_t ( &group_name, &res_cpg_deliver_callback->group_name); callbacks.cpg_deliver_fn (handle, &group_name, res_cpg_deliver_callback->nodeid, res_cpg_deliver_callback->pid, &res_cpg_deliver_callback->message, res_cpg_deliver_callback->msglen); break; case MESSAGE_RES_CPG_CONFCHG_CALLBACK: res_cpg_confchg_callback = (struct res_lib_cpg_confchg_callback *)&dispatch_data; for (i = 0; i < res_cpg_confchg_callback->member_list_entries; i++) { marshall_from_mar_cpg_address_t (&member_list[i], &res_cpg_confchg_callback->member_list[i]); } left_list_start = res_cpg_confchg_callback->member_list + res_cpg_confchg_callback->member_list_entries; for (i = 0; i < res_cpg_confchg_callback->left_list_entries; i++) { marshall_from_mar_cpg_address_t (&left_list[i], &left_list_start[i]); } joined_list_start = res_cpg_confchg_callback->member_list + res_cpg_confchg_callback->member_list_entries + res_cpg_confchg_callback->left_list_entries; for (i = 0; i < res_cpg_confchg_callback->joined_list_entries; i++) { marshall_from_mar_cpg_address_t (&joined_list[i], &joined_list_start[i]); } marshall_from_mar_cpg_name_t ( &group_name, &res_cpg_confchg_callback->group_name); callbacks.cpg_confchg_fn (handle, &group_name, member_list, res_cpg_confchg_callback->member_list_entries, left_list, res_cpg_confchg_callback->left_list_entries, joined_list, res_cpg_confchg_callback->joined_list_entries); break; default: error = CS_ERR_LIBRARY; goto error_put; break; } /* * Determine if more messages should be processed * */ switch (dispatch_types) { case CPG_DISPATCH_ONE: if (ignore_dispatch) { ignore_dispatch = 0; } else { cont = 0; } break; case CPG_DISPATCH_ALL: if (ignore_dispatch) { ignore_dispatch = 0; } break; case CPG_DISPATCH_BLOCKING: break; } } while (cont); error_put: saHandleInstancePut (&cpg_handle_t_db, handle); return (error); } cs_error_t cpg_join ( cpg_handle_t handle, - struct cpg_name *group) + const struct cpg_name *group) { cs_error_t error; struct cpg_inst *cpg_inst; struct iovec iov[2]; struct req_lib_cpg_join req_lib_cpg_join; struct res_lib_cpg_join res_lib_cpg_join; struct req_lib_cpg_trackstart req_lib_cpg_trackstart; struct res_lib_cpg_trackstart res_lib_cpg_trackstart; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } pthread_mutex_lock (&cpg_inst->response_mutex); /* Automatically add a tracker */ req_lib_cpg_trackstart.header.size = sizeof (struct req_lib_cpg_trackstart); req_lib_cpg_trackstart.header.id = MESSAGE_REQ_CPG_TRACKSTART; marshall_to_mar_cpg_name_t (&req_lib_cpg_trackstart.group_name, group); iov[0].iov_base = &req_lib_cpg_trackstart; iov[0].iov_len = sizeof (struct req_lib_cpg_trackstart); error = coroipcc_msg_send_reply_receive (cpg_inst->ipc_ctx, iov, 1, &res_lib_cpg_trackstart, sizeof (struct res_lib_cpg_trackstart)); if (error != CS_OK) { pthread_mutex_unlock (&cpg_inst->response_mutex); goto error_exit; } /* Now join */ req_lib_cpg_join.header.size = sizeof (struct req_lib_cpg_join); req_lib_cpg_join.header.id = MESSAGE_REQ_CPG_JOIN; req_lib_cpg_join.pid = getpid(); marshall_to_mar_cpg_name_t (&req_lib_cpg_join.group_name, group); iov[0].iov_base = &req_lib_cpg_join; iov[0].iov_len = sizeof (struct req_lib_cpg_join); error = coroipcc_msg_send_reply_receive (cpg_inst->ipc_ctx, iov, 1, &res_lib_cpg_join, sizeof (struct res_lib_cpg_join)); pthread_mutex_unlock (&cpg_inst->response_mutex); if (error != CS_OK) { goto error_exit; } error = res_lib_cpg_join.header.error; error_exit: saHandleInstancePut (&cpg_handle_t_db, handle); return (error); } cs_error_t cpg_leave ( cpg_handle_t handle, - struct cpg_name *group) + const struct cpg_name *group) { cs_error_t error; struct cpg_inst *cpg_inst; struct iovec iov[2]; struct req_lib_cpg_leave req_lib_cpg_leave; struct res_lib_cpg_leave res_lib_cpg_leave; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } req_lib_cpg_leave.header.size = sizeof (struct req_lib_cpg_leave); req_lib_cpg_leave.header.id = MESSAGE_REQ_CPG_LEAVE; req_lib_cpg_leave.pid = getpid(); marshall_to_mar_cpg_name_t (&req_lib_cpg_leave.group_name, group); iov[0].iov_base = &req_lib_cpg_leave; iov[0].iov_len = sizeof (struct req_lib_cpg_leave); pthread_mutex_lock (&cpg_inst->response_mutex); error = coroipcc_msg_send_reply_receive (cpg_inst->ipc_ctx, iov, 1, &res_lib_cpg_leave, sizeof (struct res_lib_cpg_leave)); pthread_mutex_unlock (&cpg_inst->response_mutex); if (error != CS_OK) { goto error_exit; } error = res_lib_cpg_leave.header.error; error_exit: saHandleInstancePut (&cpg_handle_t_db, handle); return (error); } cs_error_t cpg_mcast_joined ( cpg_handle_t handle, cpg_guarantee_t guarantee, - struct iovec *iovec, + const struct iovec *iovec, unsigned int iov_len) { int i; cs_error_t error; struct cpg_inst *cpg_inst; struct iovec iov[64]; struct req_lib_cpg_mcast req_lib_cpg_mcast; struct res_lib_cpg_mcast res_lib_cpg_mcast; int msg_len = 0; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } for (i = 0; i < iov_len; i++ ) { msg_len += iovec[i].iov_len; } req_lib_cpg_mcast.header.size = sizeof (struct req_lib_cpg_mcast) + msg_len; req_lib_cpg_mcast.header.id = MESSAGE_REQ_CPG_MCAST; req_lib_cpg_mcast.guarantee = guarantee; req_lib_cpg_mcast.msglen = msg_len; iov[0].iov_base = &req_lib_cpg_mcast; iov[0].iov_len = sizeof (struct req_lib_cpg_mcast); memcpy (&iov[1], iovec, iov_len * sizeof (struct iovec)); pthread_mutex_lock (&cpg_inst->response_mutex); error = coroipcc_msg_send_reply_receive (cpg_inst->ipc_ctx, iov, iov_len + 1, &res_lib_cpg_mcast, sizeof (res_lib_cpg_mcast)); pthread_mutex_unlock (&cpg_inst->response_mutex); if (error != CS_OK) { goto error_exit; } error = res_lib_cpg_mcast.header.error; error_exit: saHandleInstancePut (&cpg_handle_t_db, handle); return (error); } cs_error_t cpg_membership_get ( cpg_handle_t handle, struct cpg_name *group_name, struct cpg_address *member_list, int *member_list_entries) { cs_error_t error; struct cpg_inst *cpg_inst; struct iovec iov; struct req_lib_cpg_membership req_lib_cpg_membership_get; struct res_lib_cpg_confchg_callback res_lib_cpg_membership_get; unsigned int i; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } req_lib_cpg_membership_get.header.size = sizeof (mar_req_header_t); req_lib_cpg_membership_get.header.id = MESSAGE_REQ_CPG_MEMBERSHIP; iov.iov_base = &req_lib_cpg_membership_get; iov.iov_len = sizeof (mar_req_header_t); pthread_mutex_lock (&cpg_inst->response_mutex); error = coroipcc_msg_send_reply_receive (cpg_inst->ipc_ctx, &iov, 1, &res_lib_cpg_membership_get, sizeof (mar_res_header_t)); pthread_mutex_unlock (&cpg_inst->response_mutex); if (error != CS_OK) { goto error_exit; } error = res_lib_cpg_membership_get.header.error; /* * Copy results to caller */ *member_list_entries = res_lib_cpg_membership_get.member_list_entries; if (member_list) { for (i = 0; i < res_lib_cpg_membership_get.member_list_entries; i++) { marshall_from_mar_cpg_address_t (&member_list[i], &res_lib_cpg_membership_get.member_list[i]); } } error_exit: saHandleInstancePut (&cpg_handle_t_db, handle); return (error); } cs_error_t cpg_local_get ( cpg_handle_t handle, unsigned int *local_nodeid) { cs_error_t error; struct cpg_inst *cpg_inst; struct iovec iov; struct req_lib_cpg_local_get req_lib_cpg_local_get; struct res_lib_cpg_local_get res_lib_cpg_local_get; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } req_lib_cpg_local_get.header.size = sizeof (mar_req_header_t); req_lib_cpg_local_get.header.id = MESSAGE_REQ_CPG_LOCAL_GET; iov.iov_base = &req_lib_cpg_local_get; iov.iov_len = sizeof (struct req_lib_cpg_local_get); pthread_mutex_lock (&cpg_inst->response_mutex); error = coroipcc_msg_send_reply_receive (cpg_inst->ipc_ctx, &iov, 1, &res_lib_cpg_local_get, sizeof (res_lib_cpg_local_get)); pthread_mutex_unlock (&cpg_inst->response_mutex); if (error != CS_OK) { goto error_exit; } error = res_lib_cpg_local_get.header.error; *local_nodeid = res_lib_cpg_local_get.local_nodeid; error_exit: saHandleInstancePut (&cpg_handle_t_db, handle); return (error); } cs_error_t cpg_flow_control_state_get ( cpg_handle_t handle, cpg_flow_control_state_t *flow_control_state) { cs_error_t error; struct cpg_inst *cpg_inst; error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst); if (error != CS_OK) { return (error); } *flow_control_state = coroipcc_dispatch_flow_control_get (cpg_inst->ipc_ctx); saHandleInstancePut (&cpg_handle_t_db, handle); return (error); } /** @} */