]> git.proxmox.com Git - mirror_corosync.git/commitdiff
Add confdb, a library to access the configuration object database.
authorPatrick Caulfield <pcaulfie@redhat.com>
Wed, 16 Apr 2008 12:07:05 +0000 (12:07 +0000)
committerPatrick Caulfield <pcaulfie@redhat.com>
Wed, 16 Apr 2008 12:07:05 +0000 (12:07 +0000)
git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1516 fd59a12c-fef9-0310-b244-a6a79926bd2f

14 files changed:
Makefile
exec/Makefile
exec/confdb.c [new file with mode: 0644]
exec/objdb.c
exec/objdb.h
exec/service.c
include/confdb.h [new file with mode: 0644]
include/ipc_confdb.h [new file with mode: 0644]
include/ipc_gen.h
lib/Makefile
lib/confdb.c [new file with mode: 0644]
lib/libconfdb.versions [new file with mode: 0644]
test/Makefile
test/testconfdb.c [new file with mode: 0644]

index abbaf51169edb2ad088027902e6097032c56652d..6deefa540de05530a157c0555de7ded49bb5eb7f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -125,11 +125,11 @@ clean:
        rm -rf $(builddir)doc/api
 
 AIS_LIBS       = ais SaAmf SaClm SaCkpt SaEvt SaLck SaMsg evs cpg \
-                 cfg aisutil
+                 cfg aisutil confdb
 
 AIS_HEADERS    = saAis.h saAmf.h saClm.h saCkpt.h saEvt.h saEvt.h saLck.h \
                  saMsg.h cpg.h cfg.h evs.h ipc_gen.h mar_gen.h swab.h     \
-                 ais_util.h
+                 ais_util.h confdb.h
 
 EXEC_LIBS      = totem_pg logsys
 
index 095af8568181cad69e0ce6c8e28c28724ba5d5a3..a659e1bd30bb14096b5e6ca07d74b26074c40699 100644 (file)
@@ -1,6 +1,6 @@
 # Copyright (c) 2002-2006 MontaVista Software, Inc.
 # Copyright (c) 2006 Sun Microsystems, Inc.
-# Copyright (c) 2006-2007 Red Hat, Inc.
+# Copyright (c) 2006-2008 Red Hat, Inc.
 # 
 # All rights reserved.
 # 
@@ -62,8 +62,8 @@ AMF_SRC = amf.c amfutil.c amfnode.c amfcluster.c amfapp.c amfsg.c amfsu.c amfcom
 AMF_OBJS = amf.o amfutil.o amfnode.o amfcluster.o amfapp.o amfsg.o amfsu.o amfcomp.o amfsi.o
 
 # LCR objects
-LCR_SRC = evs.c clm.c ckpt.c evt.c lck.c msg.c cfg.c cpg.c aisparser.c vsf_ykd.c objdb.c $(AMF_SRC)
-LCR_OBJS = evs.o clm.o ckpt.o evt.o lck.o msg.o cfg.o cpg.o aisparser.o vsf_ykd.o objdb.o $(AMF_OBJS)
+LCR_SRC = evs.c clm.c ckpt.c evt.c lck.c msg.c cfg.c cpg.c aisparser.c vsf_ykd.c objdb.c confdb.c $(AMF_SRC)
+LCR_OBJS = evs.o clm.o ckpt.o evt.o lck.o msg.o cfg.o cpg.o aisparser.o vsf_ykd.o objdb.o confdb.o $(AMF_OBJS)
 
 # main executive objects
 MAIN_SRC = main.c mempool.c util.c sync.c service.c ipc.c flow.c timer.c \
@@ -81,6 +81,7 @@ all:libtotem_pg.a libtotem_pg.so.2.0.0 liblogsys.a liblogsys.so.2.0.0 \
        service_evs.lcrso service_clm.lcrso service_amf.lcrso \
        service_ckpt.lcrso service_evt.lcrso service_lck.lcrso \
        service_msg.lcrso service_cfg.lcrso service_cpg.lcrso \
+       service_confdb.lcrso \
        objdb.lcrso aisparser.lcrso vsf_ykd.lcrso keygen openais-instantiate
 else
 EXEC_OBJS = $(MAIN_OBJS) $(LCR_OBJS)
@@ -114,6 +115,9 @@ service_msg.lcrso: msg.o
 service_cfg.lcrso: cfg.o
        $(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ./aisexec -bind_at_load cfg.o -o $@
 
+service_confdb.lcrso: confdb.o
+       $(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ./aisexec -bind_at_load confdb.o -o $@
+
 service_cpg.lcrso: cpg.o
        $(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ./aisexec -bind_at_load cpg.o -o $@
 
@@ -153,6 +157,9 @@ service_msg.lcrso: msg.o
 service_cfg.lcrso: cfg.o
        $(CC) -shared -Wl,-soname,service_cfg.lcrso cfg.o -o $@
 
+service_confdb.lcrso: confdb.o
+       $(CC) -shared -Wl,-soname,service_confdb.lcrso confdb.o -o $@
+
 service_cpg.lcrso: cpg.o
        $(CC) -shared -Wl,-soname,service_cpg.lcrso cpg.o -o $@
 
@@ -234,6 +241,9 @@ msg.o: msg.c
 cfg.o: cfg.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
+confdb.o: confdb.c
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
 aisparser.o: aisparser.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
diff --git a/exec/confdb.c b/exec/confdb.c
new file mode 100644 (file)
index 0000000..b39d206
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "../include/saAis.h"
+#include "../include/ipc_gen.h"
+#include "../include/ipc_confdb.h"
+#include "../include/mar_gen.h"
+#include "../lcr/lcr_comp.h"
+#include "main.h"
+#include "flow.h"
+#include "ipc.h"
+#include "objdb.h"
+#include "service.h"
+#include "ipc.h"
+#include "logsys.h"
+
+LOGSYS_DECLARE_SUBSYS ("CONFDB", LOG_INFO);
+
+static struct objdb_iface_ver0 *global_objdb;
+
+static int confdb_exec_init_fn (struct objdb_iface_ver0 *objdb);
+
+static int confdb_lib_init_fn (void *conn);
+static int confdb_lib_exit_fn (void *conn);
+
+static void message_handler_req_lib_confdb_object_create (void *conn, void *message);
+static void message_handler_req_lib_confdb_object_destroy (void *conn, void *message);
+
+static void message_handler_req_lib_confdb_key_create (void *conn, void *message);
+static void message_handler_req_lib_confdb_key_get (void *conn, void *message);
+static void message_handler_req_lib_confdb_key_replace (void *conn, void *message);
+static void message_handler_req_lib_confdb_key_delete (void *conn, void *message);
+static void message_handler_req_lib_confdb_key_iter (void *conn, void *message);
+
+static void message_handler_req_lib_confdb_object_iter (void *conn, void *message);
+static void message_handler_req_lib_confdb_object_find (void *conn, void *message);
+
+static void message_handler_req_lib_confdb_object_parent_get (void *conn, void *message);
+
+static void message_handler_req_lib_confdb_track_start (void *conn, void *message);
+static void message_handler_req_lib_confdb_track_stop (void *conn, void *message);
+
+
+/*
+ * Library Handler Definition
+ */
+static struct openais_lib_handler confdb_lib_service[] =
+{
+       { /* 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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_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                           = OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+       },
+       { /* 11 */
+               .lib_handler_fn                         = message_handler_req_lib_confdb_track_stop,
+               .response_size                          = sizeof (mar_res_header_t),
+               .response_id                            = MESSAGE_RES_CONFDB_TRACK_START,
+               .flow_control                           = OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+       },
+};
+
+
+struct openais_service_handler confdb_service_handler = {
+       .name                                   = "openais cluster config database access v1.01",
+       .id                                     = CONFDB_SERVICE,
+       .private_data_size                      = 0,
+       .flow_control                           = OPENAIS_FLOW_CONTROL_NOT_REQUIRED,
+       .lib_init_fn                            = confdb_lib_init_fn,
+       .lib_exit_fn                            = confdb_lib_exit_fn,
+       .lib_service                            = confdb_lib_service,
+       .lib_service_count                      = sizeof (confdb_lib_service) / sizeof (struct openais_lib_handler),
+       .exec_init_fn                           = confdb_exec_init_fn,
+};
+
+/*
+ * Dynamic loader definition
+ */
+static struct openais_service_handler *confdb_get_service_handler_ver0 (void);
+
+static struct openais_service_handler_iface_ver0 confdb_service_handler_iface = {
+       .openais_get_service_handler_ver0               = confdb_get_service_handler_ver0
+};
+
+static struct lcr_iface openais_confdb_ver0[1] = {
+       {
+               .name                           = "openais_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                         = openais_confdb_ver0
+};
+
+
+static struct openais_service_handler *confdb_get_service_handler_ver0 (void)
+{
+       return (&confdb_service_handler);
+}
+
+__attribute__ ((constructor)) static void confdb_comp_register (void) {
+        lcr_interfaces_set (&openais_confdb_ver0[0], &confdb_service_handler_iface);
+
+       lcr_component_register (&confdb_comp_ver0);
+}
+
+static int confdb_exec_init_fn (struct objdb_iface_ver0 *objdb)
+{
+       global_objdb = objdb;
+       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);
+       return (0);
+}
+
+static void message_handler_req_lib_confdb_object_create (void *conn, void *message)
+{
+       struct req_lib_confdb_object_create *req_lib_confdb_object_create = (struct req_lib_confdb_object_create *)message;
+       struct res_lib_confdb_object_create res_lib_confdb_object_create;
+       unsigned int object_handle;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_create(req_lib_confdb_object_create->parent_object_handle,
+                                       &object_handle,
+                                       req_lib_confdb_object_create->object_name.value,
+                                       req_lib_confdb_object_create->object_name.length))
+               ret = SA_AIS_ERR_ACCESS;
+
+       res_lib_confdb_object_create.object_handle = object_handle;
+       res_lib_confdb_object_create.header.size = sizeof(res_lib_confdb_object_create);
+       res_lib_confdb_object_create.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE;
+       res_lib_confdb_object_create.header.error = ret;
+       openais_conn_send_response(conn, &res_lib_confdb_object_create, sizeof(res_lib_confdb_object_create));
+}
+
+static void message_handler_req_lib_confdb_object_destroy (void *conn, void *message)
+{
+       struct req_lib_confdb_object_destroy *req_lib_confdb_object_destroy = (struct req_lib_confdb_object_destroy *)message;
+       mar_res_header_t res;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_destroy(req_lib_confdb_object_destroy->object_handle))
+               ret = SA_AIS_ERR_ACCESS;
+
+       res.size = sizeof(res);
+       res.id = MESSAGE_RES_CONFDB_OBJECT_CREATE;
+       res.error = ret;
+       openais_conn_send_response(conn, &res, sizeof(res));
+}
+
+
+static void message_handler_req_lib_confdb_key_create (void *conn, void *message)
+{
+       struct req_lib_confdb_key_create *req_lib_confdb_key_create = (struct req_lib_confdb_key_create *)message;
+       mar_res_header_t res;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_key_create(req_lib_confdb_key_create->object_handle,
+                                           req_lib_confdb_key_create->key_name.value,
+                                           req_lib_confdb_key_create->key_name.length,
+                                           req_lib_confdb_key_create->value.value,
+                                           req_lib_confdb_key_create->value.length))
+               ret = SA_AIS_ERR_ACCESS;
+
+       res.size = sizeof(res);
+       res.id = MESSAGE_RES_CONFDB_KEY_CREATE;
+       res.error = ret;
+       openais_conn_send_response(conn, &res, sizeof(res));
+}
+
+static void message_handler_req_lib_confdb_key_get (void *conn, void *message)
+{
+       struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message;
+       struct res_lib_confdb_key_get res_lib_confdb_key_get;
+       int value_len;
+       void *value;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_key_get(req_lib_confdb_key_get->parent_object_handle,
+                                        req_lib_confdb_key_get->key_name.value,
+                                        req_lib_confdb_key_get->key_name.length,
+                                        &value,
+                                        &value_len))
+               ret = SA_AIS_ERR_ACCESS;
+       else {
+               memcpy(res_lib_confdb_key_get.value.value, value, value_len);
+               res_lib_confdb_key_get.value.length = value_len;
+
+       }
+       res_lib_confdb_key_get.header.size = sizeof(res_lib_confdb_key_get);
+       res_lib_confdb_key_get.header.id = MESSAGE_RES_CONFDB_KEY_GET;
+       res_lib_confdb_key_get.header.error = ret;
+       openais_conn_send_response(conn, &res_lib_confdb_key_get, sizeof(res_lib_confdb_key_get));
+}
+
+static void message_handler_req_lib_confdb_key_replace (void *conn, void *message)
+{
+       struct req_lib_confdb_key_replace *req_lib_confdb_key_replace = (struct req_lib_confdb_key_replace *)message;
+       mar_res_header_t res;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_key_replace(req_lib_confdb_key_replace->object_handle,
+                                            req_lib_confdb_key_replace->key_name.value,
+                                            req_lib_confdb_key_replace->key_name.length,
+                                            req_lib_confdb_key_replace->old_value.value,
+                                            req_lib_confdb_key_replace->old_value.length,
+                                            req_lib_confdb_key_replace->new_value.value,
+                                            req_lib_confdb_key_replace->new_value.length))
+               ret = SA_AIS_ERR_ACCESS;
+
+       res.size = sizeof(res);
+       res.id = MESSAGE_RES_CONFDB_KEY_REPLACE;
+       res.error = ret;
+       openais_conn_send_response(conn, &res, sizeof(res));
+}
+
+static void message_handler_req_lib_confdb_key_delete (void *conn, void *message)
+{
+       struct req_lib_confdb_key_delete *req_lib_confdb_key_delete = (struct req_lib_confdb_key_delete *)message;
+       mar_res_header_t res;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_key_delete(req_lib_confdb_key_delete->object_handle,
+                                           req_lib_confdb_key_delete->key_name.value,
+                                           req_lib_confdb_key_delete->key_name.length,
+                                           req_lib_confdb_key_delete->value.value,
+                                           req_lib_confdb_key_delete->value.length))
+               ret = SA_AIS_ERR_ACCESS;
+
+       res.size = sizeof(res);
+       res.id = MESSAGE_RES_CONFDB_KEY_DELETE;
+       res.error = ret;
+       openais_conn_send_response(conn, &res, sizeof(res));
+}
+
+static void message_handler_req_lib_confdb_object_parent_get (void *conn, void *message)
+{
+       struct req_lib_confdb_object_parent_get *req_lib_confdb_object_parent_get = (struct req_lib_confdb_object_parent_get *)message;
+       struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get;
+       unsigned int object_handle;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_parent_get(req_lib_confdb_object_parent_get->object_handle,
+                                           &object_handle))
+               ret = SA_AIS_ERR_ACCESS;
+
+       res_lib_confdb_object_parent_get.parent_object_handle = object_handle;
+       res_lib_confdb_object_parent_get.header.size = sizeof(res_lib_confdb_object_parent_get);
+       res_lib_confdb_object_parent_get.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE;
+       res_lib_confdb_object_parent_get.header.error = ret;
+       openais_conn_send_response(conn, &res_lib_confdb_object_parent_get, sizeof(res_lib_confdb_object_parent_get));
+}
+
+
+static void message_handler_req_lib_confdb_key_iter (void *conn, void *message)
+{
+       struct req_lib_confdb_key_iter *req_lib_confdb_key_iter = (struct req_lib_confdb_key_iter *)message;
+       struct res_lib_confdb_key_iter res_lib_confdb_key_iter;
+       void *key_name;
+       int key_name_len;
+       void *value;
+       int value_len;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle,
+                                              req_lib_confdb_key_iter->next_entry,
+                                              &key_name,
+                                              &key_name_len,
+                                              &value,
+                                              &value_len))
+               ret = SA_AIS_ERR_ACCESS;
+       else {
+               memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len);
+               memcpy(res_lib_confdb_key_iter.value.value, value, value_len);
+               res_lib_confdb_key_iter.key_name.length = key_name_len;
+               res_lib_confdb_key_iter.value.length = value_len;
+       }
+       res_lib_confdb_key_iter.header.size = sizeof(res_lib_confdb_key_iter);
+       res_lib_confdb_key_iter.header.id = MESSAGE_RES_CONFDB_KEY_ITER;
+       res_lib_confdb_key_iter.header.error = ret;
+
+       openais_conn_send_response(conn, &res_lib_confdb_key_iter, sizeof(res_lib_confdb_key_iter));
+}
+
+static void message_handler_req_lib_confdb_object_iter (void *conn, void *message)
+{
+       struct req_lib_confdb_object_iter *req_lib_confdb_object_iter = (struct req_lib_confdb_object_iter *)message;
+       struct res_lib_confdb_object_iter res_lib_confdb_object_iter;
+       void *object_name;
+       int object_name_len;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_iter_from(req_lib_confdb_object_iter->parent_object_handle,
+                                          req_lib_confdb_object_iter->next_entry,
+                                          &object_name,
+                                          &object_name_len,
+                                          &res_lib_confdb_object_iter.object_handle))
+               ret = SA_AIS_ERR_ACCESS;
+       else {
+               res_lib_confdb_object_iter.object_name.length = object_name_len;
+               memcpy(res_lib_confdb_object_iter.object_name.value, object_name, object_name_len);
+       }
+       res_lib_confdb_object_iter.header.size = sizeof(res_lib_confdb_object_iter);
+       res_lib_confdb_object_iter.header.id = MESSAGE_RES_CONFDB_OBJECT_ITER;
+       res_lib_confdb_object_iter.header.error = ret;
+
+       openais_conn_send_response(conn, &res_lib_confdb_object_iter, sizeof(res_lib_confdb_object_iter));
+}
+
+static void message_handler_req_lib_confdb_object_find (void *conn, void *message)
+{
+       struct req_lib_confdb_object_find *req_lib_confdb_object_find = (struct req_lib_confdb_object_find *)message;
+       struct res_lib_confdb_object_find res_lib_confdb_object_find;
+       int ret = SA_AIS_OK;
+
+       if (global_objdb->object_find_from(req_lib_confdb_object_find->parent_object_handle,
+                                          req_lib_confdb_object_find->next_entry,
+                                          req_lib_confdb_object_find->object_name.value,
+                                          req_lib_confdb_object_find->object_name.length,
+                                          &res_lib_confdb_object_find.object_handle,
+                                          &res_lib_confdb_object_find.next_entry))
+               ret = SA_AIS_ERR_ACCESS;
+
+       res_lib_confdb_object_find.header.size = sizeof(res_lib_confdb_object_find);
+       res_lib_confdb_object_find.header.id = MESSAGE_RES_CONFDB_OBJECT_FIND;
+       res_lib_confdb_object_find.header.error = ret;
+
+       openais_conn_send_response(conn, &res_lib_confdb_object_find, sizeof(res_lib_confdb_object_find));
+}
+
+/* TODO: when we have notification in the objdb. */
+static void message_handler_req_lib_confdb_track_start (void *conn, void *message)
+{
+       mar_res_header_t res;
+
+       res.size = sizeof(res);
+       res.id = MESSAGE_RES_CONFDB_TRACK_START;
+       res.error = SA_AIS_ERR_NOT_SUPPORTED;
+       openais_conn_send_response(conn, &res, sizeof(res));
+}
+
+static void message_handler_req_lib_confdb_track_stop (void *conn, void *message)
+{
+       mar_res_header_t res;
+
+       res.size = sizeof(res);
+       res.id = MESSAGE_RES_CONFDB_TRACK_STOP;
+       res.error = SA_AIS_ERR_NOT_SUPPORTED;
+       openais_conn_send_response(conn, &res, sizeof(res));
+}
+
index 69093b1dcb793ba6e379667c800e7ce38d8f1be5..fe2540d77c34b2b7e2041da6df29c0a257a63073 100644 (file)
@@ -1,12 +1,13 @@
 /*
  * Copyright (c) 2006 MontaVista Software, Inc.
+ * Copyright (c) 2008 Red Hat, Inc.
  *
  * All rights reserved.
  *
  * Author: Steven Dake (sdake@mvista.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:
  *
@@ -503,7 +504,7 @@ static int object_key_get (
        void **value,
        int *value_len)
 {
-       unsigned int res;
+       unsigned int res = 0;
        struct object_instance *instance;
        struct object_key *object_key = NULL;
        struct list_head *list;
@@ -531,9 +532,12 @@ static int object_key_get (
                        *value_len = object_key->value_len;
                }
        }
+       else {
+               res = -1;
+       }
 
        hdb_handle_put (&object_instance_database, object_handle);
-       return (0);
+       return (res);
 
 error_exit:
        return (-1);
@@ -888,6 +892,156 @@ error_exit:
 }
 
 
+static int object_find_from(unsigned int parent_object_handle,
+                           unsigned int start_pos,
+                           void *object_name,
+                           int object_name_len,
+                           unsigned int *object_handle,
+                           unsigned int *next_pos)
+{
+       unsigned int res;
+       unsigned int pos = 0;
+       struct object_instance *instance;
+       struct object_instance *find_instance = NULL;
+       struct list_head *list;
+       unsigned int found = 0;
+
+       res = hdb_handle_get (&object_instance_database,
+               parent_object_handle, (void *)&instance);
+       if (res != 0) {
+               goto error_exit;
+       }
+       res = -ENOENT;
+       for (list = instance->child_head.next;
+               list != &instance->child_head; list = list->next) {
+
+                find_instance = list_entry (list, struct object_instance,
+                       child_list);
+
+               if ((find_instance->object_name_len == object_name_len) &&
+                       (memcmp (find_instance->object_name, object_name,
+                       object_name_len) == 0)) {
+                       if (pos++ == start_pos) {
+                               found = 1;
+                               break;
+                       }
+               }
+       }
+
+       hdb_handle_put (&object_instance_database, parent_object_handle);
+       if (found) {
+               *object_handle = find_instance->object_handle;
+               res = 0;
+       }
+       *next_pos = pos;
+       return (res);
+
+error_exit:
+       return (-1);
+}
+
+static int object_iter_from(unsigned int parent_object_handle,
+                           unsigned int start_pos,
+                           void **object_name,
+                           int *name_len,
+                           unsigned int *object_handle)
+{
+       unsigned int res;
+       unsigned int pos = 0;
+       struct object_instance *instance;
+       struct object_instance *find_instance = NULL;
+       struct list_head *list;
+       unsigned int found = 0;
+
+       res = hdb_handle_get (&object_instance_database,
+               parent_object_handle, (void *)&instance);
+       if (res != 0) {
+               goto error_exit;
+       }
+       res = -ENOENT;
+
+       for (list = instance->child_head.next;
+               list != &instance->child_head; list = list->next) {
+
+                find_instance = list_entry (list, struct object_instance,
+                                           child_list);
+               if (pos++ == start_pos) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found) {
+               *object_handle = find_instance->object_handle;
+               *object_name = find_instance->object_name;
+               *name_len = find_instance->object_name_len;
+               res = 0;
+       }
+       else {
+               res = -1;
+       }
+
+       return (res);
+
+error_exit:
+       return (-1);
+}
+
+static int object_key_iter_from(unsigned int parent_object_handle,
+                               unsigned int start_pos,
+                               void **key_name,
+                               int *key_len,
+                               void **value,
+                               int *value_len)
+{
+       unsigned int pos = 0;
+       unsigned int res;
+       struct object_instance *instance;
+       struct object_key *find_key = NULL;
+       struct list_head *list;
+       unsigned int found = 0;
+
+       res = hdb_handle_get (&object_instance_database,
+               parent_object_handle, (void *)&instance);
+       if (res != 0) {
+               goto error_exit;
+       }
+       res = -ENOENT;
+
+       for (list = instance->key_head.next;
+               list != &instance->key_head; list = list->next) {
+
+               find_key = list_entry (list, struct object_key, list);
+
+               if (pos++ == start_pos) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found) {
+               *key_name = find_key->key_name;
+               if (key_len)
+                       *key_len = find_key->key_len;
+               *value = find_key->value;
+               if (value_len)
+                       *value_len = find_key->value_len;
+               res = 0;
+       }
+       else {
+               res = -1;
+       }
+
+       hdb_handle_put (&object_instance_database, parent_object_handle);
+       return (res);
+
+error_exit:
+       return (-1);
+}
+
+
+
+
 static int object_parent_get(unsigned int object_handle,
                             unsigned int *parent_handle)
 {
@@ -942,11 +1096,14 @@ struct objdb_iface_ver0 objdb_iface = {
        .object_key_valid_set   = object_key_valid_set,
        .object_find_reset      = object_find_reset,
        .object_find            = object_find,
+       .object_find_from       = object_find_from,
        .object_key_get         = object_key_get,
        .object_key_iter        = object_key_iter,
        .object_key_iter_reset  = object_key_iter_reset,
+       .object_key_iter_from   = object_key_iter_from,
        .object_iter            = object_iter,
        .object_iter_reset      = object_iter_reset,
+       .object_iter_from       = object_iter_from,
        .object_priv_get        = object_priv_get,
        .object_parent_get      = object_parent_get,
        .object_dump            = object_dump
index 2de46afbf7eb66d869aa8d4ab20df7467663a340..b1713904c6d30dddee6b3a3655834bb669e05620 100644 (file)
@@ -145,6 +145,29 @@ struct objdb_iface_ver0 {
        int (*object_dump) (
                unsigned int object_handle,
                FILE *file);
+
+       int (*object_find_from) (
+               unsigned int parent_object_handle,
+               unsigned int start_pos,
+               void *object_name,
+               int object_name_len,
+               unsigned int *object_handle,
+               unsigned int *next_pos);
+
+       int (*object_iter_from) (
+               unsigned int parent_object_handle,
+               unsigned int start_pos,
+               void **object_name,
+               int *name_len,
+               unsigned int *object_handle);
+
+       int (*object_key_iter_from) (
+               unsigned int parent_object_handle,
+               unsigned int start_pos,
+               void **key_name,
+               int *key_len,
+               void **value,
+               int *value_len);
 };
 
 #endif /* OBJDB_H_DEFINED */
index ae0c8d3ed0ad48e879c41eb99c71afe918090460..7899f6b806afd81c8d8836e848b739911d1c0c18 100644 (file)
@@ -90,6 +90,10 @@ static struct default_service default_services[] = {
        {
                .name                    = "openais_cpg",
                .ver                     = 0,
+       },
+       {
+               .name                    = "openais_confdb",
+               .ver                     = 0,
        }
 };
 
diff --git a/include/confdb.h b/include/confdb.h
new file mode 100644 (file)
index 0000000..095e1e4
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfi@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPENAIS_CONFDB_H_DEFINED
+#define OPENAIS_CONFDB_H_DEFINED
+
+/**
+ * @addtogroup confdb_openais
+ *
+ * @{
+ */
+typedef uint64_t confdb_handle_t;
+
+#define OBJECT_PARENT_HANDLE 0
+
+typedef enum {
+       CONFDB_DISPATCH_ONE,
+       CONFDB_DISPATCH_ALL,
+       CONFDB_DISPATCH_BLOCKING
+} confdb_dispatch_t;
+
+typedef enum {
+       CONFDB_OK = 1,
+       CONFDB_ERR_LIBRARY = 2,
+       CONFDB_ERR_TIMEOUT = 5,
+       CONFDB_ERR_TRY_AGAIN = 6,
+       CONFDB_ERR_INVALID_PARAM = 7,
+       CONFDB_ERR_NO_MEMORY = 8,
+       CONFDB_ERR_BAD_HANDLE = 9,
+       CONFDB_ERR_ACCESS = 11,
+       CONFDB_ERR_NOT_EXIST = 12,
+       CONFDB_ERR_EXIST = 14,
+       CONFDB_ERR_CONTEXT_NOT_FOUND = 17,
+       CONFDB_ERR_NOT_SUPPORTED = 20,
+       CONFDB_ERR_SECURITY = 29,
+} confdb_error_t;
+
+
+typedef void (*confdb_change_notify_fn_t) (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       unsigned int object_handle,
+       void *object_name,
+       int  object_name_len,
+       void *key_name,
+       int key_name_len,
+       void *key_value,
+       int key_value_len);
+
+typedef struct {
+       confdb_change_notify_fn_t confdb_change_notify_fn;
+} confdb_callbacks_t;
+
+/** @} */
+
+/*
+ * Create a new confdb connection
+ */
+confdb_error_t confdb_initialize (
+       confdb_handle_t *handle,
+       confdb_callbacks_t *callbacks);
+
+/*
+ * Close the confdb handle
+ */
+confdb_error_t confdb_finalize (
+       confdb_handle_t handle);
+
+/*
+ * Get a file descriptor on which to poll.  confdb_handle_t is NOT a
+ * file descriptor and may not be used directly.
+ */
+confdb_error_t confdb_fd_get (
+       confdb_handle_t handle,
+       int *fd);
+
+/*
+ * Dispatch configuration changes
+ */
+confdb_error_t confdb_dispatch (
+       confdb_handle_t handle,
+       confdb_dispatch_t dispatch_types);
+
+
+/*
+ * Change notification
+ */
+confdb_error_t confdb_track_changes (
+       confdb_handle_t handle,
+       unsigned int object_handle,
+       unsigned int flags);
+
+confdb_error_t confdb_stop_track_changes (
+       confdb_handle_t handle);
+
+/*
+ * Manipulate objects
+ */
+confdb_error_t confdb_object_create (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *object_name,
+       int object_name_len,
+       unsigned int *object_handle);
+
+confdb_error_t confdb_object_destroy (
+       confdb_handle_t handle,
+       unsigned int object_handle);
+
+confdb_error_t confdb_object_parent_get (
+       confdb_handle_t handle,
+       unsigned int object_handle,
+       unsigned int *parent_object_handle);
+
+/*
+ * Manipulate keys
+ */
+confdb_error_t confdb_key_create (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int key_name_len,
+       void *value,
+       int value_len);
+
+confdb_error_t confdb_key_delete (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int key_name_len,
+       void *value,
+       int value_len);
+
+/*
+ * Key queries
+ */
+confdb_error_t confdb_key_get (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int key_name_len,
+       void *value,
+       int *value_len);
+
+confdb_error_t confdb_key_replace (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int key_name_len,
+       void *old_value,
+       int old_value_len,
+       void *new_value,
+       int new_value_len);
+
+/*
+ * Object queries
+ * "find" loops through all objects of a given name and is also
+ * a quick way of finding a specific object,
+ * "iter" returns ech object in sequence.
+ */
+confdb_error_t confdb_object_find_start (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle);
+
+confdb_error_t confdb_object_find (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *object_name,
+       int object_name_len,
+       unsigned int *object_handle);
+
+confdb_error_t confdb_object_iter_start (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle);
+
+confdb_error_t confdb_object_iter (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       unsigned int *object_handle,
+       void *object_name,
+       int *object_name_len);
+
+/*
+ * Key iterator
+ */
+confdb_error_t confdb_key_iter_start (
+       confdb_handle_t handle,
+       unsigned int object_handle);
+
+confdb_error_t confdb_key_iter (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int *key_name_len,
+       void *value,
+       int *value_len);
+
+
+#endif /* OPENAIS_CONFDB_H_DEFINED */
diff --git a/include/ipc_confdb.h b/include/ipc_confdb.h
new file mode 100644 (file)
index 0000000..84649e5
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef IPC_CONFDB_H_DEFINED
+#define IPC_CONFDB_H_DEFINED
+
+#include <netinet/in.h>
+#include "saAis.h"
+#include "ipc_gen.h"
+
+enum req_confdb_types {
+       MESSAGE_REQ_CONFDB_OBJECT_CREATE = 0,
+       MESSAGE_REQ_CONFDB_OBJECT_DESTROY = 1,
+       MESSAGE_REQ_CONFDB_OBJECT_FIND = 2,
+       MESSAGE_REQ_CONFDB_KEY_CREATE = 3,
+       MESSAGE_REQ_CONFDB_KEY_GET = 4,
+       MESSAGE_REQ_CONFDB_KEY_REPLACE = 5,
+       MESSAGE_REQ_CONFDB_KEY_DELETE = 6,
+       MESSAGE_REQ_CONFDB_OBJECT_ITER = 7,
+       MESSAGE_REQ_CONFDB_OBJECT_PARENT_GET = 8,
+       MESSAGE_REQ_CONFDB_KEY_ITER = 9,
+       MESSAGE_REQ_CONFDB_TRACK_START = 10,
+       MESSAGE_REQ_CONFDB_TRACK_STOP = 11
+};
+
+enum res_confdb_types {
+       MESSAGE_RES_CONFDB_OBJECT_CREATE = 0,
+       MESSAGE_RES_CONFDB_OBJECT_DESTROY = 1,
+       MESSAGE_RES_CONFDB_OBJECT_FIND = 2,
+       MESSAGE_RES_CONFDB_KEY_CREATE = 3,
+       MESSAGE_RES_CONFDB_KEY_GET = 4,
+       MESSAGE_RES_CONFDB_KEY_REPLACE = 5,
+       MESSAGE_RES_CONFDB_KEY_DELETE = 6,
+       MESSAGE_RES_CONFDB_OBJECT_ITER = 7,
+       MESSAGE_RES_CONFDB_OBJECT_PARENT_GET = 8,
+       MESSAGE_RES_CONFDB_KEY_ITER = 9,
+       MESSAGE_RES_CONFDB_TRACK_START = 10,
+       MESSAGE_RES_CONFDB_TRACK_STOP = 11,
+       MESSAGE_RES_CONFDB_CHANGE_CALLBACK = 12
+};
+
+
+struct req_lib_confdb_object_create {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+       mar_name_t object_name __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_object_create {
+       mar_res_header_t header __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_object_destroy {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_object_parent_get {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_object_parent_get {
+       mar_res_header_t header __attribute__((aligned(8)));
+       mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+};
+
+
+struct req_lib_confdb_key_create {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+       mar_name_t key_name __attribute__((aligned(8)));
+       mar_name_t value __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_key_delete {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+       mar_name_t key_name __attribute__((aligned(8)));
+       mar_name_t value __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_key_replace {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+       mar_name_t key_name __attribute__((aligned(8)));
+       mar_name_t old_value __attribute__((aligned(8)));
+       mar_name_t new_value __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_object_find {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+       mar_name_t object_name __attribute__((aligned(8)));
+       mar_uint32_t next_entry __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_object_find {
+       mar_res_header_t header __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+       mar_uint32_t next_entry __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_object_iter {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+       mar_uint32_t next_entry __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_object_iter {
+       mar_res_header_t header __attribute__((aligned(8)));
+       mar_name_t object_name __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_key_iter {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+       mar_uint32_t next_entry __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_key_iter {
+       mar_res_header_t header __attribute__((aligned(8)));
+       mar_name_t key_name __attribute__((aligned(8)));
+       mar_name_t value __attribute__((aligned(8)));
+};
+
+struct req_lib_confdb_key_get {
+       mar_req_header_t header __attribute__((aligned(8)));
+       mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+       mar_name_t key_name __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_key_get {
+       mar_res_header_t header __attribute__((aligned(8)));
+       mar_name_t value __attribute__((aligned(8)));
+};
+
+struct res_lib_confdb_change_callback {
+       mar_res_header_t header __attribute__((aligned(8)));
+       mar_uint32_t parent_object_handle __attribute__((aligned(8)));
+       mar_uint32_t object_handle __attribute__((aligned(8)));
+       mar_name_t object_name __attribute__((aligned(8)));
+       mar_name_t key_name __attribute__((aligned(8)));
+       mar_name_t key_value __attribute__((aligned(8)));
+};
+
+
+#endif /* IPC_CONFDB_H_DEFINED */
index 070fb0ac3bffc84b6ee1776c9ce7693d7a198984..3efbd3999d263952e40832b7f3302fb5e9838af3 100644 (file)
@@ -45,7 +45,8 @@ enum service_types {
        LCK_SERVICE = 5,
        MSG_SERVICE = 6,
        CFG_SERVICE = 7,
-       CPG_SERVICE = 8
+       CPG_SERVICE = 8,
+       CONFDB_SERVICE = 10
 };
 
 enum req_init_types {
index 6cb0403f0c91c632b1996b3c8d0ec4e3d79f7900..6a2a6fe38948bb7e8491f13d3b5b21bcf7acbe8e 100644 (file)
@@ -42,6 +42,7 @@ all:libSaClm.a libSaClm.so.2.0.0 \
        libSaLck.a libSaLck.so.2.0.0 \
        libSaMsg.a libSaMsg.so.2.0.0 \
        libcpg.a libcpg.so.2.0.0 \
+       libconfdb.a libconfdb.so.2.0.0 \
        libais.a libais.so.2.0.0 \
        libevs.a libevs.so.2.0.0 \
        libcfg.a libcfg.so.2.0.0 \
@@ -89,6 +90,9 @@ libevs.so.2.0.0: util.o evs.o
 libcpg.so.2.0.0: util.o cpg.o
        $(CC) -bundle -bind_at_load util.o cpg.o -o $@
 
+libconfdb.so.2.0.0: util.o confdb.o
+       $(CC) -bundle -bind_at_load util.o confdb.o -o $@
+
 libcfg.so.2.0.0: util.o cfg.o
        $(CC) -bundle -bind_at_load util.o cfg.o -o $@
 
@@ -124,6 +128,9 @@ libevs.so.2.0.0: util.o evs.o
 libcpg.so.2.0.0: util.o cpg.o
        $(CC) -shared -Wl,-soname,libcpg.so.2,-version-script=$(srcdir)$(subdir)libcpg.versions util.o cpg.o -o $@
 
+libconfdb.so.2.0.0: util.o confdb.o
+       $(CC) -shared -Wl,-soname,libconfdb.so.2,-version-script=$(srcdir)$(subdir)libconfdb.versions util.o confdb.o -o $@
+
 libcfg.so.2.0.0: util.o cfg.o
        $(CC) -shared -Wl,-soname,libcfg.so.2,-version-script=$(srcdir)$(subdir)libcfg.versions util.o cfg.o -o $@
 
@@ -153,6 +160,9 @@ libevs.a: util.o evs.o
 libcpg.a: util.o cpg.o
        $(AR) -rc libcpg.a util.o cpg.o
 
+libconfdb.a: util.o confdb.o
+       $(AR) -rc libconfdb.a util.o confdb.o
+
 libcfg.a: util.o cfg.o
        $(AR) -rc libcfg.a util.o cfg.o
 
@@ -160,7 +170,8 @@ clean:
        rm -f *.o libais.so* libais.a libSaClm.so* libSaClm.a* libSaAmf.so* libSaAmf.a \
                libSaCkpt.so* libSaCkpt.a* libSaEvt.so* libSaEvt.a libSaLck.so* libSaLck.a \
                libSaMsg.so* libSaMsg.a libcfg.so* libOpenaisCfg.a libaisutil.so* libaisutil.a \
-               libevs.so* libevs.a libcpg.so* libcpg.a libcfg.a *.da *.bb *.bbg
+               libevs.so* libevs.a libcpg.so* libcpg.a libcfg.a libconfdb.so* libconfdb.a libconfdb.a \
+               *.da *.bb *.bbg
  
 # -fPIC rules required for all libraries
 %.o: %.c
diff --git a/lib/confdb.c b/lib/confdb.c
new file mode 100644 (file)
index 0000000..af43da8
--- /dev/null
@@ -0,0 +1,985 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Provides access to data in the openais object database
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <saAis.h>
+#include <confdb.h>
+#include <ipc_confdb.h>
+#include <mar_gen.h>
+#include <ais_util.h>
+#include <list.h>
+
+/* Hold the information for iterators so that
+   callers can do recursive tree traversals.
+   each object_handle can have its own iterator */
+struct iter_context {
+       struct list_head list;
+       uint32_t parent_object_handle;
+       uint32_t context;
+};
+
+struct confdb_inst {
+       int response_fd;
+       int dispatch_fd;
+       int finalize;
+       confdb_callbacks_t callbacks;
+       void *context;
+       pthread_mutex_t response_mutex;
+       pthread_mutex_t dispatch_mutex;
+
+       struct list_head object_find_head;
+       struct list_head object_iter_head;
+       struct list_head key_iter_head;
+};
+
+static void confdb_instance_destructor (void *instance);
+
+static struct saHandleDatabase confdb_handle_t_db = {
+       .handleCount                    = 0,
+       .handles                        = 0,
+       .mutex                          = PTHREAD_MUTEX_INITIALIZER,
+       .handleInstanceDestructor       = confdb_instance_destructor
+};
+
+/* Safely tidy one iterator context list */
+static void free_context_list(struct list_head *list)
+{
+       struct iter_context *context;
+       struct list_head *iter, *tmp;
+
+       for (iter = list->next, tmp = iter->next;
+            iter != list; iter = tmp, tmp = iter->next) {
+
+               context = list_entry (iter, struct iter_context, list);
+               free(context);
+       }
+}
+
+/*
+ * Clean up function for a confdb instance (confdb_initialize) handle
+ */
+static void confdb_instance_destructor (void *instance)
+{
+       struct confdb_inst *confdb_inst = instance;
+
+       pthread_mutex_destroy (&confdb_inst->response_mutex);
+       pthread_mutex_destroy (&confdb_inst->dispatch_mutex);
+}
+
+static struct iter_context *find_iter_context(struct list_head *list, unsigned int object_handle)
+{
+       struct iter_context *context;
+       struct list_head *iter;
+
+       for (iter = list->next;
+            iter != list; iter = iter->next) {
+
+               context = list_entry (iter, struct iter_context, list);
+               if (context->parent_object_handle == object_handle)
+                       return context;
+       }
+       return NULL;
+}
+
+/**
+ * @defgroup confdb_openais
+ * @ingroup openais
+ *
+ * @{
+ */
+
+confdb_error_t confdb_initialize (
+       confdb_handle_t *handle,
+       confdb_callbacks_t *callbacks)
+{
+       SaAisErrorT error;
+       struct confdb_inst *confdb_inst;
+
+       error = saHandleCreate (&confdb_handle_t_db, sizeof (struct confdb_inst), handle);
+       if (error != SA_AIS_OK) {
+               goto error_no_destroy;
+       }
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, *handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               goto error_destroy;
+       }
+
+       error = saServiceConnect (&confdb_inst->dispatch_fd,
+                                 &confdb_inst->response_fd,
+                                 CONFDB_SERVICE);
+       if (error != SA_AIS_OK) {
+               goto error_put_destroy;
+       }
+
+       memcpy (&confdb_inst->callbacks, callbacks, sizeof (confdb_callbacks_t));
+
+       pthread_mutex_init (&confdb_inst->response_mutex, NULL);
+       pthread_mutex_init (&confdb_inst->dispatch_mutex, NULL);
+
+       list_init (&confdb_inst->object_find_head);
+       list_init (&confdb_inst->object_iter_head);
+       list_init (&confdb_inst->key_iter_head);
+
+       saHandleInstancePut (&confdb_handle_t_db, *handle);
+
+       return (SA_AIS_OK);
+
+error_put_destroy:
+       saHandleInstancePut (&confdb_handle_t_db, *handle);
+error_destroy:
+       saHandleDestroy (&confdb_handle_t_db, *handle);
+error_no_destroy:
+       return (error);
+}
+
+confdb_error_t confdb_finalize (
+       confdb_handle_t handle)
+{
+       struct confdb_inst *confdb_inst;
+       SaAisErrorT error;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       /*
+        * Another thread has already started finalizing
+        */
+       if (confdb_inst->finalize) {
+               pthread_mutex_unlock (&confdb_inst->response_mutex);
+               saHandleInstancePut (&confdb_handle_t_db, handle);
+               return (CONFDB_ERR_BAD_HANDLE);
+       }
+
+       confdb_inst->finalize = 1;
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+
+       saHandleDestroy (&confdb_handle_t_db, handle);
+
+       /* Free saved context handles */
+       free_context_list(&confdb_inst->object_find_head);
+       free_context_list(&confdb_inst->object_iter_head);
+       free_context_list(&confdb_inst->key_iter_head);
+
+       /*
+        * Disconnect from the server
+        */
+       if (confdb_inst->response_fd != -1) {
+               shutdown(confdb_inst->response_fd, 0);
+               close(confdb_inst->response_fd);
+       }
+       if (confdb_inst->dispatch_fd != -1) {
+               shutdown(confdb_inst->dispatch_fd, 0);
+               close(confdb_inst->dispatch_fd);
+       }
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (CONFDB_OK);
+}
+
+confdb_error_t confdb_fd_get (
+       confdb_handle_t handle,
+       int *fd)
+{
+       SaAisErrorT error;
+       struct confdb_inst *confdb_inst;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       *fd = confdb_inst->dispatch_fd;
+
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (SA_AIS_OK);
+}
+
+confdb_error_t confdb_context_get (
+       confdb_handle_t handle,
+       void **context)
+{
+       SaAisErrorT error;
+       struct confdb_inst *confdb_inst;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       *context = confdb_inst->context;
+
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (SA_AIS_OK);
+}
+
+confdb_error_t confdb_context_set (
+       confdb_handle_t handle,
+       void *context)
+{
+       SaAisErrorT error;
+       struct confdb_inst *confdb_inst;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       confdb_inst->context = context;
+
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (SA_AIS_OK);
+}
+
+struct res_overlay {
+       mar_res_header_t header __attribute__((aligned(8)));
+       char data[512000];
+};
+
+confdb_error_t confdb_dispatch (
+       confdb_handle_t handle,
+       confdb_dispatch_t dispatch_types)
+{
+       struct pollfd ufds;
+       int timeout = -1;
+       SaAisErrorT error;
+       int cont = 1; /* always continue do loop except when set to 0 */
+       int dispatch_avail;
+       struct confdb_inst *confdb_inst;
+       struct res_lib_confdb_change_callback *res_confdb_change_callback;
+       confdb_callbacks_t callbacks;
+       struct res_overlay dispatch_data;
+       int ignore_dispatch = 0;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       /*
+        * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and
+        * wait indefinately for SA_DISPATCH_BLOCKING
+        */
+       if (dispatch_types == CONFDB_DISPATCH_ALL) {
+               timeout = 0;
+       }
+
+       do {
+               ufds.fd = confdb_inst->dispatch_fd;
+               ufds.events = POLLIN;
+               ufds.revents = 0;
+
+               error = saPollRetry (&ufds, 1, timeout);
+               if (error != SA_AIS_OK) {
+                       goto error_nounlock;
+               }
+
+               pthread_mutex_lock (&confdb_inst->dispatch_mutex);
+
+               /*
+                * Regather poll data in case ufds has changed since taking lock
+                */
+               error = saPollRetry (&ufds, 1, timeout);
+               if (error != SA_AIS_OK) {
+                       goto error_nounlock;
+               }
+
+               /*
+                * Handle has been finalized in another thread
+                */
+               if (confdb_inst->finalize == 1) {
+                       error = CONFDB_OK;
+                       pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
+                       goto error_unlock;
+               }
+
+               dispatch_avail = ufds.revents & POLLIN;
+               if (dispatch_avail == 0 && dispatch_types == CONFDB_DISPATCH_ALL) {
+                       pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
+                       break; /* exit do while cont is 1 loop */
+               } else
+               if (dispatch_avail == 0) {
+                       pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
+                       continue; /* next poll */
+               }
+
+               if (ufds.revents & POLLIN) {
+                       /*
+                        * Queue empty, read response from socket
+                        */
+                       error = saRecvRetry (confdb_inst->dispatch_fd, &dispatch_data.header,
+                               sizeof (mar_res_header_t));
+                       if (error != SA_AIS_OK) {
+                               goto error_unlock;
+                       }
+                       if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
+                               error = saRecvRetry (confdb_inst->dispatch_fd, &dispatch_data.data,
+                                       dispatch_data.header.size - sizeof (mar_res_header_t));
+
+                               if (error != SA_AIS_OK) {
+                                       goto error_unlock;
+                               }
+                       }
+               } else {
+                       pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
+                       continue;
+               }
+
+               /*
+                * Make copy of callbacks, message data, unlock instance, and call callback
+                * A risk of this dispatch method is that the callback routines may
+                * operate at the same time that confdbFinalize has been called.
+               */
+               memcpy (&callbacks, &confdb_inst->callbacks, sizeof (confdb_callbacks_t));
+
+               pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
+               /*
+                * Dispatch incoming message
+                */
+               switch (dispatch_data.header.id) {
+               case MESSAGE_RES_CONFDB_CHANGE_CALLBACK:
+                       res_confdb_change_callback = (struct res_lib_confdb_change_callback *)&dispatch_data;
+
+                       callbacks.confdb_change_notify_fn (handle,
+                                                          res_confdb_change_callback->parent_object_handle,
+                                                          res_confdb_change_callback->object_handle,
+                                                          res_confdb_change_callback->object_name.value,
+                                                          res_confdb_change_callback->object_name.length,
+                                                          res_confdb_change_callback->key_name.value,
+                                                          res_confdb_change_callback->key_name.length,
+                                                          res_confdb_change_callback->key_value.value,
+                                                          res_confdb_change_callback->key_value.length);
+                       break;
+
+               default:
+                       error = SA_AIS_ERR_LIBRARY;
+                       goto error_nounlock;
+                       break;
+               }
+
+               /*
+                * Determine if more messages should be processed
+                * */
+               switch (dispatch_types) {
+               case CONFDB_DISPATCH_ONE:
+                       if (ignore_dispatch) {
+                               ignore_dispatch = 0;
+                       } else {
+                               cont = 0;
+                       }
+                       break;
+               case CONFDB_DISPATCH_ALL:
+                       if (ignore_dispatch) {
+                               ignore_dispatch = 0;
+                       }
+                       break;
+               case CONFDB_DISPATCH_BLOCKING:
+                       break;
+               }
+       } while (cont);
+
+error_unlock:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+error_nounlock:
+       return (error);
+}
+
+confdb_error_t confdb_object_create (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *object_name,
+       int object_name_len,
+       unsigned int *object_handle)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct req_lib_confdb_object_create req_lib_confdb_object_create;
+       struct res_lib_confdb_object_create res_lib_confdb_object_create;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       req_lib_confdb_object_create.header.size = sizeof (struct req_lib_confdb_object_create);
+       req_lib_confdb_object_create.header.id = MESSAGE_REQ_CONFDB_OBJECT_CREATE;
+       req_lib_confdb_object_create.parent_object_handle = parent_object_handle;
+       memcpy(req_lib_confdb_object_create.object_name.value, object_name, object_name_len);
+       req_lib_confdb_object_create.object_name.length = object_name_len;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_object_create;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_object_create);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res_lib_confdb_object_create, sizeof (struct res_lib_confdb_object_create));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res_lib_confdb_object_create.header.error;
+       *object_handle = res_lib_confdb_object_create.object_handle;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+confdb_error_t confdb_object_destroy (
+       confdb_handle_t handle,
+       unsigned int object_handle)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct req_lib_confdb_object_destroy req_lib_confdb_object_destroy;
+       mar_res_header_t res;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       req_lib_confdb_object_destroy.header.size = sizeof (struct req_lib_confdb_object_destroy);
+       req_lib_confdb_object_destroy.header.id = MESSAGE_REQ_CONFDB_OBJECT_DESTROY;
+       req_lib_confdb_object_destroy.object_handle = object_handle;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_object_destroy;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_object_destroy);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res, sizeof ( mar_res_header_t));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res.error;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+confdb_error_t confdb_object_parent_get (
+       confdb_handle_t handle,
+       unsigned int object_handle,
+       unsigned int *parent_object_handle)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct req_lib_confdb_object_parent_get req_lib_confdb_object_parent_get;
+       struct res_lib_confdb_object_parent_get res_lib_confdb_object_parent_get;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       req_lib_confdb_object_parent_get.header.size = sizeof (struct req_lib_confdb_object_parent_get);
+       req_lib_confdb_object_parent_get.header.id = MESSAGE_REQ_CONFDB_OBJECT_PARENT_GET;
+       req_lib_confdb_object_parent_get.object_handle = object_handle;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_object_parent_get;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_object_parent_get);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res_lib_confdb_object_parent_get, sizeof (struct res_lib_confdb_object_parent_get));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res_lib_confdb_object_parent_get.header.error;
+       *parent_object_handle = res_lib_confdb_object_parent_get.parent_object_handle;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+confdb_error_t confdb_key_create (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int key_name_len,
+       void *value,
+       int value_len)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct req_lib_confdb_key_create req_lib_confdb_key_create;
+       mar_res_header_t res;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       req_lib_confdb_key_create.header.size = sizeof (struct req_lib_confdb_key_create);
+       req_lib_confdb_key_create.header.id = MESSAGE_REQ_CONFDB_KEY_CREATE;
+       req_lib_confdb_key_create.object_handle = parent_object_handle;
+       memcpy(req_lib_confdb_key_create.key_name.value, key_name, key_name_len);
+       req_lib_confdb_key_create.key_name.length = key_name_len;
+       memcpy(req_lib_confdb_key_create.value.value, value, value_len);
+       req_lib_confdb_key_create.value.length = value_len;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_key_create;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_key_create);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res, sizeof (res));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res.error;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+confdb_error_t confdb_key_get (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int key_name_len,
+       void *value,
+       int *value_len)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct req_lib_confdb_key_get req_lib_confdb_key_get;
+       struct res_lib_confdb_key_get res_lib_confdb_key_get;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       req_lib_confdb_key_get.header.size = sizeof (struct req_lib_confdb_key_get);
+       req_lib_confdb_key_get.header.id = MESSAGE_REQ_CONFDB_KEY_GET;
+       req_lib_confdb_key_get.parent_object_handle = parent_object_handle;
+       memcpy(req_lib_confdb_key_get.key_name.value, key_name, key_name_len);
+       req_lib_confdb_key_get.key_name.length = key_name_len;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_key_get;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_key_get);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res_lib_confdb_key_get, sizeof (struct res_lib_confdb_key_get));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res_lib_confdb_key_get.header.error;
+       if (error == SA_AIS_OK) {
+               *value_len = res_lib_confdb_key_get.value.length;
+               memcpy(value, res_lib_confdb_key_get.value.value, *value_len);
+       }
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+
+confdb_error_t confdb_key_replace (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int key_name_len,
+       void *old_value,
+       int old_value_len,
+       void *new_value,
+       int new_value_len)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct req_lib_confdb_key_replace req_lib_confdb_key_replace;
+       mar_res_header_t res;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       req_lib_confdb_key_replace.header.size = sizeof (struct req_lib_confdb_key_replace);
+       req_lib_confdb_key_replace.header.id = MESSAGE_REQ_CONFDB_KEY_REPLACE;
+       req_lib_confdb_key_replace.object_handle = parent_object_handle;
+       memcpy(req_lib_confdb_key_replace.key_name.value, key_name, key_name_len);
+       req_lib_confdb_key_replace.key_name.length = key_name_len;
+       memcpy(req_lib_confdb_key_replace.old_value.value, old_value, old_value_len);
+       req_lib_confdb_key_replace.old_value.length = old_value_len;
+       memcpy(req_lib_confdb_key_replace.new_value.value, new_value, new_value_len);
+       req_lib_confdb_key_replace.new_value.length = new_value_len;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_key_replace;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_key_replace);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res, sizeof (res));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res.error;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+confdb_error_t confdb_object_iter_start (
+       confdb_handle_t handle,
+       unsigned int object_handle)
+{
+       struct confdb_inst *confdb_inst;
+       confdb_error_t error = SA_AIS_OK;
+       struct iter_context *context;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       context = find_iter_context(&confdb_inst->object_iter_head, object_handle);
+       if (!context) {
+               context = malloc(sizeof(struct iter_context));
+               if (!context) {
+                       error = CONFDB_ERR_NO_MEMORY;
+                       goto ret;
+               }
+               context->parent_object_handle = object_handle;
+               list_add(&context->list, &confdb_inst->object_iter_head);
+       }
+
+       context->context = 0;
+
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+ret:
+       return error;
+}
+
+confdb_error_t confdb_key_iter_start (
+       confdb_handle_t handle,
+       unsigned int object_handle)
+{
+       struct confdb_inst *confdb_inst;
+       confdb_error_t error = SA_AIS_OK;
+       struct iter_context *context;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       context = find_iter_context(&confdb_inst->key_iter_head, object_handle);
+       if (!context) {
+               context = malloc(sizeof(struct iter_context));
+               if (!context) {
+                       error = CONFDB_ERR_NO_MEMORY;
+                       goto ret;
+               }
+               context->parent_object_handle = object_handle;
+               list_add(&context->list, &confdb_inst->key_iter_head);
+       }
+
+       context->context = 0;
+
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+ret:
+       return error;
+}
+
+confdb_error_t confdb_object_find_start (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle)
+{
+       struct confdb_inst *confdb_inst;
+       confdb_error_t error = SA_AIS_OK;
+       struct iter_context *context;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle);
+       if (!context) {
+               context = malloc(sizeof(struct iter_context));
+               if (!context) {
+                       error = CONFDB_ERR_NO_MEMORY;
+                       goto ret;
+               }
+               context->parent_object_handle = parent_object_handle;
+               list_add(&context->list, &confdb_inst->object_find_head);
+       }
+
+       context->context = 0;
+
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+ret:
+       return error;
+}
+
+confdb_error_t confdb_object_find (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *object_name,
+       int object_name_len,
+       unsigned int *object_handle)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct iter_context *context;
+       struct req_lib_confdb_object_find req_lib_confdb_object_find;
+       struct res_lib_confdb_object_find res_lib_confdb_object_find;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       /* You MUST call confdb_object_find_start first */
+       context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle);
+       if (!context) {
+               error = CONFDB_ERR_CONTEXT_NOT_FOUND;
+               goto error_exit;
+       }
+
+       req_lib_confdb_object_find.header.size = sizeof (struct req_lib_confdb_object_find);
+       req_lib_confdb_object_find.header.id = MESSAGE_REQ_CONFDB_OBJECT_FIND;
+       req_lib_confdb_object_find.parent_object_handle = parent_object_handle;
+       req_lib_confdb_object_find.next_entry = context->context;
+       memcpy(req_lib_confdb_object_find.object_name.value, object_name, object_name_len);
+       req_lib_confdb_object_find.object_name.length = object_name_len;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_object_find;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_object_find);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res_lib_confdb_object_find, sizeof (struct res_lib_confdb_object_find));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res_lib_confdb_object_find.header.error;
+       *object_handle = res_lib_confdb_object_find.object_handle;
+       context->context = res_lib_confdb_object_find.next_entry;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+
+confdb_error_t confdb_object_iter (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       unsigned int *object_handle,
+       void *object_name,
+       int *object_name_len)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct iter_context *context;
+       struct req_lib_confdb_object_iter req_lib_confdb_object_iter;
+       struct res_lib_confdb_object_iter res_lib_confdb_object_iter;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       /* You MUST call confdb_object_iter_start first */
+       context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle);
+       if (!context) {
+               error = CONFDB_ERR_CONTEXT_NOT_FOUND;
+               goto error_exit;
+       }
+
+       req_lib_confdb_object_iter.header.size = sizeof (struct req_lib_confdb_object_iter);
+       req_lib_confdb_object_iter.header.id = MESSAGE_REQ_CONFDB_OBJECT_ITER;
+       req_lib_confdb_object_iter.parent_object_handle = parent_object_handle;
+       req_lib_confdb_object_iter.next_entry = context->context;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_object_iter;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_object_iter);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res_lib_confdb_object_iter, sizeof (struct res_lib_confdb_object_iter));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res_lib_confdb_object_iter.header.error;
+       if (error == SA_AIS_OK) {
+               *object_name_len = res_lib_confdb_object_iter.object_name.length;
+               memcpy(object_name, res_lib_confdb_object_iter.object_name.value, *object_name_len);
+               *object_handle = res_lib_confdb_object_iter.object_handle;
+       }
+
+       context->context++;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
+
+confdb_error_t confdb_key_iter (
+       confdb_handle_t handle,
+       unsigned int parent_object_handle,
+       void *key_name,
+       int *key_name_len,
+       void *value,
+       int *value_len)
+{
+       confdb_error_t error;
+       struct confdb_inst *confdb_inst;
+       struct iovec iov[2];
+       struct iter_context *context;
+       struct req_lib_confdb_key_iter req_lib_confdb_key_iter;
+       struct res_lib_confdb_key_iter res_lib_confdb_key_iter;
+
+       error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
+       if (error != SA_AIS_OK) {
+               return (error);
+       }
+
+       /* You MUST call confdb_key_iter_start first */
+       context = find_iter_context(&confdb_inst->key_iter_head, parent_object_handle);
+       if (!context) {
+               error = CONFDB_ERR_CONTEXT_NOT_FOUND;
+               goto error_exit;
+       }
+
+       req_lib_confdb_key_iter.header.size = sizeof (struct req_lib_confdb_key_iter);
+       req_lib_confdb_key_iter.header.id = MESSAGE_REQ_CONFDB_KEY_ITER;
+       req_lib_confdb_key_iter.parent_object_handle = parent_object_handle;
+       req_lib_confdb_key_iter.next_entry = context->context;
+
+       iov[0].iov_base = (char *)&req_lib_confdb_key_iter;
+       iov[0].iov_len = sizeof (struct req_lib_confdb_key_iter);
+
+       pthread_mutex_lock (&confdb_inst->response_mutex);
+
+       error = saSendMsgReceiveReply (confdb_inst->response_fd, iov, 1,
+               &res_lib_confdb_key_iter, sizeof (struct res_lib_confdb_key_iter));
+
+       pthread_mutex_unlock (&confdb_inst->response_mutex);
+       if (error != SA_AIS_OK) {
+               goto error_exit;
+       }
+
+       error = res_lib_confdb_key_iter.header.error;
+       if (error == SA_AIS_OK) {
+               *key_name_len = res_lib_confdb_key_iter.key_name.length;
+               memcpy(key_name, res_lib_confdb_key_iter.key_name.value, *key_name_len);
+               *value_len = res_lib_confdb_key_iter.value.length;
+               memcpy(value, res_lib_confdb_key_iter.value.value, *value_len);
+       }
+
+       context->context++;
+
+error_exit:
+       saHandleInstancePut (&confdb_handle_t_db, handle);
+
+       return (error);
+}
diff --git a/lib/libconfdb.versions b/lib/libconfdb.versions
new file mode 100644 (file)
index 0000000..29d8ca1
--- /dev/null
@@ -0,0 +1,38 @@
+# Version and symbol export for libconfdb.so
+
+OPENAIS_CONFDB_1.0 {
+       global:
+               confdb_initialize;
+               confdb_finalize;
+               confdb_fd_get;
+               confdb_dispatch;
+               confdb_track_changes;
+               confdb_stop_track_changes;
+               confdb_object_create;
+               confdb_object_destroy;
+               confdb_object_parent_get;
+               confdb_key_create;
+               confdb_key_delete;
+               confdb_key_get;
+               confdb_key_replace;
+               confdb_object_find_start;
+               confdb_object_find;
+               confdb_object_iter_start;
+               confdb_object_iter;
+               confdb_key_iter_start;
+               confdb_key_iter;
+
+       local:
+               saHandleCreate;
+               saHandleDestroy;
+               saHandleInstanceGet;
+               saHandleInstancePut;
+               saRecvRetry;
+               saSelectRetry;
+               saSendMsgReceiveReply;
+               saSendMsgRetry;
+               saSendReceiveReply;
+               saSendRetry;
+               saServiceConnect;
+               saVersionVerify;
+};
index 0c6b1c62eceb8636fa40672e2869dab60b96854e..be9747a594f2494d36565b66bcbf3f627db47463 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright (c) 2002-2004 MontaVista Software, Inc.
-# Copyright (c) 2006-2007 Red Hat, Inc.
+# Copyright (c) 2006-2008 Red Hat, Inc.
 # Copyright (c) 2006 Sun Microsystems, Inc.
 # 
 # All rights reserved.
@@ -38,13 +38,13 @@ ifeq (${OPENAIS_COMPAT}, SOLARIS)
        override LDFLAGS += -lnsl -lsocket -lrt
 endif
 
-LIBRARIES= ../lib/libSaClm.a ../lib/libSaAmf.a ../lib/libSaCkpt.a ../lib/libSaEvt.a ../lib/libSaLck.a ../lib/libSaMsg.a ../lib/libevs.a ../lib/libcpg.a ../lib/libcfg.a
+LIBRARIES= ../lib/libSaClm.a ../lib/libSaAmf.a ../lib/libSaCkpt.a ../lib/libSaEvt.a ../lib/libSaLck.a ../lib/libSaMsg.a ../lib/libevs.a ../lib/libcpg.a ../lib/libcfg.a ../lib/libconfdb.a
 LIBS = $(LIBRARIES) 
 BINARIES=testclm testamf1 \
        testckpt ckptstress ckptbench \
        ckptbenchth ckpt-rd ckpt-wr testevt testevs \
        evsbench subscription publish evtbench unlink testclm2 testlck \
-       testmsg testcpg testcpg2 cpgbench openais-cfgtool \
+       testmsg testcpg testcpg2 cpgbench testconfdb openais-cfgtool \
        logsys_s logsys_t1 logsys_t2
 
 override CFLAGS += -I../include
@@ -154,6 +154,9 @@ testcpg2: testcpg2.o $(LIBRARIES)
 cpgbench: cpgbench.o $(LIBRARIES)
        $(CC) $(LDFLAGS) -o cpgbench cpgbench.o $(LIBS)
 
+testconfdb: testconfdb.o $(LIBRARIES)
+       $(CC) $(LDFLAGS) -o testconfdb testconfdb.o $(LIBS)
+
 openais-cfgtool: openais-cfgtool.o $(LIBRARIES)
        $(CC) $(LDFLAGS) -o openais-cfgtool openais-cfgtool.o $(LIBS)
 
diff --git a/test/testconfdb.c b/test/testconfdb.c
new file mode 100644 (file)
index 0000000..64e194a
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2008 Red Hat Inc
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield <ccaulfie@redhat.com>
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include "saAis.h"
+#include "confdb.h"
+
+
+/* Callbacks are not supported yet */
+confdb_callbacks_t callbacks = {
+       .confdb_change_notify_fn = NULL,
+};
+
+/* Recursively dump the object tree */
+static void print_config_tree(confdb_handle_t handle, unsigned int parent_object_handle, int depth)
+{
+       unsigned int object_handle;
+       char object_name[1024];
+       int object_name_len;
+       char key_name[1024];
+       int key_name_len;
+       char key_value[1024];
+       int key_value_len;
+       int res;
+       int i;
+
+       /* Show the keys */
+       res = confdb_key_iter_start(handle, parent_object_handle);
+       if (res != SA_AIS_OK) {
+               printf( "error resetting key iterator for object %d: %d\n", parent_object_handle, res);
+               return;
+       }
+
+       while ( (res = confdb_key_iter(handle, parent_object_handle, key_name, &key_name_len,
+                                      key_value, &key_value_len)) == SA_AIS_OK) {
+               key_name[key_name_len] = '\0';
+               key_value[key_value_len] = '\0';
+               for (i=0; i<depth; i++) printf("  ");
+               printf("  KEY %s=%s\n", key_name, key_value);
+       }
+
+       /* Show sub-objects */
+       res = confdb_object_iter_start(handle, parent_object_handle);
+       if (res != SA_AIS_OK) {
+               printf( "error resetting object iterator for object %d: %d\n", parent_object_handle, res);
+               return;
+       }
+
+       while ( (res = confdb_object_iter(handle, parent_object_handle, &object_handle, object_name, &object_name_len)) == SA_AIS_OK)   {
+               unsigned int parent;
+
+               res = confdb_object_parent_get(handle, object_handle, &parent);
+               if (res != SA_AIS_OK) {
+                       printf( "error getting parent for object %d: %d\n", object_handle, res);
+                       return;
+               }
+
+               for (i=0; i<depth; i++) printf("  ");
+
+               object_name[object_name_len] = '\0';
+               printf("OBJECT: %s (%u, parent: %u)\n", object_name, object_handle, parent);
+
+               /* Down we go ... */
+               print_config_tree(handle, object_handle, depth+1);
+       }
+}
+
+static void do_write_tests(confdb_handle_t handle)
+{
+       int res;
+       unsigned int object_handle;
+
+       /* Add a scratch object and put some keys into it */
+       res = confdb_object_create(handle, OBJECT_PARENT_HANDLE, (void *)"testconfdb", strlen("testconfdb"), &object_handle);
+       if (res != SA_AIS_OK) {
+               printf( "error creating 'testconfdb' object: %d\n", res);
+               return;
+       }
+
+       res = confdb_key_create(handle, object_handle, "testkey", strlen("testkey"), "one", strlen("one"));
+       if (res != SA_AIS_OK) {
+               printf( "error creating 'testconfdb' key 1: %d\n", res);
+               return;
+       }
+
+       res = confdb_key_create(handle, object_handle, "testkey", strlen("testkey"), "two", strlen("two"));
+       if (res != SA_AIS_OK) {
+               printf( "error creating 'testconfdb' key 2: %d\n", res);
+               return;
+       }
+
+       res = confdb_key_create(handle, object_handle, "grot", strlen("grot"), "perrins", strlen("perrins"));
+       if (res != SA_AIS_OK) {
+               printf( "error creating 'testconfdb' key 3: %d\n", res);
+               return;
+       }
+
+       res = confdb_key_replace(handle, object_handle, "testkey", strlen("testkey"), "two", strlen("two"),
+                                "newtwo", strlen("newtwo"));
+
+       if (res != SA_AIS_OK) {
+               printf( "error replace 'testconfdb' key 2: %d\n", res);
+               return;
+       }
+
+       /* Print it for verification */
+       print_config_tree(handle, object_handle, 0);
+       printf("-------------------------\n");
+
+       /* Remove it.
+          Check that it doesn't exist when the full tree dump runs next */
+       res = confdb_object_destroy(handle, object_handle);
+       if (res != SA_AIS_OK) {
+               printf( "error destroying 'testconfdb' object: %d\n", res);
+               return;
+       }
+}
+
+
+int main (int argc, char *argv[]) {
+       confdb_handle_t handle;
+       int result;
+       unsigned int totem_handle;
+       char key_value[256];
+       int value_len;
+
+       result = confdb_initialize (&handle, &callbacks);
+       if (result != SA_AIS_OK) {
+               printf ("Could not initialize Cluster Configuration Database API instance error %d\n", result);
+               exit (1);
+       }
+
+       if (argv[1] && strcmp(argv[1], "write")==0)
+               do_write_tests(handle);
+
+       /* Test iterators */
+       print_config_tree(handle, OBJECT_PARENT_HANDLE, 0);
+
+       /* Find "totem" and dump bits of it again, to test the direct APIs */
+       result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
+       if (result != SA_AIS_OK) {
+               printf ("Could not start object_find %d\n", result);
+               exit (1);
+       }
+
+       result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, "totem", strlen("totem"), &totem_handle);
+       if (result != SA_AIS_OK) {
+               printf ("Could not object_find \"totem\": %d\n", result);
+               exit (1);
+       }
+
+       result = confdb_key_get(handle, totem_handle, "version", strlen("version"), key_value, &value_len);
+       if (result != SA_AIS_OK) {
+               printf ("Could not get \"version\" key: %d\n", result);
+               exit (1);
+       }
+       key_value[value_len] = '\0';
+       printf("totem/version = '%s'\n", key_value);
+
+       result = confdb_key_get(handle, totem_handle, "secauth", strlen("secauth"), key_value, &value_len);
+       if (result != SA_AIS_OK) {
+               printf ("Could not get \"secauth\" key: %d\n", result);
+               exit (1);
+       }
+       key_value[value_len] = '\0';
+       printf("totem/secauth = '%s'\n", key_value);
+
+       /* Try a call that fails */
+       result = confdb_key_get(handle, totem_handle, "grot", strlen("grot"), key_value, &value_len);
+       printf ("Get \"grot\" key returned: %d (should fail)\n", result);
+
+       result = confdb_finalize (handle);
+       printf ("Finalize  result is %d (should be 1)\n", result);
+       return (0);
+}