Kaynağa Gözat

Add confdb, a library to access the configuration object database.

git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1516 fd59a12c-fef9-0310-b244-a6a79926bd2f
Patrick Caulfield 18 yıl önce
ebeveyn
işleme
9ab240e478
14 değiştirilmiş dosya ile 2335 ekleme ve 13 silme
  1. 2 2
      Makefile
  2. 13 3
      exec/Makefile
  3. 467 0
      exec/confdb.c
  4. 160 3
      exec/objdb.c
  5. 23 0
      exec/objdb.h
  6. 4 0
      exec/service.c
  7. 229 0
      include/confdb.h
  8. 180 0
      include/ipc_confdb.h
  9. 2 1
      include/ipc_gen.h
  10. 12 1
      lib/Makefile
  11. 985 0
      lib/confdb.c
  12. 38 0
      lib/libconfdb.versions
  13. 6 3
      test/Makefile
  14. 214 0
      test/testconfdb.c

+ 2 - 2
Makefile

@@ -125,11 +125,11 @@ clean:
 	rm -rf $(builddir)doc/api
 	rm -rf $(builddir)doc/api
 
 
 AIS_LIBS	= ais SaAmf SaClm SaCkpt SaEvt SaLck SaMsg evs cpg \
 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 \
 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 	   \
 		  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
 EXEC_LIBS	= totem_pg logsys
 
 

+ 13 - 3
exec/Makefile

@@ -1,6 +1,6 @@
 # Copyright (c) 2002-2006 MontaVista Software, Inc.
 # Copyright (c) 2002-2006 MontaVista Software, Inc.
 # Copyright (c) 2006 Sun Microsystems, Inc.
 # Copyright (c) 2006 Sun Microsystems, Inc.
-# Copyright (c) 2006-2007 Red Hat, Inc.
+# Copyright (c) 2006-2008 Red Hat, Inc.
 # 
 # 
 # All rights reserved.
 # 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
 AMF_OBJS = amf.o amfutil.o amfnode.o amfcluster.o amfapp.o amfsg.o amfsu.o amfcomp.o amfsi.o
 
 
 # LCR objects
 # 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 executive objects
 MAIN_SRC = main.c mempool.c util.c sync.c service.c ipc.c flow.c timer.c \
 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_evs.lcrso service_clm.lcrso service_amf.lcrso \
 	service_ckpt.lcrso service_evt.lcrso service_lck.lcrso \
 	service_ckpt.lcrso service_evt.lcrso service_lck.lcrso \
 	service_msg.lcrso service_cfg.lcrso service_cpg.lcrso \
 	service_msg.lcrso service_cfg.lcrso service_cpg.lcrso \
+	service_confdb.lcrso \
 	objdb.lcrso aisparser.lcrso vsf_ykd.lcrso keygen openais-instantiate
 	objdb.lcrso aisparser.lcrso vsf_ykd.lcrso keygen openais-instantiate
 else
 else
 EXEC_OBJS = $(MAIN_OBJS) $(LCR_OBJS)
 EXEC_OBJS = $(MAIN_OBJS) $(LCR_OBJS)
@@ -114,6 +115,9 @@ service_msg.lcrso: msg.o
 service_cfg.lcrso: cfg.o
 service_cfg.lcrso: cfg.o
 	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ./aisexec -bind_at_load cfg.o -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
 service_cpg.lcrso: cpg.o
 	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ./aisexec -bind_at_load cpg.o -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
 service_cfg.lcrso: cfg.o
 	$(CC) -shared -Wl,-soname,service_cfg.lcrso cfg.o -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
 service_cpg.lcrso: cpg.o
 	$(CC) -shared -Wl,-soname,service_cpg.lcrso cpg.o -o $@
 	$(CC) -shared -Wl,-soname,service_cpg.lcrso cpg.o -o $@
 
 
@@ -234,6 +241,9 @@ msg.o: msg.c
 cfg.o: cfg.c
 cfg.o: cfg.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
 
+confdb.o: confdb.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
 aisparser.o: aisparser.c
 aisparser.o: aisparser.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
 

+ 467 - 0
exec/confdb.c

@@ -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));
+}
+

+ 160 - 3
exec/objdb.c

@@ -1,12 +1,13 @@
 /*
 /*
  * Copyright (c) 2006 MontaVista Software, Inc.
  * Copyright (c) 2006 MontaVista Software, Inc.
+ * Copyright (c) 2008 Red Hat, Inc.
  *
  *
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Author: Steven Dake (sdake@mvista.com)
  * Author: Steven Dake (sdake@mvista.com)
  *
  *
  * This software licensed under BSD license, the text of which follows:
  * This software licensed under BSD license, the text of which follows:
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  * modification, are permitted provided that the following conditions are met:
  *
  *
@@ -503,7 +504,7 @@ static int object_key_get (
 	void **value,
 	void **value,
 	int *value_len)
 	int *value_len)
 {
 {
-	unsigned int res;
+	unsigned int res = 0;
 	struct object_instance *instance;
 	struct object_instance *instance;
 	struct object_key *object_key = NULL;
 	struct object_key *object_key = NULL;
 	struct list_head *list;
 	struct list_head *list;
@@ -531,9 +532,12 @@ static int object_key_get (
 			*value_len = object_key->value_len;
 			*value_len = object_key->value_len;
 		}
 		}
 	}
 	}
+	else {
+		res = -1;
+	}
 
 
 	hdb_handle_put (&object_instance_database, object_handle);
 	hdb_handle_put (&object_instance_database, object_handle);
-	return (0);
+	return (res);
 
 
 error_exit:
 error_exit:
 	return (-1);
 	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,
 static int object_parent_get(unsigned int object_handle,
 			     unsigned int *parent_handle)
 			     unsigned int *parent_handle)
 {
 {
@@ -942,11 +1096,14 @@ struct objdb_iface_ver0 objdb_iface = {
 	.object_key_valid_set	= object_key_valid_set,
 	.object_key_valid_set	= object_key_valid_set,
 	.object_find_reset	= object_find_reset,
 	.object_find_reset	= object_find_reset,
 	.object_find		= object_find,
 	.object_find		= object_find,
+	.object_find_from	= object_find_from,
 	.object_key_get		= object_key_get,
 	.object_key_get		= object_key_get,
 	.object_key_iter	= object_key_iter,
 	.object_key_iter	= object_key_iter,
 	.object_key_iter_reset	= object_key_iter_reset,
 	.object_key_iter_reset	= object_key_iter_reset,
+	.object_key_iter_from	= object_key_iter_from,
 	.object_iter	        = object_iter,
 	.object_iter	        = object_iter,
 	.object_iter_reset	= object_iter_reset,
 	.object_iter_reset	= object_iter_reset,
+	.object_iter_from	= object_iter_from,
 	.object_priv_get	= object_priv_get,
 	.object_priv_get	= object_priv_get,
 	.object_parent_get	= object_parent_get,
 	.object_parent_get	= object_parent_get,
 	.object_dump	        = object_dump
 	.object_dump	        = object_dump

+ 23 - 0
exec/objdb.h

@@ -145,6 +145,29 @@ struct objdb_iface_ver0 {
 	int (*object_dump) (
 	int (*object_dump) (
 		unsigned int object_handle,
 		unsigned int object_handle,
 		FILE *file);
 		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 */
 #endif /* OBJDB_H_DEFINED */

+ 4 - 0
exec/service.c

@@ -90,6 +90,10 @@ static struct default_service default_services[] = {
 	{
 	{
 		.name			 = "openais_cpg",
 		.name			 = "openais_cpg",
 		.ver			 = 0,
 		.ver			 = 0,
+	},
+	{
+		.name			 = "openais_confdb",
+		.ver			 = 0,
 	}
 	}
 };
 };
 
 

+ 229 - 0
include/confdb.h

@@ -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 */

+ 180 - 0
include/ipc_confdb.h

@@ -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 */

+ 2 - 1
include/ipc_gen.h

@@ -45,7 +45,8 @@ enum service_types {
 	LCK_SERVICE = 5,
 	LCK_SERVICE = 5,
 	MSG_SERVICE = 6,
 	MSG_SERVICE = 6,
 	CFG_SERVICE = 7,
 	CFG_SERVICE = 7,
-	CPG_SERVICE = 8
+	CPG_SERVICE = 8,
+	CONFDB_SERVICE = 10
 };
 };
 
 
 enum req_init_types {
 enum req_init_types {

+ 12 - 1
lib/Makefile

@@ -42,6 +42,7 @@ all:libSaClm.a libSaClm.so.2.0.0 \
 	libSaLck.a libSaLck.so.2.0.0 \
 	libSaLck.a libSaLck.so.2.0.0 \
 	libSaMsg.a libSaMsg.so.2.0.0 \
 	libSaMsg.a libSaMsg.so.2.0.0 \
 	libcpg.a libcpg.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 \
 	libais.a libais.so.2.0.0 \
 	libevs.a libevs.so.2.0.0 \
 	libevs.a libevs.so.2.0.0 \
 	libcfg.a libcfg.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
 libcpg.so.2.0.0: util.o cpg.o
 	$(CC) -bundle -bind_at_load util.o cpg.o -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
 libcfg.so.2.0.0: util.o cfg.o
 	$(CC) -bundle -bind_at_load util.o cfg.o -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
 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 $@
 	$(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
 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 $@
 	$(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
 libcpg.a: util.o cpg.o
 	$(AR) -rc 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
 libcfg.a: util.o cfg.o
 	$(AR) -rc 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 \
 	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 \
 		libSaCkpt.so* libSaCkpt.a* libSaEvt.so* libSaEvt.a libSaLck.so* libSaLck.a \
 		libSaMsg.so* libSaMsg.a libcfg.so* libOpenaisCfg.a libaisutil.so* libaisutil.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
 # -fPIC rules required for all libraries
 %.o: %.c
 %.o: %.c

+ 985 - 0
lib/confdb.c

@@ -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);
+}

+ 38 - 0
lib/libconfdb.versions

@@ -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;
+};

+ 6 - 3
test/Makefile

@@ -1,5 +1,5 @@
 # Copyright (c) 2002-2004 MontaVista Software, Inc.
 # 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.
 # Copyright (c) 2006 Sun Microsystems, Inc.
 # 
 # 
 # All rights reserved.
 # All rights reserved.
@@ -38,13 +38,13 @@ ifeq (${OPENAIS_COMPAT}, SOLARIS)
 	override LDFLAGS += -lnsl -lsocket -lrt
 	override LDFLAGS += -lnsl -lsocket -lrt
 endif
 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) 
 LIBS = $(LIBRARIES) 
 BINARIES=testclm testamf1 \
 BINARIES=testclm testamf1 \
 	testckpt ckptstress ckptbench \
 	testckpt ckptstress ckptbench \
 	ckptbenchth ckpt-rd ckpt-wr testevt testevs \
 	ckptbenchth ckpt-rd ckpt-wr testevt testevs \
 	evsbench subscription publish evtbench unlink testclm2 testlck \
 	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
 	logsys_s logsys_t1 logsys_t2
 
 
 override CFLAGS += -I../include
 override CFLAGS += -I../include
@@ -154,6 +154,9 @@ testcpg2: testcpg2.o $(LIBRARIES)
 cpgbench: cpgbench.o $(LIBRARIES)
 cpgbench: cpgbench.o $(LIBRARIES)
 	$(CC) $(LDFLAGS) -o cpgbench cpgbench.o $(LIBS)
 	$(CC) $(LDFLAGS) -o cpgbench cpgbench.o $(LIBS)
 
 
+testconfdb: testconfdb.o $(LIBRARIES)
+	$(CC) $(LDFLAGS) -o testconfdb testconfdb.o $(LIBS)
+
 openais-cfgtool: openais-cfgtool.o $(LIBRARIES)
 openais-cfgtool: openais-cfgtool.o $(LIBRARIES)
 	$(CC) $(LDFLAGS) -o openais-cfgtool openais-cfgtool.o $(LIBS)
 	$(CC) $(LDFLAGS) -o openais-cfgtool openais-cfgtool.o $(LIBS)
 
 

+ 214 - 0
test/testconfdb.c

@@ -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);
+}