honzaf / rpms / corosync

Forked from rpms/corosync 4 years ago
Clone
Blob Blame History Raw
diff -Naurd corosync-0.92/exec/apidef.c corosync-trunk/exec/apidef.c
--- corosync-0.92/exec/apidef.c	2008-09-17 21:15:00.000000000 +0200
+++ corosync-trunk/exec/apidef.c	2008-12-08 16:55:41.000000000 +0100
@@ -46,6 +46,7 @@
 #include "main.h"
 #include "ipc.h"
 #include "sync.h"
+#include "quorum.h"
 #include <corosync/engine/coroapi.h>
 #include "service.h"
 #include <corosync/lcr/lcr_ifact.h>
@@ -55,11 +56,16 @@
 /*
  * Remove compile warnings about type name changes
  */
-typedef int (*typedef_tpg_join) (corosync_tpg_handle, struct corosync_tpg_group *, int);
-typedef int (*typedef_tpg_leave) (corosync_tpg_handle, struct corosync_tpg_group *, int);
-typedef int (*typedef_tpg_groups_mcast) (corosync_tpg_handle, int, struct corosync_tpg_group *, int groups_cnt, struct iovec *, int);
-typedef int (*typedef_tpg_groups_send_ok) (corosync_tpg_handle, struct corosync_tpg_group *, int groups_cnt, struct iovec *, int);
+typedef int (*typedef_tpg_join) (cs_tpg_handle, struct corosync_tpg_group *, int);
+typedef int (*typedef_tpg_leave) (cs_tpg_handle, struct corosync_tpg_group *, int);
+typedef int (*typedef_tpg_groups_mcast) (cs_tpg_handle, int, struct corosync_tpg_group *, int groups_cnt, struct iovec *, int);
+typedef int (*typedef_tpg_groups_send_ok) (cs_tpg_handle, struct corosync_tpg_group *, int groups_cnt, struct iovec *, int);
 
+static inline void _corosync_public_exit_error (
+	cs_fatal_error_t err, const char *file, unsigned int line)
+{
+	_corosync_exit_error (err, file, line);
+}
 
 static struct corosync_api_v1 apidef_corosync_api_v1 = {
 	.timer_add_duration = corosync_timer_add_duration,
@@ -68,16 +74,16 @@
 	.timer_time_get = NULL,
 	.ipc_source_set = message_source_set,
 	.ipc_source_is_local = message_source_is_local,
-	.ipc_private_data_get = corosync_conn_private_data_get,
+	.ipc_private_data_get = cs_conn_private_data_get,
 	.ipc_response_send = NULL,
-	.ipc_response_no_fcc = corosync_conn_send_response_no_fcc,
+	.ipc_response_no_fcc = cs_conn_send_response_no_fcc,
 	.ipc_dispatch_send = NULL,
-	.ipc_conn_send_response = corosync_conn_send_response,
-	.ipc_conn_partner_get = corosync_conn_partner_get,
-	.ipc_refcnt_inc =  corosync_ipc_flow_control_local_increment,
-	.ipc_refcnt_dec = corosync_ipc_flow_control_local_decrement,
-	.ipc_fc_create = corosync_ipc_flow_control_create,
-	.ipc_fc_destroy = corosync_ipc_flow_control_destroy,
+	.ipc_conn_send_response = cs_conn_send_response,
+	.ipc_conn_partner_get = cs_conn_partner_get,
+	.ipc_refcnt_inc =  cs_ipc_flow_control_local_increment,
+	.ipc_refcnt_dec = cs_ipc_flow_control_local_decrement,
+	.ipc_fc_create = cs_ipc_flow_control_create,
+	.ipc_fc_destroy = cs_ipc_flow_control_destroy,
 	.totem_nodeid_get = totempg_my_nodeid_get,
 	.totem_family_get = totempg_my_family_get,
 	.totem_ring_reenable = totempg_ring_reenable,
@@ -86,6 +92,7 @@
 	.totem_ifaces_get = totempg_ifaces_get,
 	.totem_ifaces_print = totempg_ifaces_print,
 	.totem_ip_print = totemip_print,
+	.totem_callback_token_create = totempg_callback_token_create,
 	.tpg_init = totempg_groups_initialize,
 	.tpg_exit = NULL, /* missing from totempg api */
 	.tpg_join = (typedef_tpg_join)totempg_groups_join,
@@ -95,12 +102,16 @@
 	.tpg_groups_mcast = (typedef_tpg_groups_mcast)totempg_groups_mcast_groups,
 	.tpg_groups_send_ok = (typedef_tpg_groups_send_ok)totempg_groups_send_ok_groups,
 	.sync_request = sync_request,
+	.quorum_is_quorate = corosync_quorum_is_quorate,
+	.quorum_register_callback = corosync_quorum_register_callback,
+	.quorum_unregister_callback = corosync_quorum_unregister_callback,
+	.quorum_initialize = corosync_quorum_initialize,
 	.service_link_and_init = corosync_service_link_and_init,
 	.service_unlink_and_exit = corosync_service_unlink_and_exit,
 	.plugin_interface_reference = lcr_ifact_reference,
 	.plugin_interface_release = lcr_ifact_release,
 	.error_memory_failure = _corosync_out_of_memory_error,
-	.fatal_error = _corosync_exit_error
+	.fatal_error = _corosync_public_exit_error
 };
 
 void apidef_init (struct objdb_iface_ver0 *objdb) {
diff -Naurd corosync-0.92/exec/coropoll.c corosync-trunk/exec/coropoll.c
--- corosync-0.92/exec/coropoll.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/coropoll.c	2009-01-20 18:59:10.000000000 +0100
@@ -59,6 +59,7 @@
 	struct timerlist timerlist;
 	void (*serialize_lock_fn) (void);
 	void (*serialize_unlock_fn) (void);
+	int stop_requested;
 };
 
 /*
@@ -92,6 +93,7 @@
 	poll_instance->poll_entries = 0;
 	poll_instance->ufds = 0;
 	poll_instance->poll_entry_count = 0;
+	poll_instance->stop_requested = 0;
 	poll_instance->serialize_lock_fn = serialize_lock_fn;
 	poll_instance->serialize_unlock_fn = serialize_unlock_fn;
 	timerlist_init (&poll_instance->timerlist);
@@ -291,18 +293,18 @@
 	struct poll_instance *poll_instance;
 	int res = 0;
 
+	if (timer_handle_out == NULL) {
+		res -ENOENT;
+		goto error_exit;
+	}
+
 	res = hdb_handle_get (&poll_instance_database, handle,
 		(void *)&poll_instance);
 	if (res != 0) {
 		res = -ENOENT;
-		
 		goto error_exit;
 	}
 
-	if (timer_handle_out == 0) {
-		res = -ENOENT;
-	}
-
 	timerlist_add_duration (&poll_instance->timerlist,
 		timer_fn, data, ((unsigned long long)msec_duration) * 1000000ULL, timer_handle_out);
 
@@ -336,6 +338,27 @@
 	return (res);
 }
 
+int poll_stop (
+	poll_handle handle)
+{
+	struct poll_instance *poll_instance;
+	unsigned int res;
+
+	res = hdb_handle_get (&poll_instance_database, handle,
+		(void *)&poll_instance);
+	if (res != 0) {
+		res = -ENOENT;
+		goto error_exit;
+	}
+	
+	poll_instance->stop_requested = 1;
+
+	hdb_handle_put (&poll_instance_database, handle);
+error_exit:
+	return (res);
+}
+
+
 int poll_run (
 	poll_handle handle)
 {
@@ -366,6 +389,10 @@
 retry_poll:
 		res = poll (poll_instance->ufds,
 			poll_instance->poll_entry_count, expire_timeout_msec);
+		if (poll_instance->stop_requested) {
+			printf ("poll should stop\n");
+			return (0);
+		}
 		if (errno == EINTR && res == -1) {
 			goto retry_poll;
 		} else
@@ -403,9 +430,6 @@
 	return (-1);
 }
 
-int poll_stop (
-	poll_handle handle);
-
 #ifdef COMPILE_OUT
 void poll_print_state (
 	poll_handle handle,
diff -Naurd corosync-0.92/exec/crypto.c corosync-trunk/exec/crypto.c
--- corosync-0.92/exec/crypto.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/exec/crypto.c	2009-01-26 21:22:28.000000000 +0100
@@ -20,13 +20,14 @@
 #endif
 #include <fcntl.h>
 #include <unistd.h>
+#include <stdint.h>
 
 #include "crypto.h"
 
 #define CONST64(n) n ## ULL
 
-typedef unsigned long ulong32;
-typedef unsigned long long ulong64;
+typedef uint32_t ulong32;
+typedef uint64_t ulong64;
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define ENDIAN_LITTLE
@@ -41,10 +42,10 @@
 #endif
 
 #if defined(COROSYNC_LINUX)
-#if __WORDIZE == 64
+#if __WORDSIZE == 64
 #define ENDIAN_64BITWORD
 #endif
-#if __WORDIZE == 32
+#if __WORDSIZE == 32
 #define ENDIAN_32BITWORD
 #endif
 #else
@@ -844,7 +845,7 @@
        assert ((len & 3) == 0);
     
        for (i = 0; i < len; i += 4) {
-           k = BYTE2WORD((unsigned char *)&buf[i]);
+           k = BYTE2WORD((unsigned char*)&buf[i]);
           ADDKEY(k);
           cycle(c->R);
           XORNL(nltap(c));
@@ -1250,11 +1251,11 @@
                              void (*callback)(void))
 {
 	int fd;
-	int rb;
+	unsigned long rb;
 
 	fd = open ("/dev/urandom", O_RDONLY);
 	
-	rb = read (fd, buf, len);
+	rb = (unsigned long)read (fd, buf, len);
 
 	close (fd);
 
diff -Naurd corosync-0.92/exec/crypto.h corosync-trunk/exec/crypto.h
--- corosync-0.92/exec/crypto.h	2004-09-15 22:20:07.000000000 +0200
+++ corosync-trunk/exec/crypto.h	2009-01-26 21:22:28.000000000 +0100
@@ -1,6 +1,8 @@
 #ifndef CRYPTO_H_DEFINED
 #define CRYPTO_H_DEFINED
 
+#include <stdint.h>
+
 #define DIGEST_SHA1     0
 #define PRNG_SOBER      0
 
@@ -88,7 +90,7 @@
                        unsigned char *dst, unsigned long *dstlen);
 
 struct sober128_prng {
-    unsigned long      R[17],          /* Working storage for the shift register */
+    uint32_t      R[17],          /* Working storage for the shift register */
                  initR[17],      /* saved register contents */ 
                  konst,          /* key dependent constant */
                  sbuf;           /* partial word encryption buffer */
diff -Naurd corosync-0.92/exec/flow.c corosync-trunk/exec/flow.c
--- corosync-0.92/exec/flow.c	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/exec/flow.c	2008-11-06 22:49:07.000000000 +0100
@@ -34,9 +34,9 @@
 
 /*
  * New messages are allowed from the library ONLY when the processor has not
- * received a COROSYNC_FLOW_CONTROL_STATE_ENABLED from any processor.  If a
- * COROSYNC_FLOW_CONTROL_STATE_ENABLED message is sent, it must later be
- *  cancelled by a COROSYNC_FLOW_CONTROL_STATE_DISABLED message.  A configuration
+ * received a CS_FLOW_CONTROL_STATE_ENABLED from any processor.  If a
+ * CS_FLOW_CONTROL_STATE_ENABLED message is sent, it must later be
+ *  cancelled by a CS_FLOW_CONTROL_STATE_DISABLED message.  A configuration
  * change with the flow controlled processor leaving the configuration will
  * also cancel flow control.
  */
@@ -68,12 +68,12 @@
 	unsigned int service __attribute__((aligned(8)));
 	char id[1024] __attribute__((aligned(8)));
 	unsigned int id_len __attribute__((aligned(8)));
-	enum corosync_flow_control_state flow_control_state __attribute__((aligned(8)));
+	enum cs_flow_control_state flow_control_state __attribute__((aligned(8)));
 };
 
 struct flow_control_node_state {
 	unsigned int nodeid;
-	enum corosync_flow_control_state flow_control_state;
+	enum cs_flow_control_state flow_control_state;
 };
 
 struct flow_control_service {
@@ -81,10 +81,10 @@
 	unsigned int service;
 	char id[1024];
 	unsigned int id_len;
-	void (*flow_control_state_set_fn) (void *context, enum corosync_flow_control_state flow_control_state);
+	void (*flow_control_state_set_fn) (void *context, enum cs_flow_control_state flow_control_state);
 	void *context;
 	unsigned int processor_count;
-	enum corosync_flow_control_state flow_control_state;
+	enum cs_flow_control_state flow_control_state;
 	struct list_head list;
 	struct list_head list_all;
 };
@@ -108,7 +108,7 @@
 
 static inline int flow_control_xmit (
 	struct flow_control_service *flow_control_service,
-	enum corosync_flow_control_state flow_control_state)
+	enum cs_flow_control_state flow_control_state)
 {
 	struct flow_control_message flow_control_message;
 	struct iovec iovec;
@@ -165,11 +165,11 @@
 		 * Determine if any flow control is enabled on any nodes and set
 		 * the internal variable appropriately
 		 */
-		flow_control_service->flow_control_state = COROSYNC_FLOW_CONTROL_STATE_DISABLED;
+		flow_control_service->flow_control_state = CS_FLOW_CONTROL_STATE_DISABLED;
 		flow_control_service->flow_control_state_set_fn (flow_control_service->context, flow_control_service->flow_control_state);
 		for (i = 0; i < flow_control_service->processor_count; i++) {
-			if (flow_control_service->flow_control_node_state[i].flow_control_state == COROSYNC_FLOW_CONTROL_STATE_ENABLED) {
-				flow_control_service->flow_control_state = COROSYNC_FLOW_CONTROL_STATE_ENABLED;
+			if (flow_control_service->flow_control_node_state[i].flow_control_state == CS_FLOW_CONTROL_STATE_ENABLED) {
+				flow_control_service->flow_control_state = CS_FLOW_CONTROL_STATE_ENABLED;
 				flow_control_service->flow_control_state_set_fn (flow_control_service->context, flow_control_service->flow_control_state);
 			}
 		}
@@ -204,7 +204,7 @@
 		 */
 		for (i = 0; i < member_list_entries; i++) {
 			flow_control_node_state_temp[i].nodeid = member_list[i];
-			flow_control_node_state_temp[i].flow_control_state = COROSYNC_FLOW_CONTROL_STATE_DISABLED;
+			flow_control_node_state_temp[i].flow_control_state = CS_FLOW_CONTROL_STATE_DISABLED;
 
 			/*
 			 * Determine if previous state was set for this processor
@@ -231,10 +231,10 @@
 		 * Turn on all flow control after a configuration change
 		 */
 		flow_control_service->processor_count = flow_control_member_list_entries;
-		flow_control_service->flow_control_state = COROSYNC_FLOW_CONTROL_STATE_DISABLED;
+		flow_control_service->flow_control_state = CS_FLOW_CONTROL_STATE_DISABLED;
 		for (i = 0; i < member_list_entries; i++) {
-			if (flow_control_service->flow_control_node_state[i].flow_control_state == COROSYNC_FLOW_CONTROL_STATE_ENABLED) {
-				flow_control_service->flow_control_state = COROSYNC_FLOW_CONTROL_STATE_ENABLED;
+			if (flow_control_service->flow_control_node_state[i].flow_control_state == CS_FLOW_CONTROL_STATE_ENABLED) {
+				flow_control_service->flow_control_state = CS_FLOW_CONTROL_STATE_ENABLED;
 				flow_control_service->flow_control_state_set_fn (flow_control_service->context, flow_control_service->flow_control_state);
 			}
 		}
@@ -244,7 +244,7 @@
 /*
  * External API
  */
-unsigned int corosync_flow_control_initialize (void)
+unsigned int cs_flow_control_initialize (void)
 {
 	unsigned int res;
 
@@ -271,7 +271,7 @@
 	return (0);
 }
 
-unsigned int corosync_flow_control_ipc_init (
+unsigned int cs_flow_control_ipc_init (
 	unsigned int *flow_control_handle,
 	unsigned int service)
 {
@@ -301,19 +301,19 @@
 
 }
 
-unsigned int corosync_flow_control_ipc_exit (
+unsigned int cs_flow_control_ipc_exit (
 	unsigned int flow_control_handle)
 {
 	hdb_handle_destroy (&flow_control_hdb, flow_control_handle);
 	return (0);
 }
 
-unsigned int corosync_flow_control_create (
+unsigned int cs_flow_control_create (
 	unsigned int flow_control_handle,
 	unsigned int service,
 	void *id,
 	unsigned int id_len,
-	void (*flow_control_state_set_fn) (void *context, enum corosync_flow_control_state flow_control_state),
+	void (*flow_control_state_set_fn) (void *context, enum cs_flow_control_state flow_control_state),
 	void *context)
 {
 	struct flow_control_service *flow_control_service;
@@ -337,7 +337,7 @@
 	 */
 	memset (flow_control_service, 0, sizeof (struct flow_control_service));
 
-	flow_control_service->flow_control_state = COROSYNC_FLOW_CONTROL_STATE_DISABLED;
+	flow_control_service->flow_control_state = CS_FLOW_CONTROL_STATE_DISABLED;
 	flow_control_service->service = service;
 	memcpy (flow_control_service->id, id, id_len);
 	flow_control_service->id_len = id_len;
@@ -363,7 +363,7 @@
 	return (res);
 }
 
-unsigned int corosync_flow_control_destroy (
+unsigned int cs_flow_control_destroy (
 	unsigned int flow_control_identifier,
 	unsigned int service,
 	unsigned char *id,
@@ -389,7 +389,7 @@
 		if ((flow_control_service->id_len == id_len) &&
 			(memcmp (flow_control_service->id, id, id_len) == 0)) {
 			flow_control_xmit (flow_control_service,
-				COROSYNC_FLOW_CONTROL_STATE_DISABLED);
+				CS_FLOW_CONTROL_STATE_DISABLED);
 			list_del (&flow_control_service->list);
 			list_del (&flow_control_service->list_all);
 			free (flow_control_service);
@@ -406,7 +406,7 @@
  * Disable the ability for new messages to be sent for this service
  * with the handle id of length id_len
  */
-unsigned int corosync_flow_control_disable (
+unsigned int cs_flow_control_disable (
 	unsigned int flow_control_handle)
 {
 	struct flow_control_instance *instance;
@@ -425,8 +425,8 @@
 		list = list->next) {
 
 		flow_control_service = list_entry (list, struct flow_control_service, list);
-		flow_control_service->flow_control_state = COROSYNC_FLOW_CONTROL_STATE_DISABLED;
-		flow_control_xmit (flow_control_service, COROSYNC_FLOW_CONTROL_STATE_DISABLED);
+		flow_control_service->flow_control_state = CS_FLOW_CONTROL_STATE_DISABLED;
+		flow_control_xmit (flow_control_service, CS_FLOW_CONTROL_STATE_DISABLED);
 	}
 	hdb_handle_put (&flow_control_hdb, flow_control_handle);
 
@@ -438,7 +438,7 @@
  * Enable the ability for new messagess to be sent for this service
  * with the handle id of length id_len
  */
-unsigned int corosync_flow_control_enable (
+unsigned int cs_flow_control_enable (
 	unsigned int flow_control_handle)
 {
 	struct flow_control_instance *instance;
@@ -458,8 +458,8 @@
 
 
 		flow_control_service = list_entry (list, struct flow_control_service, list);
-		flow_control_service->flow_control_state = COROSYNC_FLOW_CONTROL_STATE_ENABLED;
-		flow_control_xmit (flow_control_service, COROSYNC_FLOW_CONTROL_STATE_ENABLED);
+		flow_control_service->flow_control_state = CS_FLOW_CONTROL_STATE_ENABLED;
+		flow_control_xmit (flow_control_service, CS_FLOW_CONTROL_STATE_ENABLED);
 	}
 	hdb_handle_put (&flow_control_hdb, flow_control_handle);
 
diff -Naurd corosync-0.92/exec/flow.h corosync-trunk/exec/flow.h
--- corosync-0.92/exec/flow.h	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/exec/flow.h	2008-11-06 22:49:07.000000000 +0100
@@ -37,38 +37,38 @@
 #define FLOW_H_DEFINED
 
 #define COROSYNC_FLOW_CONTROL_STATE
-enum corosync_flow_control_state {
-	COROSYNC_FLOW_CONTROL_STATE_DISABLED,
-	COROSYNC_FLOW_CONTROL_STATE_ENABLED
+enum cs_flow_control_state {
+	CS_FLOW_CONTROL_STATE_DISABLED,
+	CS_FLOW_CONTROL_STATE_ENABLED
 };
 
-unsigned int corosync_flow_control_initialize (void);
+unsigned int cs_flow_control_initialize (void);
 
-unsigned int corosync_flow_control_ipc_init (
+unsigned int cs_flow_control_ipc_init (
 	unsigned int *flow_control_identifier,
 	unsigned int service);
 
-unsigned int corosync_flow_control_ipc_exit (
+unsigned int cs_flow_control_ipc_exit (
 	unsigned int flow_control_identifier);
 
-unsigned int corosync_flow_control_create (
+unsigned int cs_flow_control_create (
 	unsigned int flow_control_handle,
 	unsigned int service,
 	void *id,
 	unsigned int id_len,
-	void (*flow_control_state_set_fn) (void *context, enum corosync_flow_control_state flow_control_state),
+	void (*flow_control_state_set_fn) (void *context, enum cs_flow_control_state flow_control_state),
 	void *context);
 
-unsigned int corosync_flow_control_destroy (
+unsigned int cs_flow_control_destroy (
 	unsigned int flow_control_identifier,
 	unsigned int service,
 	unsigned char *id,
 	unsigned int id_len);
 
-unsigned int corosync_flow_control_disable (
+unsigned int cs_flow_control_disable (
 	unsigned int flow_control_identifier);
 
-unsigned int corosync_flow_control_enable (
+unsigned int cs_flow_control_enable (
 	unsigned int flow_control_identifier);
 
 #endif /* FLOW_H_DEFINED */
diff -Naurd corosync-0.92/exec/ipc.c corosync-trunk/exec/ipc.c
--- corosync-0.92/exec/ipc.c	2008-09-17 21:15:00.000000000 +0200
+++ corosync-trunk/exec/ipc.c	2008-12-28 10:25:17.000000000 +0100
@@ -62,7 +62,7 @@
 #endif
 
 #include <corosync/swab.h>
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/list.h>
 #include <corosync/queue.h>
 #include <corosync/lcr/lcr_ifact.h>
@@ -72,6 +72,7 @@
 #include <corosync/engine/config.h>
 #include <corosync/engine/logsys.h>
 
+#include "quorum.h"
 #include "poll.h"
 #include "totemsrp.h"
 #include "mempool.h"
@@ -153,7 +154,7 @@
 	unsigned int flow_control_handle;	/* flow control identifier */
 	unsigned int flow_control_enabled;	/* flow control enabled bit */
 	unsigned int flow_control_local_count;	/* flow control local count */
-	enum corosync_lib_flow_control flow_control;	/* Does this service use IPC flow control */
+	enum cs_lib_flow_control flow_control;	/* Does this service use IPC flow control */
 	pthread_mutex_t flow_control_mutex;
         int (*lib_exit_fn) (void *conn);
 	struct timerlist timerlist;
@@ -193,26 +194,26 @@
 	struct conn_info *conn_info,
 	void *message)
 {
-	SaAisErrorT error = SA_AIS_ERR_ACCESS;
+	cs_error_t error = CS_ERR_ACCESS;
 	uintptr_t cinfo = (uintptr_t)conn_info;
 	mar_req_lib_response_init_t *req_lib_response_init = (mar_req_lib_response_init_t *)message;
 	mar_res_lib_response_init_t res_lib_response_init;
 
 	if (conn_info->authenticated) {
 		conn_info->service = req_lib_response_init->resdis_header.service;
-		error = SA_AIS_OK;
+		error = CS_OK;
 	}
 	res_lib_response_init.header.size = sizeof (mar_res_lib_response_init_t);
 	res_lib_response_init.header.id = MESSAGE_RES_INIT;
 	res_lib_response_init.header.error = error;
 	res_lib_response_init.conn_info = (mar_uint64_t)cinfo;
 
-	corosync_conn_send_response (
+	cs_conn_send_response (
 		conn_info,
 		&res_lib_response_init,
 		sizeof (res_lib_response_init));
 
-	if (error == SA_AIS_ERR_ACCESS) {
+	if (error == CS_ERR_ACCESS) {
 		libais_disconnect_security (conn_info);
 		return (-1);
 	}
@@ -223,7 +224,7 @@
 	struct conn_info *conn_info,
 	void *message)
 {
-	SaAisErrorT error = SA_AIS_ERR_ACCESS;
+	cs_error_t error = CS_ERR_ACCESS;
 	uintptr_t cinfo;
 	mar_req_lib_dispatch_init_t *req_lib_dispatch_init = (mar_req_lib_dispatch_init_t *)message;
 	mar_res_lib_dispatch_init_t res_lib_dispatch_init;
@@ -232,9 +233,9 @@
 	if (conn_info->authenticated) {
 		conn_info->service = req_lib_dispatch_init->resdis_header.service;
 		if (!ais_service[req_lib_dispatch_init->resdis_header.service])
-			error = SA_AIS_ERR_NOT_SUPPORTED;
+			error = CS_ERR_NOT_SUPPORTED;
 		else
-			error = SA_AIS_OK;
+			error = CS_OK;
 
 		cinfo = (uintptr_t)req_lib_dispatch_init->conn_info;
 		conn_info->conn_info_partner = (struct conn_info *)cinfo;
@@ -252,7 +253,7 @@
 		msg_conn_info = (struct conn_info *)cinfo;
 		msg_conn_info->conn_info_partner = conn_info;
 
-		if (error == SA_AIS_OK) {
+		if (error == CS_OK) {
 			int private_data_size;
 
 			private_data_size = ais_service[req_lib_dispatch_init->resdis_header.service]->private_data_size;
@@ -261,7 +262,7 @@
 
 				conn_info->conn_info_partner->private_data = conn_info->private_data;
 				if (conn_info->private_data == NULL) {
-					error = SA_AIS_ERR_NO_MEMORY;
+					error = CS_ERR_NO_MEMORY;
 				} else {
 					memset (conn_info->private_data, 0, private_data_size);
 				}
@@ -276,16 +277,16 @@
 	res_lib_dispatch_init.header.id = MESSAGE_RES_INIT;
 	res_lib_dispatch_init.header.error = error;
 
-	corosync_conn_send_response (
+	cs_conn_send_response (
 		conn_info,
 		&res_lib_dispatch_init,
 		sizeof (res_lib_dispatch_init));
 
-	if (error == SA_AIS_ERR_ACCESS) {
+	if (error == CS_ERR_ACCESS) {
 		libais_disconnect_security (conn_info);
 		return (-1);
 	}
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (-1);
 	}
 
@@ -296,8 +297,8 @@
 
 	conn_info->flow_control = ais_service[conn_info->service]->flow_control;
 	conn_info->conn_info_partner->flow_control = ais_service[conn_info->service]->flow_control;
-	if (ais_service[conn_info->service]->flow_control == COROSYNC_LIB_FLOW_CONTROL_REQUIRED) {
-		corosync_flow_control_ipc_init (
+	if (ais_service[conn_info->service]->flow_control == CS_LIB_FLOW_CONTROL_REQUIRED) {
+		cs_flow_control_ipc_init (
 			&conn_info->flow_control_handle,
 			conn_info->service);
 
@@ -448,7 +449,7 @@
 	conn_info->state = CONN_STATE_DISCONNECTED;
 	conn_info->conn_info_partner->state = CONN_STATE_DISCONNECTED;
 	if (conn_info->flow_control_enabled == 1) {
-		corosync_flow_control_disable (conn_info->flow_control_handle);
+		cs_flow_control_disable (conn_info->flow_control_handle);
 	}
 	return (0);
 }
@@ -486,6 +487,7 @@
 	struct sched_param sched_param;
 	int res;
 	pthread_mutex_t *rel_mutex;
+	pthread_mutex_t *rel2_mutex;
 	unsigned int service;
 	struct conn_info *cinfo_partner;
 	void *private_data;
@@ -523,11 +525,12 @@
 
 		case CONN_STATE_DISCONNECTED:
 			rel_mutex = conn_info->shared_mutex;
+			rel2_mutex = &conn_info->mutex;
 			private_data = conn_info->private_data;
 			cinfo_partner = conn_info->conn_info_partner;
 			conn_info_destroy (conn);
 			if (service == SOCKET_SERVICE_INIT) {
-				pthread_mutex_unlock (&conn_info->mutex);
+				pthread_mutex_unlock (rel2_mutex);
 			} else {
 				pthread_mutex_unlock (rel_mutex);
 			}
@@ -633,34 +636,37 @@
 	/*
 	 * IPC group-wide flow control
 	 */
-	if (conn_info->flow_control == COROSYNC_LIB_FLOW_CONTROL_REQUIRED) {
+	if (conn_info->flow_control == CS_LIB_FLOW_CONTROL_REQUIRED) {
 		if (conn_info->flow_control_enabled == 0 &&
 			((fcc + FLOW_CONTROL_ENTRIES_ENABLE) > SIZEQUEUE)) {
 
 			log_printf (LOG_LEVEL_NOTICE, "Enabling flow control [%d/%d] - [%d].\n",
 				entries_usedhw, SIZEQUEUE,
 				flow_control_local_count);
-			corosync_flow_control_enable (conn_info->flow_control_handle);
+			cs_flow_control_enable (conn_info->flow_control_handle);
 			conn_info->flow_control_enabled = 1;
-			conn_info->conn_info_partner->flow_control_enabled = 1;
+			if (conn_info->conn_info_partner) {
+				conn_info->conn_info_partner->flow_control_enabled = 1;
+			}
 		}
 		if (conn_info->flow_control_enabled == 1 &&
-
 			fcc <= FLOW_CONTROL_ENTRIES_DISABLE) {
 
 			log_printf (LOG_LEVEL_NOTICE, "Disabling flow control [%d/%d] - [%d].\n",
 				entries_usedhw, SIZEQUEUE,
 				flow_control_local_count);
-			corosync_flow_control_disable (conn_info->flow_control_handle);
+			cs_flow_control_disable (conn_info->flow_control_handle);
 			conn_info->flow_control_enabled = 0;
-			conn_info->conn_info_partner->flow_control_enabled = 0;
+			if (conn_info->conn_info_partner) {
+				conn_info->conn_info_partner->flow_control_enabled = 0;
+			}
 		}
 	}
 }
 
 static int conn_info_outq_flush (struct conn_info *conn_info) {
 	struct queue *outq;
-	int res = 0;
+	ssize_t res = 0;
 	struct outq_item *queue_item;
 	struct msghdr msg_send;
 	struct iovec iov_send;
@@ -731,14 +737,15 @@
 
 
 
-struct res_overlay {
+struct ipc_res_overlay {
 	mar_res_header_t header __attribute((aligned(8)));
 	char buf[4096];
 };
 
 static void libais_deliver (struct conn_info *conn_info)
 {
-	int res;
+	ssize_t res;
+	int dispatch_res;
 	mar_req_header_t *header;
 	int service;
 	struct msghdr msg_recv;
@@ -752,7 +759,7 @@
 	int send_ok = 0;
 	int send_ok_joined = 0;
 	struct iovec send_ok_joined_iovec;
-	struct res_overlay res_overlay;
+	struct ipc_res_overlay res_overlay;
 
 	msg_recv.msg_iov = &iov_recv;
 	msg_recv.msg_iovlen = 1;
@@ -841,7 +848,7 @@
 #ifdef COROSYNC_LINUX
 	if (conn_info->authenticated == 0) {
 		cmsg = CMSG_FIRSTHDR (&msg_recv);
-		assert (cmsg);
+		assert (cmsg != NULL);
 		cred = (struct ucred *)CMSG_DATA (cmsg);
 		if (cred) {
 			if (cred->uid == 0 || cred->gid == g_gid_valid) {
@@ -861,7 +868,8 @@
 	conn_info->inb_inuse += res;
 	conn_info->inb_start += res;
 
-	while (conn_info->inb_inuse >= sizeof (mar_req_header_t) && res != -1) {
+	dispatch_res = 0;
+	while (conn_info->inb_inuse >= sizeof (mar_req_header_t) && dispatch_res != -1) {
 		header = (mar_req_header_t *)&conn_info->inb[conn_info->inb_start - conn_info->inb_inuse];
 
 		if (header->size > conn_info->inb_inuse) {
@@ -874,7 +882,7 @@
 		 * else handle message using service service
 		 */
 		if (service == SOCKET_SERVICE_INIT) {
-			res = ais_init_service[header->id] (conn_info, header);
+			dispatch_res = ais_init_service[header->id] (conn_info, header);
 		} else  {
 			/*
 			 * Not an init service, but a standard service
@@ -897,11 +905,11 @@
 				&send_ok_joined_iovec, 1);
 
 			send_ok =
-				(sync_primary_designated() == 1) && (
-				(ais_service[service]->lib_engine[header->id].flow_control == COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED) ||
-				((ais_service[service]->lib_engine[header->id].flow_control == COROSYNC_LIB_FLOW_CONTROL_REQUIRED) &&
+				(corosync_quorum_is_quorate() == 1 || ais_service[service]->allow_inquorate == CS_LIB_ALLOW_INQUORATE) && (
+				(ais_service[service]->lib_engine[header->id].flow_control == CS_LIB_FLOW_CONTROL_NOT_REQUIRED) ||
+				((ais_service[service]->lib_engine[header->id].flow_control == CS_LIB_FLOW_CONTROL_REQUIRED) &&
 				(send_ok_joined) &&
-				(sync_in_process() == 0)));
+				 (sync_in_process() == 0)));
 
 			if (send_ok) {
 				ais_service[service]->lib_engine[header->id].lib_handler_fn(conn_info, header);
@@ -914,8 +922,8 @@
 					ais_service[service]->lib_engine[header->id].response_size;
 				res_overlay.header.id =
 					ais_service[service]->lib_engine[header->id].response_id;
-				res_overlay.header.error = SA_AIS_ERR_TRY_AGAIN;
-				corosync_conn_send_response (
+				res_overlay.header.error = CS_ERR_TRY_AGAIN;
+				cs_conn_send_response (
 					conn_info,
 					&res_overlay,
 					res_overlay.header.size);
@@ -1030,7 +1038,7 @@
 {
 }
 
-void corosync_ipc_init (
+void cs_ipc_init (
 	void (*serialize_lock_fn) (void),
 	void (*serialize_unlock_fn) (void),
 	unsigned int gid_valid)
@@ -1102,7 +1110,7 @@
 /*
  * Get the conn info private data
  */
-void *corosync_conn_private_data_get (void *conn)
+void *cs_conn_private_data_get (void *conn)
 {
 	struct conn_info *conn_info = (struct conn_info *)conn;
 
@@ -1116,7 +1124,7 @@
 /*
  * Get the conn info partner connection
  */
-void *corosync_conn_partner_get (void *conn)
+void *cs_conn_partner_get (void *conn)
 {
 	struct conn_info *conn_info = (struct conn_info *)conn;
 
@@ -1127,25 +1135,27 @@
 	}
 }
 
-int corosync_conn_send_response_no_fcc (
+int cs_conn_send_response_no_fcc (
 	void *conn,
 	void *msg,
 	int mlen)
 {
+	int ret;
 	dont_call_flow_control = 1;
-	corosync_conn_send_response (
+	ret = cs_conn_send_response (
 		conn, msg, mlen);
 	dont_call_flow_control = 0;
+	return ret;
 }
 
-int corosync_conn_send_response (
+int cs_conn_send_response (
 	void *conn,
 	void *msg,
 	int mlen)
 {
 	struct queue *outq;
 	char *cmsg;
-	int res = 0;
+	ssize_t res = 0;
 	int queue_empty;
 	struct outq_item *queue_item;
 	struct outq_item queue_item_out;
@@ -1282,17 +1292,17 @@
 	return (0);
 }
 
-void corosync_ipc_flow_control_create (
+void cs_ipc_flow_control_create (
 	void *conn,
 	unsigned int service,
 	char *id,
 	int id_len,
-	void (*flow_control_state_set_fn) (void *conn, enum corosync_flow_control_state),
+	void (*flow_control_state_set_fn) (void *conn, enum cs_flow_control_state),
 	void *context)
 {
 	struct conn_info *conn_info = (struct conn_info *)conn;
 
-	corosync_flow_control_create (
+	cs_flow_control_create (
 		conn_info->flow_control_handle,
 		service,
 		id,
@@ -1302,7 +1312,7 @@
 	conn_info->conn_info_partner->flow_control_handle = conn_info->flow_control_handle;
 }
 
-void corosync_ipc_flow_control_destroy (
+void cs_ipc_flow_control_destroy (
 	void *conn,
 	unsigned int service,
 	unsigned char *id,
@@ -1310,14 +1320,14 @@
 {
 	struct conn_info *conn_info = (struct conn_info *)conn;
 
-	corosync_flow_control_destroy (
+	cs_flow_control_destroy (
 		conn_info->flow_control_handle,
 		service,
 		id,
 		id_len);
 }
 
-void corosync_ipc_flow_control_local_increment (
+void cs_ipc_flow_control_local_increment (
         void *conn)
 {
 	struct conn_info *conn_info = (struct conn_info *)conn;
@@ -1329,7 +1339,7 @@
 	pthread_mutex_unlock (&conn_info->flow_control_mutex);
 }
 
-void corosync_ipc_flow_control_local_decrement (
+void cs_ipc_flow_control_local_decrement (
         void *conn)
 {
 	struct conn_info *conn_info = (struct conn_info *)conn;
diff -Naurd corosync-0.92/exec/ipc.h corosync-trunk/exec/ipc.h
--- corosync-0.92/exec/ipc.h	2008-09-17 21:15:00.000000000 +0200
+++ corosync-trunk/exec/ipc.h	2008-11-06 22:49:07.000000000 +0100
@@ -46,52 +46,52 @@
 
 extern int message_source_is_local (mar_message_source_t *source);
 
-extern void *corosync_conn_partner_get (void *conn);
+extern void *cs_conn_partner_get (void *conn);
 
-extern void *corosync_conn_private_data_get (void *conn);
+extern void *cs_conn_private_data_get (void *conn);
 
-extern int corosync_conn_send_response (void *conn, void *msg, int mlen);
+extern int cs_conn_send_response (void *conn, void *msg, int mlen);
 
-extern int corosync_conn_send_response_no_fcc (void *conn, void *msg,int mlen);
+extern int cs_conn_send_response_no_fcc (void *conn, void *msg,int mlen);
 
-extern void corosync_ipc_init (
+extern void cs_ipc_init (
         void (*serialize_lock_fn) (void),
         void (*serialize_unlock_fn) (void),
 	unsigned int gid_valid);
 
-extern int corosync_ipc_timer_add (
+extern int cs_ipc_timer_add (
 	void *conn,
 	void (*timer_fn) (void *data),
 	void *data,
 	unsigned int msec_in_future,
 	timer_handle *handle);
 
-extern void corosync_ipc_timer_del (
+extern void cs_ipc_timer_del (
 	void *conn,
 	timer_handle timer_handle);
 
-extern void corosync_ipc_timer_del_data (
+extern void cs_ipc_timer_del_data (
 	void *conn,
 	timer_handle timer_handle);
 
-extern void corosync_ipc_flow_control_create (
+extern void cs_ipc_flow_control_create (
 	void *conn,
 	unsigned int service,
 	char *id,
 	int id_len,
-	void (*flow_control_state_set_fn) (void *context, enum corosync_flow_control_state flow_control_state_set),
+	void (*flow_control_state_set_fn) (void *context, enum cs_flow_control_state flow_control_state_set),
 	void *context);
 	
-extern void corosync_ipc_flow_control_destroy (
+extern void cs_ipc_flow_control_destroy (
 	void *conn,
 	unsigned int service,
 	unsigned char *id,
 	int id_len);
 
-extern void corosync_ipc_flow_control_local_increment (
+extern void cs_ipc_flow_control_local_increment (
 	void *conn);
 
-extern void corosync_ipc_flow_control_local_decrement (
+extern void cs_ipc_flow_control_local_decrement (
 	void *conn);
 
 #endif /* IPC_H_DEFINED */
diff -Naurd corosync-0.92/exec/logsys.c corosync-trunk/exec/logsys.c
--- corosync-0.92/exec/logsys.c	2008-09-17 20:22:58.000000000 +0200
+++ corosync-trunk/exec/logsys.c	2009-01-26 14:15:57.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002-2004 MontaVista Software, Inc.
- * Copyright (c) 2006-2007 Red Hat, Inc.
+ * Copyright (c) 2006-2009 Red Hat, Inc.
  *
  * Author: Steven Dake (sdake@redhat.com)
  * Author: Lon Hohberger (lhh@redhat.com)
@@ -35,13 +35,17 @@
  */
 #include <assert.h>
 #include <stdio.h>
+#include <ctype.h>
 #include <string.h>
 #include <stdarg.h>
 #include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <time.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <unistd.h>
 #if defined(COROSYNC_LINUX)
 #include <linux/un.h>
 #endif
@@ -54,14 +58,54 @@
 #include <pthread.h>
 
 #include <corosync/engine/logsys.h>
-#include "wthread.h"
+
+/* similar to syslog facilities/priorities tables,
+ * make a tag table for internal use
+ */
+
+#ifdef SYSLOG_NAMES
+CODE tagnames[] =
+  {
+    { "log", LOGSYS_TAG_LOG },
+    { "enter", LOGSYS_TAG_ENTER },
+    { "leave", LOGSYS_TAG_LEAVE },
+    { "trace1", LOGSYS_TAG_TRACE1 },
+    { "trace2", LOGSYS_TAG_TRACE2 },
+    { "trace3", LOGSYS_TAG_TRACE3 },
+    { "trace4", LOGSYS_TAG_TRACE4 },
+    { "trace5", LOGSYS_TAG_TRACE5 },
+    { "trace6", LOGSYS_TAG_TRACE6 },
+    { "trace7", LOGSYS_TAG_TRACE7 },
+    { "trace8", LOGSYS_TAG_TRACE8 },
+    { NULL, -1 }
+  };
+#endif
+
+/*
+ * These are not static so they can be read from the core file
+ */
+int *flt_data;
+
+int flt_data_size;
+
+#define SUBSYS_MAX 32
+
+#define COMBINE_BUFFER_SIZE 2048
+
+struct logsys_logger {
+	char subsys[64];
+	unsigned int facility;
+	unsigned int priority;
+	unsigned int tags;
+	unsigned int mode;
+};
 
 /*
  * Configuration parameters for logging system
  */
 static char *logsys_name = NULL;
 
-static unsigned int logsys_mode = 0;
+static unsigned int logsys_mode = LOG_MODE_NOSUBSYS;
 
 static char *logsys_file = NULL;
 
@@ -69,35 +113,44 @@
 
 static int logsys_facility = LOG_DAEMON;
 
-static int logsys_wthread_active = 0;
+static char *logsys_format = NULL;
+
+/*
+ * operating global variables
+ */
+static struct logsys_logger logsys_loggers[SUBSYS_MAX];
+
+static int wthread_active = 0;
+
+static int wthread_should_exit = 0;
 
 static pthread_mutex_t logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-static pthread_mutex_t logsys_new_log_mutex = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int records_written = 1;
 
-static struct worker_thread_group log_thread_group;
+static pthread_t logsys_thread_id;
 
-static unsigned int dropped_log_entries = 0;
+static pthread_cond_t logsys_cond;
 
-#ifndef MAX_LOGGERS
-#define MAX_LOGGERS 32
-#endif
-struct logsys_logger logsys_loggers[MAX_LOGGERS];
+static pthread_mutex_t logsys_cond_mutex;
 
-int logsys_single_id = 0;
+static pthread_spinlock_t logsys_idx_spinlock;
 
+static unsigned int log_rec_idx;
 
-struct log_entry {
-	char *file;
-	int line;
-	int priority;
-	char str[128];
-	struct log_entry *next;
-};
+static int logsys_buffer_full = 0;
 
-static struct log_entry *head;
+static char *format_buffer="[%6s] %b";
 
-static struct log_entry *tail;
+static int log_requests_pending = 0;
+
+static int log_requests_lost = 0;
+
+void *logsys_rec_end;
+
+#define FDHEAD_INDEX	(flt_data_size)
+
+#define FDTAIL_INDEX 	(flt_data_size + 1)
 
 struct log_data {
 	unsigned int syslog_pos;
@@ -105,324 +158,674 @@
 	char *log_string;
 };
 
-enum logsys_config_mutex_state {
-	LOGSYS_CONFIG_MUTEX_LOCKED,
-	LOGSYS_CONFIG_MUTEX_UNLOCKED
-};
-
 static void logsys_atexit (void);
 
-#define LEVELMASK 0x07                 /* 3 bits */
-#define LOG_LEVEL(p) ((p) & LEVELMASK)
-#define LOGSYS_IDMASK (0x3f << 3)             /* 6 bits */
-#define LOG_ID(p)  (((p) & LOGSYS_IDMASK) >> 3)
-
-static void logsys_buffer_flush (void);
+/*
+ * Helpers for _logsys_log_rec functionality
+ */
+static inline void my_memcpy_32bit (int *dest, int *src, unsigned int words)
+{
+	unsigned int word_idx;
+	for (word_idx = 0; word_idx < words; word_idx++) {
+		dest[word_idx] = src[word_idx];
+	}
+}
 
-void _logsys_nosubsys_set (void)
+static inline void my_memcpy_8bit (char *dest, char *src, unsigned int bytes)
 {
-	logsys_mode |= LOG_MODE_NOSUBSYS;
+	unsigned int byte_idx;
+
+	for (byte_idx = 0; byte_idx < bytes; byte_idx++) {
+		dest[byte_idx] = src[byte_idx];
+	}
 }
 
-int logsys_facility_id_get (const char *name)
+/*
+ * Before any write operation, a reclaim on the buffer area must be executed
+ */
+static inline void records_reclaim (unsigned int idx, unsigned int words)
 {
-	unsigned int i;
+	unsigned int should_reclaim;
 
-	for (i = 0; facilitynames[i].c_name != NULL; i++) {
-		if (strcasecmp(name, facilitynames[i].c_name) == 0) {
-			return (facilitynames[i].c_val);
+	should_reclaim = 0;
+
+	if ((idx + words) >= flt_data_size) {
+		logsys_buffer_full = 1;
+	}
+	if (logsys_buffer_full == 0) {
+		return;
+	}
+
+	pthread_spin_lock (&logsys_idx_spinlock);
+	if (flt_data[FDTAIL_INDEX] > flt_data[FDHEAD_INDEX]) {
+		if (idx + words >= flt_data[FDTAIL_INDEX]) {
+			should_reclaim = 1;
+		}
+	} else {
+		if ((idx + words) >= (flt_data[FDTAIL_INDEX] + flt_data_size)) {
+			should_reclaim = 1;
 		}
 	}
-	return (-1);
+
+	if (should_reclaim) {
+		int words_needed = 0;
+
+		words_needed = words + 1;
+		do {
+			unsigned int old_tail;
+
+			words_needed -= flt_data[flt_data[FDTAIL_INDEX]];
+			old_tail = flt_data[FDTAIL_INDEX];
+			flt_data[FDTAIL_INDEX] = 
+				(flt_data[FDTAIL_INDEX] + 
+				flt_data[flt_data[FDTAIL_INDEX]]) % (flt_data_size);
+			if (log_rec_idx == old_tail) {
+				log_requests_lost += 1;
+				log_rec_idx = flt_data[FDTAIL_INDEX];
+			}
+		} while (words_needed > 0);
+	}
+	pthread_spin_unlock (&logsys_idx_spinlock);
 }
 
-const char *logsys_facility_name_get (unsigned int facility)
+#define idx_word_step(idx)						\
+do {									\
+	if (idx > (flt_data_size - 1)) {				\
+		idx = 0;						\
+	}								\
+} while (0);
+
+#define idx_buffer_step(idx)						\
+do {									\
+	if (idx > (flt_data_size - 1)) {				\
+		idx = ((idx) % (flt_data_size));			\
+	}								\
+} while (0);
+
+/*
+ * Internal threaded logging implementation
+ */
+static inline int strcpy_cutoff (char *dest, char *src, int cutoff)
 {
-	unsigned int i;
+	unsigned int len;
 
-	for (i = 0; facilitynames[i].c_name != NULL; i++) {
-		if (facility == facilitynames[i].c_val) {
-			return (facilitynames[i].c_name);
+	if (cutoff == -1) {
+		strcpy (dest, src);
+		return (strlen (dest));
+	} else {
+		assert (cutoff > 0);
+		strncpy (dest, src, cutoff);
+		dest[cutoff] = '\0';
+		len = strlen (dest);
+		if (len != cutoff) {
+			memset (&dest[len], ' ', cutoff - len);
 		}
 	}
-	return (NULL);
+	return (cutoff);
 }
 
-int logsys_priority_id_get (const char *name)
+/*
+ * %s SUBSYSTEM
+ * %n FUNCTION NAME
+ * %f FILENAME
+ * %l FILELINE
+ * %p PRIORITY
+ * %t TIMESTAMP
+ * %b BUFFER
+ * 
+ * any number between % and character specify field length to pad or chop
+*/
+static void log_printf_to_logs (
+	char *subsys,
+	char *function_name,
+	char *file_name,
+	int file_line,
+	unsigned int level,
+	char *buffer)
 {
-	unsigned int i;
+	char output_buffer[COMBINE_BUFFER_SIZE];
+	char char_time[128];
+	char line_no[30];
+	unsigned int format_buffer_idx = 0;
+	unsigned int output_buffer_idx = 0;
+	struct timeval tv;
+	int cutoff;
+	unsigned int len;
+	
+	while (format_buffer[format_buffer_idx]) {
+		cutoff = -1;
+		if (format_buffer[format_buffer_idx] == '%') {
+			format_buffer_idx += 1;
+			if (isdigit (format_buffer[format_buffer_idx])) {
+				cutoff = atoi (&format_buffer[format_buffer_idx]);
+			}
+			while (isdigit (format_buffer[format_buffer_idx])) {
+				format_buffer_idx += 1;
+			}
+			
+			switch (format_buffer[format_buffer_idx]) {
+				case 's':
+					len = strcpy_cutoff (&output_buffer[output_buffer_idx], subsys, cutoff);
+					output_buffer_idx += len;
+					break;
 
-	for (i = 0; prioritynames[i].c_name != NULL; i++) {
-		if (strcasecmp(name, prioritynames[i].c_name) == 0) {
-			return (prioritynames[i].c_val);
+				case 'n':
+					len = strcpy_cutoff (&output_buffer[output_buffer_idx], function_name, cutoff);
+					output_buffer_idx += len;
+					break;
+
+				case 'l':
+					sprintf (line_no, "%d", file_line);
+					len = strcpy_cutoff (&output_buffer[output_buffer_idx], line_no, cutoff);
+					output_buffer_idx += len;
+					break;
+
+				case 'p':
+					break;
+
+				case 't':
+					gettimeofday (&tv, NULL);
+					(void)strftime (char_time, sizeof (char_time), "%b %e %k:%M:%S", localtime ((time_t *)&tv.tv_sec));
+					len = strcpy_cutoff (&output_buffer[output_buffer_idx], char_time, cutoff);
+					output_buffer_idx += len;
+					break;
+
+				case 'b':
+					len = strcpy_cutoff (&output_buffer[output_buffer_idx], buffer, cutoff);
+					output_buffer_idx += len;
+					break;
+			}
+			format_buffer_idx += 1;
+		} else {
+			output_buffer[output_buffer_idx++] = format_buffer[format_buffer_idx++];
 		}
 	}
-	return (-1);
+
+	output_buffer[output_buffer_idx] = '\0';
+
+	/*
+	 * Output to syslog
+	 */	
+	if (logsys_mode & LOG_MODE_OUTPUT_SYSLOG) {
+		syslog (level, "%s", output_buffer);
+	}
+
+	/*
+	 * Terminate string with \n \0
+	 */
+	if (logsys_mode & (LOG_MODE_OUTPUT_FILE|LOG_MODE_OUTPUT_STDERR)) {
+		output_buffer[output_buffer_idx++] = '\n';
+		output_buffer[output_buffer_idx] = '\0';
+	}
+
+	/*
+	 * Output to configured file
+	 */	
+	if ((logsys_mode & LOG_MODE_OUTPUT_FILE) && logsys_file_fp) {
+		/*
+		 * Output to a file
+		 */
+		(void)fwrite (output_buffer, strlen (output_buffer), 1, logsys_file_fp);
+		fflush (logsys_file_fp);
+	}
+
+	/*
+	 * Output to stderr
+	 */	
+	if (logsys_mode & LOG_MODE_OUTPUT_STDERR) {
+		(void)write (STDERR_FILENO, output_buffer, strlen (output_buffer));
+	}
 }
 
-const char *logsys_priority_name_get (unsigned int priority)
+static void record_print (char *buf)
 {
+	int *buf_uint32t = (int *)buf;
+	unsigned int rec_size = buf_uint32t[0];
+	unsigned int rec_ident = buf_uint32t[1];
+	unsigned int file_line = buf_uint32t[2];
+	unsigned int level = rec_ident >> 28;
 	unsigned int i;
+	unsigned int words_processed;
+	unsigned int arg_size_idx;
+	void *arguments[64];
+	unsigned int arg_count;
 
-	for (i = 0; prioritynames[i].c_name != NULL; i++) {
-		if (priority == prioritynames[i].c_val) {
-			return (prioritynames[i].c_name);
-		}
+	arg_size_idx = 4;
+	words_processed = 4;
+	arg_count = 0;
+
+	for (i = 0; words_processed < rec_size; i++) {
+		arguments[arg_count++] = &buf_uint32t[arg_size_idx + 1];
+		arg_size_idx += buf_uint32t[arg_size_idx] + 1;
+		words_processed += buf_uint32t[arg_size_idx] + 1;
 	}
-	return (NULL);
+	log_printf_to_logs (
+		(char *)arguments[0],
+		(char *)arguments[1],
+		(char *)arguments[2],
+		file_line,
+		level,
+		(char *)arguments[3]);
 }
+	
+static int record_read (char *buf, int rec_idx, int *log_msg) {
+        unsigned int rec_size;
+        unsigned int rec_ident;
+        int firstcopy, secondcopy;
 
-unsigned int logsys_config_subsys_set (
-	const char *subsys,
-	unsigned int tags,
-	unsigned int priority)
-{
-	int i;
+	rec_size = flt_data[rec_idx];
+	rec_ident = flt_data[(rec_idx + 1) % flt_data_size];
 
-	pthread_mutex_lock (&logsys_config_mutex);
- 	for (i = 0; i < MAX_LOGGERS; i++) {
-		if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
-			logsys_loggers[i].tags = tags;
-			logsys_loggers[i].priority = priority;
+	/*
+	 * Not a log record
+	 */
+	if ((rec_ident & LOGSYS_TAG_LOG) == 0) {
+		*log_msg = 0;
+        	return ((rec_idx + rec_size) % flt_data_size);
+	}
 
-			break;
-		}
+	/*
+	 * A log record
+	 */
+	*log_msg = 1;
+
+        firstcopy = rec_size;
+        secondcopy = 0;
+        if (firstcopy + rec_idx > flt_data_size) {
+                firstcopy = flt_data_size - rec_idx;
+                secondcopy -= firstcopy - rec_size;
+        }
+        memcpy (&buf[0], &flt_data[rec_idx], firstcopy << 2);
+        if (secondcopy) {
+                memcpy (&buf[(firstcopy << 2)], &flt_data[0], secondcopy << 2);
+        }
+        return ((rec_idx + rec_size) % flt_data_size);
+}
+
+static inline void wthread_signal (void)
+{
+	if (wthread_active == 0) {
+		return;
 	}
+	pthread_mutex_lock (&logsys_cond_mutex);
+	pthread_cond_signal (&logsys_cond);
+	pthread_mutex_unlock (&logsys_cond_mutex);
+}
 
-	if (i == MAX_LOGGERS) {
-		for (i = 0; i < MAX_LOGGERS; i++) {
-			if (strcmp (logsys_loggers[i].subsys, "") == 0) {
-				strncpy (logsys_loggers[i].subsys, subsys,
-					sizeof(logsys_loggers[i].subsys));
-				logsys_loggers[i].tags = tags;
-				logsys_loggers[i].priority = priority;
+static inline void wthread_wait (void)
+{
+	pthread_mutex_lock (&logsys_cond_mutex);
+	pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
+	pthread_mutex_unlock (&logsys_cond_mutex);
+}
+
+static inline void wthread_wait_locked (void)
+{
+	pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
+	pthread_mutex_unlock (&logsys_cond_mutex);
+}
+
+static void *logsys_worker_thread (void *data)
+{
+	int log_msg;
+	char buf[COMBINE_BUFFER_SIZE];
+
+	/*
+	 * Signal wthread_create that the initialization process may continue
+	 */
+	wthread_signal ();
+	pthread_spin_lock (&logsys_idx_spinlock);
+	log_rec_idx = flt_data[FDTAIL_INDEX];
+	pthread_spin_unlock (&logsys_idx_spinlock);
+
+	for (;;) {
+		wthread_wait ();
+		/*
+		 * Read and copy the logging record index position
+		 * It may have been updated by records_reclaim if
+		 * messages were lost or or log_rec on the first new
+		 * logging record available
+		 */
+		/*
+		 * Process any pending log messages here
+		 */
+		for (;;) {
+			pthread_spin_lock (&logsys_idx_spinlock);
+			if (log_requests_lost > 0) {
+				printf ("lost %d log requests\n", log_requests_lost);
+				log_requests_pending -= log_requests_lost;
+				log_requests_lost = 0;
+			}
+			if (log_requests_pending == 0) {
+				pthread_spin_unlock (&logsys_idx_spinlock);
 				break;
 			}
+			log_rec_idx = record_read (buf, log_rec_idx, &log_msg);
+			if (log_msg) {
+				log_requests_pending -= 1;
+			}
+			pthread_spin_unlock (&logsys_idx_spinlock);
+
+			/*
+			 * print the stored buffer
+			 */
+			if (log_msg) {
+				record_print (buf);
+			}
+		}
+
+		if (wthread_should_exit) {
+			pthread_exit (NULL);
 		}
 	}
-	assert(i < MAX_LOGGERS);
+}
 
-	pthread_mutex_unlock (&logsys_config_mutex);
-	return i;
+static void wthread_create (void)
+{
+	int res;
+
+	if (wthread_active) {
+		return;
+	}
+
+	wthread_active = 1;
+
+	pthread_mutex_init (&logsys_cond_mutex, NULL);
+	pthread_cond_init (&logsys_cond, NULL);
+	pthread_mutex_lock (&logsys_cond_mutex);
+	res = pthread_create (&logsys_thread_id, NULL,
+		logsys_worker_thread, NULL);
+
+
+	/*
+	 * Wait for thread to be started
+	 */
+	wthread_wait_locked ();
 }
 
-inline int logsys_mkpri (int priority, int id)
+/*
+ * Internal API - exported
+ */
+void _logsys_nosubsys_set (void)
 {
-	return (((id) << 3) | (priority));
+	logsys_mode |= LOG_MODE_NOSUBSYS;
 }
 
-int logsys_config_subsys_get (
+unsigned int _logsys_subsys_create (
 	const char *subsys,
-	unsigned int *tags,
-	unsigned int *priority)
+	unsigned int priority)
 {
-	unsigned int i;
+	assert (subsys != NULL);
 
-	pthread_mutex_lock (&logsys_config_mutex);
+	return logsys_config_subsys_set (
+		subsys,
+		LOGSYS_TAG_LOG,
+		priority);
+}
 
- 	for (i = 0; i < MAX_LOGGERS; i++) {
-		if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
-			*tags = logsys_loggers[i].tags;
-			*priority = logsys_loggers[i].priority;
-			pthread_mutex_unlock (&logsys_config_mutex);
-			return i;
+int _logsys_wthread_create (void)
+{
+	if ((logsys_mode & LOG_MODE_FORK) == 0) {
+		if (logsys_name != NULL) {
+			openlog (logsys_name, LOG_CONS|LOG_PID, logsys_facility);
 		}
+		wthread_create();
+		atexit (logsys_atexit);
 	}
-
-	pthread_mutex_unlock (&logsys_config_mutex);
-
-	return (-1);
+	return (0);
 }
 
-static void buffered_log_printf (
-	char *file,
-	int line,
-	int priority,
-	char *format,
-	va_list ap)
+int _logsys_rec_init (unsigned int size)
 {
-	struct log_entry *entry = malloc(sizeof(struct log_entry));
+	/*
+	 * First record starts at zero
+	 * Last record ends at zero
+	 */
+	flt_data = malloc ((size + 2) * sizeof (unsigned int));
+	assert (flt_data != NULL);
+	flt_data_size = size;
+	assert (flt_data != NULL);
+	flt_data[FDHEAD_INDEX] = 0;
+	flt_data[FDTAIL_INDEX] = 0;
+	pthread_spin_init (&logsys_idx_spinlock, 0);
 
-	entry->file = file;
-	entry->line = line;
-	entry->priority = priority;
-	entry->next = NULL;
-	if (head == NULL) {
-		head = tail = entry;
-	} else {
-		tail->next = entry;
-		tail = entry;
-	}
-	vsnprintf(entry->str, sizeof(entry->str), format, ap);
+	return (0);
 }
 
-static void log_printf_worker_fn (void *thread_data, void *work_item)
+
+/*
+ * u32 RECORD SIZE
+ * u32 record ident
+ * u32 arg count
+ * u32 file line
+ * u32 subsys length
+ * buffer null terminated subsys
+ * u32 filename length
+ * buffer null terminated filename
+ * u32 filename length
+ * buffer null terminated function
+ * u32 arg1 length
+ * buffer arg1
+ * ... repeats length & arg
+ */
+void _logsys_log_rec (
+	int subsys,
+	char *function_name,
+	char *file_name,
+	int file_line,
+	unsigned int rec_ident,
+	...)
 {
-	struct log_data *log_data = (struct log_data *)work_item;
+	va_list ap;
+	void *buf_args[64];
+	unsigned int buf_len[64];
+	unsigned int i;
+	unsigned int idx;
+	unsigned int arguments = 0;
+	unsigned int record_reclaim_size;
+	unsigned int index_start;
+	int words_written;
 
-	if (logsys_wthread_active)
-		pthread_mutex_lock (&logsys_config_mutex);
+	record_reclaim_size = 0;
+		
 	/*
-	 * Output the log data
+	 * Decode VA Args
 	 */
-	if (logsys_mode & LOG_MODE_OUTPUT_FILE && logsys_file_fp != 0) {
-		fprintf (logsys_file_fp, "%s", log_data->log_string);
-		fflush (logsys_file_fp);
+	va_start (ap, rec_ident);
+	arguments = 3;
+	for (;;) {
+		assert (arguments < 64);
+		buf_args[arguments] = va_arg (ap, void *);
+		if (buf_args[arguments] == LOG_REC_END) {
+			break;
+		}
+		buf_len[arguments] = va_arg (ap, int);
+		record_reclaim_size += ((buf_len[arguments] + 3) >> 2) + 1;
+		arguments++;
 	}
-	if (logsys_mode & LOG_MODE_OUTPUT_STDERR) {
-		fprintf (stderr, "%s", log_data->log_string);
-		fflush (stdout);
+	va_end (ap);
+
+	/*
+	 * Encode logsys subsystem identity, filename, and function
+	 */
+	buf_args[0] = logsys_loggers[subsys].subsys;
+	buf_len[0] = strlen (logsys_loggers[subsys].subsys) + 1;
+	buf_args[1] = file_name;
+	buf_len[1] = strlen (file_name) + 1;
+	buf_args[2] = function_name;
+	buf_len[2] = strlen (function_name) + 1;
+	for (i = 0; i < 3; i++) {
+		record_reclaim_size += ((buf_len[i] + 3) >> 2) + 1;
 	}
 
-       /* release mutex here in case syslog blocks */
-       if (logsys_wthread_active)
-               pthread_mutex_unlock (&logsys_config_mutex);
+	idx = flt_data[FDHEAD_INDEX];
+	index_start = idx;
 
-	if ((logsys_mode & LOG_MODE_OUTPUT_SYSLOG_THREADED) &&
-		(!((logsys_mode & LOG_MODE_FILTER_DEBUG_FROM_SYSLOG) &&
-		   (log_data->priority == LOG_LEVEL_DEBUG)))) {
-		syslog (log_data->priority,
-			&log_data->log_string[log_data->syslog_pos]);
-	}
-	free (log_data->log_string);
-}
+	/*
+	 * Reclaim data needed for record including 4 words for the header
+	 */
+	records_reclaim (idx, record_reclaim_size + 4);
 
-static void _log_printf (
-	enum logsys_config_mutex_state config_mutex_state,
-	char *file,
-	int line,
-	int priority,
-	int id,
-	char *format,
-	va_list ap)
-{
-	char newstring[4096];
-	char log_string[4096];
-	char char_time[512];
-	char *p = NULL;
-	struct timeval tv;
-	int i = 0;
-	int len;
-	struct log_data log_data;
-	unsigned int res = 0;
+	/*
+	 * Write record size of zero and rest of header information
+	 */
+	flt_data[idx++] = 0;
+	idx_word_step(idx);
 
-	assert (id < MAX_LOGGERS);
+	flt_data[idx++] = rec_ident;
+	idx_word_step(idx);
 
-	if (config_mutex_state == LOGSYS_CONFIG_MUTEX_UNLOCKED) {
-		pthread_mutex_lock (&logsys_config_mutex);
-	}
-	pthread_mutex_lock (&logsys_new_log_mutex);
+	flt_data[idx++] = file_line;
+	idx_word_step(idx);
+
+	flt_data[idx++] = records_written;
+	idx_word_step(idx);
 	/*
-	** Buffer before log has been configured has been called.
-	*/
-	if (logsys_mode & LOG_MODE_BUFFER_BEFORE_CONFIG) {
-		buffered_log_printf(file, line, logsys_mkpri(priority, id), format, ap);
-		pthread_mutex_unlock (&logsys_new_log_mutex);
-		if (config_mutex_state == LOGSYS_CONFIG_MUTEX_UNLOCKED) {
-			pthread_mutex_unlock (&logsys_config_mutex);
-		}
-		return;
-	}
+	 * Encode all of the arguments into the log message
+	 */
+	for (i = 0; i < arguments; i++) {
+		unsigned int bytes;
+		unsigned int full_words;
+		unsigned int total_words;
 
-	if (((logsys_mode & LOG_MODE_OUTPUT_FILE) || (logsys_mode & LOG_MODE_OUTPUT_STDERR)) &&
-		(logsys_mode & LOG_MODE_DISPLAY_TIMESTAMP)) {
-		gettimeofday (&tv, NULL);
-		strftime (char_time, sizeof (char_time), "%b %e %k:%M:%S",
-				  localtime ((time_t *)&tv.tv_sec));
-		i = sprintf (newstring, "%s.%06ld ", char_time, (long)tv.tv_usec);
-	}
+		bytes = buf_len[i];
+		full_words = bytes >> 2;
+		total_words = (bytes + 3) >> 2;
+
+		flt_data[idx++] = total_words;
+		idx_word_step(idx);
 
-	if ((priority == LOG_LEVEL_DEBUG) || (logsys_mode & LOG_MODE_DISPLAY_FILELINE)) {
-		if (logsys_mode & LOG_MODE_SHORT_FILELINE) {
-			p = strrchr(file, '/');
-			if (p) 
-				file = ++p;
-		}
-		sprintf (&newstring[i], "[%s:%04u] %s", file, line, format);
-	} else {	
-		if (logsys_mode & LOG_MODE_NOSUBSYS) {
-			sprintf (&newstring[i], "%s", format);
-		} else {
-			sprintf (&newstring[i], "[%-5s] %s", logsys_loggers[id].subsys, format);
-		}
-	}
-	if (dropped_log_entries) {
 		/*
-		 * Get rid of \n if there is one
+		 * determine if this is a wrapped write or normal write
 		 */
-		if (newstring[strlen (newstring) - 1] == '\n') {
-			newstring[strlen (newstring) - 1] = '\0';
+		if (idx + total_words < flt_data_size) {
+			/*
+			 * dont need to wrap buffer
+			 */
+			my_memcpy_32bit (&flt_data[idx], buf_args[i], full_words);
+			if (bytes % 4) {
+				my_memcpy_8bit ((char *)&flt_data[idx + full_words],
+					((char *)buf_args[i]) + (full_words << 2), bytes % 4);
+			}
+		} else {
+			/*
+			 * need to wrap buffer
+			 */
+			unsigned int first;
+			unsigned int second;
+
+			first = flt_data_size - idx;
+			if (first > full_words) {
+				first = full_words;
+			}
+			second = full_words - first;
+			my_memcpy_32bit (&flt_data[idx], (int *)buf_args[i], first);
+			my_memcpy_32bit (&flt_data[0],
+				(int *)(((unsigned char *)buf_args[i]) + (first << 2)),
+				second);
+			if (bytes % 4) {
+				my_memcpy_8bit ((char *)&flt_data[0 + second],
+					((char *)buf_args[i]) + (full_words << 2), bytes % 4);
+			}
 		}
-		len = sprintf (log_string,
-			"%s - prior to this log entry, corosync logger dropped '%d' messages because of overflow.", newstring, dropped_log_entries + 1);
-	} else {
-		len = vsprintf (log_string, newstring, ap);
+		idx += total_words;
+		idx_buffer_step (idx);
+	}
+	words_written = idx - index_start;
+	if (words_written < 0) {
+		words_written += flt_data_size;
 	}
 
 	/*
-	** add line feed if not done yet
-	*/
-	if (log_string[len - 1] != '\n') {
-		log_string[len] = '\n';
-		log_string[len + 1] = '\0';
-	}
+	 * Commit the write of the record size now that the full record
+	 * is in the memory buffer
+	 */
+	flt_data[index_start] = words_written;
 
 	/*
-	 * Create work thread data
+	 * If the index of the current head equals the current log_rec_idx, 
+	 * and this is not a log_printf operation, set the log_rec_idx to
+	 * the new head position and commit the new head.
 	 */
-	log_data.syslog_pos = i;
-	log_data.priority = priority;
-	log_data.log_string = strdup (log_string);
-	if (log_data.log_string == NULL) {
-		goto drop_log_msg;
+	pthread_spin_lock (&logsys_idx_spinlock);
+	if (rec_ident & LOGSYS_TAG_LOG) {
+		log_requests_pending += 1;
 	}
-	
-	if (logsys_wthread_active) {
-		res = worker_thread_group_work_add (&log_thread_group, &log_data);
-		if (res == 0) {
-			dropped_log_entries = 0;
-		} else {
-			dropped_log_entries += 1;
-		}
-	} else {
-		log_printf_worker_fn (NULL, &log_data);	
+	if (log_requests_pending == 0) {
+		log_rec_idx = idx;
 	}
+	flt_data[FDHEAD_INDEX] = idx;
+	pthread_spin_unlock (&logsys_idx_spinlock);
+	records_written++;
+}
 
-	pthread_mutex_unlock (&logsys_new_log_mutex);
-	if (config_mutex_state == LOGSYS_CONFIG_MUTEX_UNLOCKED) {
-		pthread_mutex_unlock (&logsys_config_mutex);
+void _logsys_log_printf (
+        int subsys,
+        char *function_name,
+        char *file_name,
+        int file_line,
+        unsigned int level,
+        char *format,
+        ...)
+{
+	char logsys_print_buffer[COMBINE_BUFFER_SIZE];
+	unsigned int len;
+	va_list ap;
+
+	if (logsys_mode & LOG_MODE_NOSUBSYS) {
+		subsys = 0;
+	}
+	if (level > logsys_loggers[subsys].priority) {
+		return;
+	}
+	va_start (ap, format);
+	len = vsprintf (logsys_print_buffer, format, ap);
+	va_end (ap);
+	if (logsys_print_buffer[len - 1] == '\n') {
+		logsys_print_buffer[len - 1] = '\0';
+		len -= 1;
 	}
-	return;
 
-drop_log_msg:
-	dropped_log_entries++;
-	pthread_mutex_unlock (&logsys_new_log_mutex);
-	if (config_mutex_state == LOGSYS_CONFIG_MUTEX_UNLOCKED) {
-		pthread_mutex_unlock (&logsys_config_mutex);
+	/*
+	 * Create a log record
+	 */
+	_logsys_log_rec (subsys,
+		function_name,
+		file_name,
+		file_line,
+		(level+1) << 28,
+		logsys_print_buffer, len + 1,
+		LOG_REC_END);
+
+	if ((logsys_mode & LOG_MODE_THREADED) == 0) {
+		/*
+		 * Output (and block) if the log mode is not threaded otherwise
+		 * expect the worker thread to output the log data once signaled
+		 */
+		log_printf_to_logs (logsys_loggers[subsys].subsys,
+			function_name, file_name, file_line, level,
+			logsys_print_buffer);
+	} else {
+		/*
+		 * Signal worker thread to display logging output
+		 */
+		wthread_signal ();
 	}
 }
 
-unsigned int _logsys_subsys_create (
-	const char *subsys,
-	unsigned int priority)
+/*
+ * External Configuration and Initialization API
+ */
+void logsys_fork_completed (void)
 {
-	assert (subsys != NULL);
-
-	return logsys_config_subsys_set (
-		subsys,
-		LOGSYS_TAG_LOG,
-		priority);
+	logsys_mode &= ~LOG_MODE_FORK;
+	_logsys_wthread_create ();
 }
 
-
 void logsys_config_mode_set (unsigned int mode)
 {
 	pthread_mutex_lock (&logsys_config_mutex);
 	logsys_mode = mode;
-	if (mode & LOG_MODE_FLUSH_AFTER_CONFIG) {
-		_logsys_wthread_create ();
-		logsys_buffer_flush ();
-	}
 	pthread_mutex_unlock (&logsys_config_mutex);
 }
 
@@ -431,22 +834,28 @@
 	return logsys_mode;
 }
 
+static void logsys_close_logfile()
+{
+	if (logsys_file_fp != NULL) {
+		fclose (logsys_file_fp);
+		logsys_file_fp = NULL;
+	}
+}
+
 int logsys_config_file_set (char **error_string, char *file)
 {
 	static char error_string_response[512];
 
 	if (file == NULL) {
+		logsys_close_logfile();
 		return (0);
 	}
 
-	pthread_mutex_lock (&logsys_new_log_mutex);
 	pthread_mutex_lock (&logsys_config_mutex);
 
 	if (logsys_mode & LOG_MODE_OUTPUT_FILE) {
 		logsys_file = file;
-		if (logsys_file_fp != NULL) {
-			fclose (logsys_file_fp);
-		}
+		logsys_close_logfile();
 		logsys_file_fp = fopen (file, "a+");
 		if (logsys_file_fp == 0) {
 			sprintf (error_string_response,
@@ -454,222 +863,243 @@
 					 file, strerror (errno));
 			*error_string = error_string_response;
 			pthread_mutex_unlock (&logsys_config_mutex);
-			pthread_mutex_unlock (&logsys_new_log_mutex);
 			return (-1);
 		}
-	}
+	} else
+		logsys_close_logfile();
 
 	pthread_mutex_unlock (&logsys_config_mutex);
-	pthread_mutex_unlock (&logsys_new_log_mutex);
 	return (0);
 }
 
-void logsys_config_facility_set (char *name, unsigned int facility)
+void logsys_format_set (char *format)
 {
-	pthread_mutex_lock (&logsys_new_log_mutex);
 	pthread_mutex_lock (&logsys_config_mutex);
 
-	logsys_name = name;
-	logsys_facility = facility;
+	logsys_format = format;
 
 	pthread_mutex_unlock (&logsys_config_mutex);
-	pthread_mutex_unlock (&logsys_new_log_mutex);
 }
 
-void _logsys_config_priority_set (unsigned int id, unsigned int priority)
+void logsys_config_facility_set (char *name, unsigned int facility)
 {
-	pthread_mutex_lock (&logsys_new_log_mutex);
+	pthread_mutex_lock (&logsys_config_mutex);
 
-	logsys_loggers[id].priority = priority;
+	logsys_name = name;
+	logsys_facility = facility;
 
-	pthread_mutex_unlock (&logsys_new_log_mutex);
+	pthread_mutex_unlock (&logsys_config_mutex);
 }
 
-static void child_cleanup (void)
+int logsys_facility_id_get (const char *name)
 {
-	memset(&log_thread_group, 0, sizeof(log_thread_group));
-	logsys_wthread_active = 0;
-	pthread_mutex_init(&logsys_config_mutex, NULL);
-	pthread_mutex_init(&logsys_new_log_mutex, NULL);
+	unsigned int i;
+
+	for (i = 0; facilitynames[i].c_name != NULL; i++) {
+		if (strcasecmp(name, facilitynames[i].c_name) == 0) {
+			return (facilitynames[i].c_val);
+		}
+	}
+	return (-1);
 }
 
-int _logsys_wthread_create (void)
+const char *logsys_facility_name_get (unsigned int facility)
 {
-	worker_thread_group_init (
-		&log_thread_group,
-		1,
-		1024,
-		sizeof (struct log_data),
-		0,
-		NULL,
-		log_printf_worker_fn);
-
-	logsys_flush();
-
-	atexit (logsys_atexit);
-	pthread_atfork(NULL, NULL, child_cleanup);
+	unsigned int i;
 
-	if (logsys_mode & LOG_MODE_OUTPUT_SYSLOG_THREADED && logsys_name != NULL) {
-		openlog (logsys_name, LOG_CONS|LOG_PID, logsys_facility);
+	for (i = 0; facilitynames[i].c_name != NULL; i++) {
+		if (facility == facilitynames[i].c_val) {
+			return (facilitynames[i].c_name);
+		}
 	}
+	return (NULL);
+}
 
-	logsys_wthread_active = 1;
+int logsys_priority_id_get (const char *name)
+{
+	unsigned int i;
 
-	return (0);
+	for (i = 0; prioritynames[i].c_name != NULL; i++) {
+		if (strcasecmp(name, prioritynames[i].c_name) == 0) {
+			return (prioritynames[i].c_val);
+		}
+	}
+	return (-1);
 }
 
-void logsys_log_printf (
-	char *file,
-	int line,
-	int priority,
-	char *format,
-	...)
+const char *logsys_priority_name_get (unsigned int priority)
 {
-	int id = LOG_ID(priority);
-	int level = LOG_LEVEL(priority);
-	va_list ap;
-
-	assert (id < MAX_LOGGERS);
+	unsigned int i;
 
-	if (LOG_LEVEL(priority) > logsys_loggers[id].priority) {
-		return;
+	for (i = 0; prioritynames[i].c_name != NULL; i++) {
+		if (priority == prioritynames[i].c_val) {
+			return (prioritynames[i].c_name);
+		}
 	}
-
-	va_start (ap, format);
-	_log_printf (LOGSYS_CONFIG_MUTEX_UNLOCKED, file, line, level, id,
-		format, ap);
-	va_end(ap);
+	return (NULL);
 }
 
-static void logsys_log_printf_locked (
-	char *file,
-	int line,
-	int priority,
-	char *format,
-	...)
+int logsys_tag_id_get (const char *name)
 {
-	int id = LOG_ID(priority);
-	int level = LOG_LEVEL(priority);
-	va_list ap;
-
-	assert (id < MAX_LOGGERS);
+	unsigned int i;
 
-	if (LOG_LEVEL(priority) > logsys_loggers[id].priority) {
-		return;
+	for (i = 0; tagnames[i].c_name != NULL; i++) {
+		if (strcasecmp(name, tagnames[i].c_name) == 0) {
+			return (tagnames[i].c_val);
+		}
 	}
-
-	va_start (ap, format);
-	_log_printf (LOGSYS_CONFIG_MUTEX_LOCKED, file, line, level, id,
-		format, ap);
-	va_end(ap);
+	return (-1);
 }
 
-void _logsys_log_printf2 (
-	char *file,
-	int line,
-	int priority,
-	int id,
-	char *format, ...)
+const char *logsys_tag_name_get (unsigned int tag)
 {
-	va_list ap;
-
-	assert (id < MAX_LOGGERS);
+	unsigned int i;
 
-	va_start (ap, format);
-	_log_printf (LOGSYS_CONFIG_MUTEX_UNLOCKED, file, line, priority, id,
-		format, ap);
-	va_end(ap);
+	for (i = 0; tagnames[i].c_name != NULL; i++) {
+		if (tag == tagnames[i].c_val) {
+			return (tagnames[i].c_name);
+		}
+	}
+	return (NULL);
 }
 
-void _logsys_trace (char *file, int line, int tag, int id, char *format, ...)
+unsigned int logsys_config_subsys_set (
+	const char *subsys,
+	unsigned int tags,
+	unsigned int priority)
 {
-	assert (id < MAX_LOGGERS);
+	int i;
 
 	pthread_mutex_lock (&logsys_config_mutex);
+ 	for (i = 0; i < SUBSYS_MAX; i++) {
+		if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
+			logsys_loggers[i].tags = tags;
+			logsys_loggers[i].priority = priority;
 
-	if (tag & logsys_loggers[id].tags) {
-		va_list ap;
+			break;
+		}
+	}
 
-		va_start (ap, format);
-		_log_printf (LOGSYS_CONFIG_MUTEX_LOCKED, file, line,
-			LOG_LEVEL_DEBUG, id, format, ap);
-		va_end(ap);
+	if (i == SUBSYS_MAX) {
+		for (i = 0; i < SUBSYS_MAX; i++) {
+			if (strcmp (logsys_loggers[i].subsys, "") == 0) {
+				strncpy (logsys_loggers[i].subsys, subsys,
+					sizeof(logsys_loggers[i].subsys));
+				logsys_loggers[i].tags = tags;
+				logsys_loggers[i].priority = priority;
+				break;
+			}
+		}
 	}
+	assert(i < SUBSYS_MAX);
+
 	pthread_mutex_unlock (&logsys_config_mutex);
+	return i;
 }
 
-static void logsys_atexit (void)
+int logsys_config_subsys_get (
+	const char *subsys,
+	unsigned int *tags,
+	unsigned int *priority)
 {
-	if (logsys_wthread_active) {
-		worker_thread_group_wait (&log_thread_group);
-	}
-	if (logsys_mode & LOG_MODE_OUTPUT_SYSLOG_THREADED) {
-		closelog ();
+	unsigned int i;
+
+	pthread_mutex_lock (&logsys_config_mutex);
+
+ 	for (i = 0; i < SUBSYS_MAX; i++) {
+		if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
+			*tags = logsys_loggers[i].tags;
+			*priority = logsys_loggers[i].priority;
+			pthread_mutex_unlock (&logsys_config_mutex);
+			return i;
+		}
 	}
+
+	pthread_mutex_unlock (&logsys_config_mutex);
+
+	return (-1);
 }
 
-static void logsys_buffer_flush (void)
+int logsys_log_rec_store (char *filename)
 {
-	struct log_entry *entry = head;
-	struct log_entry *tmp;
+	int fd;
+	ssize_t written_size;
+	size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int);
 
-	if (logsys_mode & LOG_MODE_FLUSH_AFTER_CONFIG) {
-		logsys_mode &= ~LOG_MODE_FLUSH_AFTER_CONFIG;
+	fd = open (filename, O_CREAT|O_RDWR, 0700);
+	if (fd == -1) {
+		return (-1);
+	}
 
-		while (entry) {
-			logsys_log_printf_locked (
-				entry->file,
-				entry->line,
-				entry->priority,
-				entry->str);
-			tmp = entry;
-			entry = entry->next;
-			free (tmp);
-		}
+	written_size = write (fd, flt_data, size_to_write);
+	if (written_size < 0) {
+		return (-1);
+	} else if ((size_t)written_size != size_to_write) {
+		return (-1);
 	}
+	return (0);
+}
 
-	head = tail = NULL;
+static void logsys_atexit (void)
+{
+	if (wthread_active) {
+		wthread_should_exit = 1;
+		wthread_signal ();
+		pthread_join (logsys_thread_id, NULL);
+	}
 }
 
-void logsys_flush (void)
+void logsys_atsegv (void)
 {
-	worker_thread_group_wait (&log_thread_group);
+	if (wthread_active) {
+		wthread_should_exit = 1;
+		wthread_signal ();
+		pthread_join (logsys_thread_id, NULL);
+	}
 }
 
-int logsys_init (char *name, int mode, int facility, int priority, char *file)
+int logsys_init (
+	char *name,
+	int mode,
+	int facility,
+	int priority,
+	char *file,
+	char *format,
+	int rec_size)
 {
 	char *errstr;
 
-	/* logsys_subsys_id will be 0 */
-	logsys_single_id = 1;
-
+	_logsys_nosubsys_set ();
+	_logsys_subsys_create (name, priority);
 	strncpy (logsys_loggers[0].subsys, name,
 		 sizeof (logsys_loggers[0].subsys));
 	logsys_config_mode_set (mode);
 	logsys_config_facility_set (name, facility);
 	logsys_config_file_set (&errstr, file);
-	_logsys_config_priority_set (0, priority);
-	if ((mode & LOG_MODE_BUFFER_BEFORE_CONFIG) == 0) {
-		_logsys_wthread_create ();
-	}
+	logsys_format_set (format);
+	_logsys_rec_init (rec_size);
+	_logsys_wthread_create ();
 	return (0);
 }
 
-int logsys_conf (char *name, int mode, int facility, int priority, char *file)
+int logsys_conf (
+	char *name,
+	int mode,
+	int facility,
+	int priority,
+	char *file)
 {
 	char *errstr;
 
+	_logsys_rec_init (100000);
 	strncpy (logsys_loggers[0].subsys, name,
 		sizeof (logsys_loggers[0].subsys));
 	logsys_config_mode_set (mode);
 	logsys_config_facility_set (name, facility);
 	logsys_config_file_set (&errstr, file);
-	_logsys_config_priority_set (0, priority);
 	return (0);
 }
 
 void logsys_exit (void)
 {
-	logsys_flush ();
 }
-
diff -Naurd corosync-0.92/exec/main.c corosync-trunk/exec/main.c
--- corosync-0.92/exec/main.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/exec/main.c	2009-01-23 17:12:13.000000000 +0100
@@ -34,8 +34,6 @@
  */
 #include <pthread.h>
 #include <assert.h>
-#include <pwd.h>
-#include <grp.h>
 #include <sys/types.h>
 #include <sys/poll.h>
 #include <sys/uio.h>
@@ -56,7 +54,7 @@
 #include <time.h>
 
 #include <corosync/swab.h>
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/list.h>
 #include <corosync/queue.h>
 #include <corosync/lcr/lcr_ifact.h>
@@ -66,6 +64,7 @@
 #include <corosync/engine/config.h>
 #include <corosync/engine/logsys.h>
 
+#include "quorum.h"
 #include "totemsrp.h"
 #include "mempool.h"
 #include "mainconfig.h"
@@ -83,18 +82,16 @@
 #include "version.h"
 
 LOGSYS_DECLARE_SYSTEM ("corosync",
-	LOG_MODE_OUTPUT_STDERR | LOG_MODE_OUTPUT_SYSLOG_THREADED | LOG_MODE_BUFFER_BEFORE_CONFIG,
+	LOG_MODE_OUTPUT_STDERR | LOG_MODE_THREADED | LOG_MODE_FORK,
 	NULL,
-	LOG_DAEMON);
+	LOG_DAEMON,
+	"[%6s] %b",
+	1000000);
 
 LOGSYS_DECLARE_SUBSYS ("MAIN", LOG_INFO);
 
 #define SERVER_BACKLOG 5
 
-static int ais_uid = 0;
-
-static int gid_valid = 0;
-
 static unsigned int service_count = 32;
 
 static pthread_mutex_t serialize_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -145,7 +142,6 @@
 #endif
 
 	totempg_finalize ();
-	logsys_flush ();
 
 	corosync_exit_error (AIS_DONE_EXIT);
 
@@ -170,15 +166,17 @@
 
 static void sigsegv_handler (int num)
 {
-	signal (SIGSEGV, SIG_DFL);
-	logsys_flush ();
+	(void)signal (SIGSEGV, SIG_DFL);
+	logsys_atsegv();
+	logsys_log_rec_store ("/var/lib/corosync/fdata");
 	raise (SIGSEGV);
 }
 
 static void sigabrt_handler (int num)
 {
-	signal (SIGABRT, SIG_DFL);
-	logsys_flush ();
+	(void)signal (SIGABRT, SIG_DFL);
+	logsys_atsegv();
+	logsys_log_rec_store ("/var/lib/corosync/fdata");
 	raise (SIGABRT);
 }
 
@@ -271,36 +269,11 @@
 	}
 }
 
-static void aisexec_uid_determine (struct main_config *main_config)
-{
-	struct passwd *passwd;
-
-	passwd = getpwnam(main_config->user);
-	if (passwd == 0) {
-		log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' user is not found in /etc/passwd, please read the documentation.\n", main_config->user);
-		corosync_exit_error (AIS_DONE_UID_DETERMINE);
-	}
-	ais_uid = passwd->pw_uid;
-	endpwent ();
-}
-
-static void aisexec_gid_determine (struct main_config *main_config)
-{
-	struct group *group;
-	group = getgrnam (main_config->group);
-	if (group == 0) {
-		log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' group is not found in /etc/group, please read the documentation.\n", group->gr_name);
-		corosync_exit_error (AIS_DONE_GID_DETERMINE);
-	}
-	gid_valid = group->gr_gid;
-	endgrent ();
-}
-
-static void aisexec_priv_drop (void)
+static void priv_drop (struct main_config *main_config)
 {
-return;
-	setuid (ais_uid);
-	setegid (ais_uid);
+return; /* TODO: we are still not dropping privs */
+	setuid (main_config->uid);
+	setegid (main_config->gid);
 }
 
 static void aisexec_mempool_init (void)
@@ -341,7 +314,7 @@
 	}
 
 	/* Create new session */
-	setsid();
+	(void)setsid();
 
 	/* 
 	 * Map stdin/out/err to /dev/null.
@@ -408,7 +381,6 @@
 #endif
 }
 
-
 static void deliver_fn (
 	unsigned int nodeid,
 	struct iovec *iovec,
@@ -448,6 +420,8 @@
 	 */
 	service = header->id >> 16;
 	fn_id = header->id & 0xffff;
+	if (!ais_service[service])
+		return;
 	if (endian_conversion_required) {
 		assert(ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn != NULL);
 		ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn
@@ -494,7 +468,6 @@
 	char *iface;
 	int res, ch;
 	int background, setprio;
- 	int totem_log_service;
 
  	/* default configuration
 	 */
@@ -506,7 +479,7 @@
 		switch (ch) {
 			case 'f':
 				background = 0;
-				logsys_config_mode_set (LOG_MODE_OUTPUT_STDERR|LOG_MODE_FLUSH_AFTER_CONFIG);
+				logsys_config_mode_set (LOG_MODE_OUTPUT_STDERR|LOG_MODE_THREADED|LOG_MODE_FORK);
 				break;
 			case 'p':
 				setprio = 0;
@@ -527,11 +500,11 @@
 	log_printf (LOG_LEVEL_NOTICE, "Copyright (C) 2002-2006 MontaVista Software, Inc and contributors.\n");
 	log_printf (LOG_LEVEL_NOTICE, "Copyright (C) 2006-2008 Red Hat, Inc.\n");
 
-	signal (SIGINT, sigintr_handler);
-	signal (SIGUSR2, sigusr2_handler);
-	signal (SIGSEGV, sigsegv_handler);
-	signal (SIGABRT, sigabrt_handler);
-	signal (SIGQUIT, sigquit_handler);
+	(void)signal (SIGINT, sigintr_handler);
+	(void)signal (SIGUSR2, sigusr2_handler);
+	(void)signal (SIGSEGV, sigsegv_handler);
+	(void)signal (SIGABRT, sigabrt_handler);
+	(void)signal (SIGQUIT, sigquit_handler);
 	
 	corosync_timer_init (
 		serialize_mutex_lock,
@@ -635,14 +608,6 @@
 		corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
 	}
 
-	logsys_config_facility_set ("corosync", main_config.syslog_facility);
-	logsys_config_mode_set (main_config.logmode);
-	logsys_config_file_set (&error_string, main_config.logfile);
-
-	aisexec_uid_determine (&main_config);
-
-	aisexec_gid_determine (&main_config);
-
 	/*
 	 * Set round robin realtime scheduling with priority 99
 	 * Lock all memory to avoid page faults which may interrupt
@@ -654,13 +619,14 @@
 	aisexec_mlockall ();
 
 	totem_config.totem_logging_configuration = totem_logging_configuration;
-	totem_log_service = _logsys_subsys_create ("TOTEM", LOG_INFO);
-  	totem_config.totem_logging_configuration.log_level_security = logsys_mkpri (LOG_LEVEL_SECURITY, totem_log_service);
-	totem_config.totem_logging_configuration.log_level_error = logsys_mkpri (LOG_LEVEL_ERROR, totem_log_service);
-	totem_config.totem_logging_configuration.log_level_warning = logsys_mkpri (LOG_LEVEL_WARNING, totem_log_service);
-	totem_config.totem_logging_configuration.log_level_notice = logsys_mkpri (LOG_LEVEL_NOTICE, totem_log_service);
-	totem_config.totem_logging_configuration.log_level_debug = logsys_mkpri (LOG_LEVEL_DEBUG, totem_log_service);
-	totem_config.totem_logging_configuration.log_printf = logsys_log_printf;
+	totem_config.totem_logging_configuration.log_subsys_id =
+		_logsys_subsys_create ("TOTEM", LOG_INFO);
+  	totem_config.totem_logging_configuration.log_level_security = LOG_LEVEL_SECURITY;
+	totem_config.totem_logging_configuration.log_level_error = LOG_LEVEL_ERROR;
+	totem_config.totem_logging_configuration.log_level_warning = LOG_LEVEL_WARNING;
+	totem_config.totem_logging_configuration.log_level_notice = LOG_LEVEL_NOTICE;
+	totem_config.totem_logging_configuration.log_level_debug = LOG_LEVEL_DEBUG;
+	totem_config.totem_logging_configuration.log_printf = _logsys_log_printf;
 
 	/*
 	 * Sleep for a while to let other nodes in the cluster
@@ -704,11 +670,9 @@
 	}
 
 
-	sync_register (corosync_sync_callbacks_retrieve, corosync_sync_completed,
-		totem_config.vsf_type);
-
+	sync_register (corosync_sync_callbacks_retrieve, corosync_sync_completed);
 
-	res = corosync_flow_control_initialize ();
+	res = cs_flow_control_initialize ();
 
 	/*
 	 * Drop root privleges to user 'ais'
@@ -718,14 +682,14 @@
 	 * CAP_SYS_NICE (setscheduler)
 	 * CAP_IPC_LOCK (mlockall)
 	 */
-	aisexec_priv_drop ();
+	priv_drop (&main_config);
 
 	aisexec_mempool_init ();
 
-	corosync_ipc_init (
+	cs_ipc_init (
 		serialize_mutex_lock,
 		serialize_mutex_unlock,
-		gid_valid);
+		main_config.gid);
 
 	/*
 	 * Start main processing loop
diff -Naurd corosync-0.92/exec/mainconfig.c corosync-trunk/exec/mainconfig.c
--- corosync-0.92/exec/mainconfig.c	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/exec/mainconfig.c	2009-01-23 17:12:13.000000000 +0100
@@ -40,8 +40,10 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <pwd.h>
+#include <grp.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/list.h>
 #include <corosync/totem/totem.h>
 #include <corosync/engine/logsys.h>
@@ -51,6 +53,12 @@
 #include "mempool.h"
 
 static char error_string_response[512];
+static struct objdb_iface_ver0 *global_objdb;
+
+static void add_logsys_config_notification(
+	struct objdb_iface_ver0 *objdb,
+	struct main_config *main_config);
+
 
 /* This just makes the code below a little neater */
 static inline int objdb_get_string (
@@ -98,7 +106,10 @@
 	unsigned int tags;
 } logsys_logger;
 
-int corosync_main_config_read (
+
+
+
+int corosync_main_config_read_logging (
 	struct objdb_iface_ver0 *objdb,
 	char **error_string,
 	struct main_config *main_config)
@@ -109,10 +120,6 @@
 	char *error_reason = error_string_response;
 	unsigned int object_find_handle;
 	unsigned int object_find_logsys_handle;
-	int global_debug = 0;
-
-
-	memset (main_config, 0, sizeof (struct main_config));
 
 	objdb->object_find_create (
 		OBJECT_PARENT_HANDLE,
@@ -120,7 +127,7 @@
 		strlen ("logging"),
 		&object_find_handle);
 
-	main_config->logmode = LOG_MODE_FLUSH_AFTER_CONFIG;
+	main_config->logmode = LOG_MODE_THREADED | LOG_MODE_FORK;
 	if (objdb->object_find_next (
 		object_find_handle,
 		&object_service_handle) == 0) {
@@ -135,10 +142,10 @@
 		}
 		if (!objdb_get_string (objdb,object_service_handle, "to_syslog", &value)) {
 			if (strcmp (value, "yes") == 0) {
-				main_config->logmode |= LOG_MODE_OUTPUT_SYSLOG_THREADED;
+				main_config->logmode |= LOG_MODE_OUTPUT_SYSLOG;
 			} else
 			if (strcmp (value, "no") == 0) {
-				main_config->logmode &= ~LOG_MODE_OUTPUT_SYSLOG_THREADED;
+				main_config->logmode &= ~LOG_MODE_OUTPUT_SYSLOG;
 			}
 		}
 		if (!objdb_get_string (objdb,object_service_handle, "to_stderr", &value)) {
@@ -149,18 +156,8 @@
 				main_config->logmode &= ~LOG_MODE_OUTPUT_STDERR;
 			}
 		}
-
-		if (!objdb_get_string (objdb,object_service_handle, "debug", &value)) {
-                        if (strcmp (value, "on") == 0) {
-                                global_debug = 1;
-                        } else
-                        if (strcmp (value, "off") == 0) {
-                                global_debug = 0;
-                        } else {
-                                goto parse_error;
-                        }
-                }
 		if (!objdb_get_string (objdb,object_service_handle, "timestamp", &value)) {
+/* todo change format string
 			if (strcmp (value, "on") == 0) {
 				main_config->logmode |= LOG_MODE_DISPLAY_TIMESTAMP;
 			} else
@@ -169,12 +166,20 @@
 			} else {
 				goto parse_error;
 			}
+*/
+		}
+
+		/* free old string on reload */
+		if (main_config->logfile) {
+			free(main_config->logfile);
+			main_config->logfile = NULL;
 		}
 		if (!objdb_get_string (objdb,object_service_handle, "logfile", &value)) {
 			main_config->logfile = strdup (value);
 		}
 
 		if (!objdb_get_string (objdb,object_service_handle, "fileline", &value)) {
+/* TODO
 			if (strcmp (value, "on") == 0) {
 				main_config->logmode |= LOG_MODE_DISPLAY_FILELINE;
 			} else
@@ -183,41 +188,21 @@
 			} else {
 				goto parse_error;
 			}
+*/
 		}
 
 		if (!objdb_get_string (objdb,object_service_handle, "syslog_facility", &value)) {
-			if (strcmp (value, "daemon") == 0) {
-				main_config->syslog_facility = LOG_DAEMON;
-			} else
-			if (strcmp (value, "local0") == 0) {
-				main_config->syslog_facility = LOG_LOCAL0;
-			} else
-			if (strcmp (value, "local1") == 0) {
-				main_config->syslog_facility = LOG_LOCAL1;
-			} else
-			if (strcmp (value, "local2") == 0) {
-				main_config->syslog_facility = LOG_LOCAL2;
-			} else
-			if (strcmp (value, "local3") == 0) {
-				main_config->syslog_facility = LOG_LOCAL3;
-			} else
-			if (strcmp (value, "local4") == 0) {
-				main_config->syslog_facility = LOG_LOCAL4;
-			} else
-			if (strcmp (value, "local5") == 0) {
-				main_config->syslog_facility = LOG_LOCAL5;
-			} else
-			if (strcmp (value, "local6") == 0) {
-				main_config->syslog_facility = LOG_LOCAL6;
-			} else
-			if (strcmp (value, "local7") == 0) {
-				main_config->syslog_facility = LOG_LOCAL7;
-			} else {
+			main_config->syslog_facility = logsys_facility_id_get(value);
+			if (main_config->syslog_facility < 0) {
 				error_reason = "unknown syslog facility specified";
 				goto parse_error;
 			}
 		}
 
+		logsys_config_facility_set ("corosync", main_config->syslog_facility);
+		logsys_config_mode_set (main_config->logmode);
+		logsys_config_file_set (error_string, main_config->logfile);
+
 		objdb->object_find_create (
 			object_service_handle,
 			"logger_subsys",
@@ -239,6 +224,13 @@
 				error_reason = "subsys required for logger directive";
 				goto parse_error;
 			}
+			if (!objdb_get_string (objdb, object_logger_subsys_handle, "syslog_level", &value)) {
+				logsys_logger.priority = logsys_priority_id_get(value);
+				if (logsys_logger.priority < 0) {
+					error_reason = "unknown syslog priority specified";
+					goto parse_error;
+				}
+			}
 			if (!objdb_get_string (objdb, object_logger_subsys_handle, "debug", &value)) {
 				if (strcmp (value, "on") == 0) {
 					logsys_logger.priority = LOG_LEVEL_DEBUG;
@@ -253,31 +245,14 @@
 				char *token = strtok (value, "|");
 
 				while (token != NULL) {
-					if (strcmp (token, "enter") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_ENTER;
-					} else if (strcmp (token, "leave") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_LEAVE;
-					} else if (strcmp (token, "trace1") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE1;
-					} else if (strcmp (token, "trace2") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE2;
-					} else if (strcmp (token, "trace3") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE3;
-					} else if (strcmp (token, "trace4") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE4;
-					} else if (strcmp (token, "trace5") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE5;
-					} else if (strcmp (token, "trace6") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE6;
-					} else if (strcmp (token, "trace7") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE7;
-					} else if (strcmp (token, "trace8") == 0) {
-						logsys_logger.tags |= LOGSYS_TAG_TRACE8;
-					} else {
+					int val;
+
+					val = logsys_tag_id_get(token);
+					if (val < 0) {
 						error_reason = "bad tags value";
 						goto parse_error;
 					}
-
+					logsys_logger.tags |= val;
 					token = strtok(NULL, "|");
 				}
 			}
@@ -295,6 +270,61 @@
 
 	objdb->object_find_destroy (object_find_handle);
 
+	return 0;
+
+parse_error:
+	sprintf (error_string_response,
+		 "parse error in config: %s.\n",
+		 error_reason);
+
+	*error_string = error_string_response;
+	return (-1);
+}
+
+static int uid_determine (char *req_user)
+{
+	struct passwd *passwd;
+	int ais_uid = 0;
+
+	passwd = getpwnam(req_user);
+	if (passwd == 0) {
+		log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' user is not found in /etc/passwd, please read the documentation.\n", req_user);
+		corosync_exit_error (AIS_DONE_UID_DETERMINE);
+	}
+	ais_uid = passwd->pw_uid;
+	endpwent ();
+	return ais_uid;
+}
+
+static int gid_determine (char *req_group)
+{
+	struct group *group;
+	int ais_gid = 0;
+
+	group = getgrnam (req_group);
+	if (group == 0) {
+		log_printf (LOG_LEVEL_ERROR, "ERROR: The '%s' group is not found in /etc/group, please read the documentation.\n", req_group);
+		corosync_exit_error (AIS_DONE_GID_DETERMINE);
+	}
+	ais_gid = group->gr_gid;
+	endgrent ();
+	return ais_gid;
+}
+
+int corosync_main_config_read (
+	struct objdb_iface_ver0 *objdb,
+	char **error_string,
+	struct main_config *main_config)
+{
+	unsigned int object_service_handle;
+	char *value;
+	char *error_reason = error_string_response;
+	unsigned int object_find_handle;
+
+	memset (main_config, 0, sizeof (struct main_config));
+
+	corosync_main_config_read_logging(objdb, error_string, main_config);
+
 	objdb->object_find_create (
 		OBJECT_PARENT_HANDLE,
 		"aisexec",
@@ -306,22 +336,18 @@
 		&object_service_handle) == 0) {
 
 		if (!objdb_get_string (objdb,object_service_handle, "user", &value)) {
-			main_config->user = strdup(value);
-		}
+			main_config->uid = uid_determine(value);
+		} else
+			main_config->uid = uid_determine("ais");
+
 		if (!objdb_get_string (objdb,object_service_handle, "group", &value)) {
-			main_config->group = strdup(value);
-		}
+			main_config->gid = gid_determine(value);
+		} else
+			main_config->gid = gid_determine("ais");
 	}
 
 	objdb->object_find_destroy (object_find_handle);
 
-	/* Default user/group */
-	if (!main_config->user)
-		main_config->user = "ais";
-
-	if (!main_config->group)
-		main_config->group = "ais";
-
 	if ((main_config->logmode & LOG_MODE_OUTPUT_FILE) &&
 		(main_config->logfile == NULL)) {
 		error_reason = "logmode set to 'file' but no logfile specified";
@@ -331,6 +357,10 @@
 	if (main_config->syslog_facility == 0)
 		main_config->syslog_facility = LOG_DAEMON;
 
+	add_logsys_config_notification(objdb, main_config);
+
+	logsys_fork_completed ();
+
 	return 0;
 
 parse_error:
@@ -341,3 +371,38 @@
 	*error_string = error_string_response;
 	return (-1);
 }
+
+
+static void main_objdb_reload_notify(objdb_reload_notify_type_t type, int flush,
+				     void *priv_data_pt)
+{
+	struct main_config *main_config = priv_data_pt;
+	char *error_string;
+
+	if (type == OBJDB_RELOAD_NOTIFY_END) {
+
+		/*
+		 * Reload the logsys configuration
+		 */
+		corosync_main_config_read_logging(global_objdb,
+						  &error_string,
+						  main_config);
+	}
+}
+
+static void add_logsys_config_notification(
+	struct objdb_iface_ver0 *objdb,
+	struct main_config *main_config)
+{
+
+	global_objdb = objdb;
+
+	objdb->object_track_start(OBJECT_PARENT_HANDLE,
+				  1,
+				  NULL,
+				  NULL,
+				  NULL,
+				  main_objdb_reload_notify,
+				  main_config);
+
+}
diff -Naurd corosync-0.92/exec/mainconfig.h corosync-trunk/exec/mainconfig.h
--- corosync-0.92/exec/mainconfig.h	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/exec/mainconfig.h	2009-01-23 17:12:13.000000000 +0100
@@ -61,13 +61,13 @@
 	/*
 	 * user/group to run as
 	 */
-	char *user;
-	char *group;
+	int uid;
+	int gid;
 };
 
 extern int corosync_main_config_read (
 	struct objdb_iface_ver0 *objdb,
 	char **error_string,
 	struct main_config *main_config);
-	
+
 #endif /* MAINCONFIG_H_DEFINED */
diff -Naurd corosync-0.92/exec/main.h corosync-trunk/exec/main.h
--- corosync-0.92/exec/main.h	2008-08-20 02:57:40.000000000 +0200
+++ corosync-trunk/exec/main.h	2008-11-06 22:49:07.000000000 +0100
@@ -37,7 +37,7 @@
 
 #define TRUE 1
 #define FALSE 0
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/ipc_gen.h>
 #include <corosync/totem/coropoll.h>
 #include <corosync/totem/totempg.h>
diff -Naurd corosync-0.92/exec/Makefile corosync-trunk/exec/Makefile
--- corosync-0.92/exec/Makefile	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/exec/Makefile	2008-12-08 16:55:41.000000000 +0100
@@ -59,14 +59,14 @@
 EXEC_LIBS = libtotem_pg.a liblogsys.a
 
 # LCR objects
-LCR_SRC = vsf_ykd.c objdb.c coroparse.c
-LCR_OBJS = vsf_ykd.o objdb.o coroparse.o
+LCR_SRC = vsf_ykd.c objdb.c coroparse.c vsf_quorum.c
+LCR_OBJS = vsf_ykd.o objdb.o coroparse.o vsf_quorum.o
 
 # main executive objects
 MAIN_SRC = main.c mempool.c util.c sync.c apidef.c service.c ipc.c flow.c \
-	timer.c totemconfig.c mainconfig.c
+	quorum.c timer.c totemconfig.c mainconfig.c
 MAIN_OBJS = main.o mempool.o util.o sync.o apidef.o service.o ipc.o flow.o \
-	timer.o totemconfig.o mainconfig.o ../lcr/lcr_ifact.o
+	quorum.o timer.o totemconfig.o mainconfig.o ../lcr/lcr_ifact.o
 
 ifeq (${BUILD_DYNAMIC}, 1) 
 #EXEC_OBJS = $(TOTEM_OBJS) $(LOGSYS_OBJS) $(MAIN_OBJS)
@@ -75,7 +75,7 @@
 
 all:libtotem_pg.a libtotem_pg.so.2.0.0 liblogsys.a liblogsys.so.2.0.0 \
 	../lcr/lcr_ifact.o corosync_ \
-	objdb.lcrso vsf_ykd.lcrso coroparse.lcrso
+	objdb.lcrso vsf_ykd.lcrso coroparse.lcrso vsf_quorum.lcrso
 else
 EXEC_OBJS = $(MAIN_OBJS) $(LCR_OBJS)
 all: libtotem_pg.a liblogsys.a corosync
@@ -90,6 +90,9 @@
 vsf_ykd.lcrso: vsf_ykd.o
 	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ./corosync -bind_at_load vsf_ykd.o -o $@
 
+vsf_quorum.lcrso: vsf_quorum.o
+	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ./corosync -bind_at_load vsf_quorum.o -o $@
+
 coroparse.lcrso: coroparse.o
 	$(CC) -bundle -bundle_loader ./corosync -bind_at_load coroparse.o -o $@
 
@@ -98,9 +101,15 @@
 vsf_ykd.lcrso: vsf_ykd.o
 	$(CC) -shared -Wl,-soname,vsf_ykd.lcrso vsf_ykd.o -o $@
 
+vsf_quorum.lcrso: vsf_quorum.o
+	$(CC) -shared -Wl,-soname,vsf_quorum.lcrso vsf_quorum.o -o $@
+
 objdb.lcrso: objdb.o
 	$(CC) -shared -Wl,-soname,objdb.lcrso objdb.o -o $@
 
+testquorum.lcrso: testquorum.o
+	$(CC) -shared -Wl,-soname,testquorum.lcrso objdb.o -o $@
+
 coroparse.lcrso: coroparse.o
 	$(CC) -shared -Wl,-soname,coroparse.lcrso coroparse.o -o $@
 endif
@@ -131,6 +140,9 @@
 
 endif
 
+lint:
+	-splint $(LINT_FLAGS) $(CFLAGS) *.c
+
 clean:
 	rm -f corosync $(OBJS) *.o *.lcrso libtotem_pg.so* libtotem_pg.a gmon.out 
 	rm -f *.da *.bb *.bbg liblogsys.so* liblogsys.a
@@ -145,9 +157,15 @@
 vsf_ykd.o: vsf_ykd.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
+vsf_quorum.o: vsf_quorum.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
 objdb.o: objdb.c
 	$(CC) $(CFLAGS) -c -o $@ $<
 
+testquorum.o: testquorum.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
 coroparse.o: coroparse.c
 	$(CC) $(CFLAGS) -c -o $@ $<
 
diff -Naurd corosync-0.92/exec/objdb.c corosync-trunk/exec/objdb.c
--- corosync-0.92/exec/objdb.c	2008-09-03 12:01:31.000000000 +0200
+++ corosync-trunk/exec/objdb.c	2009-01-23 16:41:06.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2006 MontaVista Software, Inc.
- * Copyright (c) 2007-2008 Red Hat, Inc.
+ * Copyright (c) 2007-2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -59,6 +59,7 @@
 	object_key_change_notify_fn_t key_change_notify_fn;
 	object_create_notify_fn_t object_create_notify_fn;
 	object_destroy_notify_fn_t object_destroy_notify_fn;
+	object_reload_notify_fn_t object_reload_notify_fn;
 	struct list_head tracker_list;
 	struct list_head object_list;
 };
@@ -91,6 +92,9 @@
 
 struct objdb_iface_ver0 objdb_iface;
 struct list_head objdb_trackers_head;
+static pthread_rwlock_t reload_lock;
+static pthread_t lock_thread;
+static pthread_mutex_t meta_lock;
 
 static struct hdb_handle_database object_instance_database = {
 	.handle_count	= 0,
@@ -107,6 +111,38 @@
 };
 
 
+static void objdb_wrlock()
+{
+	pthread_mutex_lock(&meta_lock);
+	pthread_rwlock_wrlock(&reload_lock);
+	lock_thread = pthread_self();
+	pthread_mutex_unlock(&meta_lock);
+}
+
+static void objdb_rdlock()
+{
+	pthread_mutex_lock(&meta_lock);
+	if (lock_thread != pthread_self())
+		pthread_rwlock_rdlock(&reload_lock);
+	pthread_mutex_unlock(&meta_lock);
+}
+
+static void objdb_rdunlock()
+{
+	pthread_mutex_lock(&meta_lock);
+	if (lock_thread != pthread_self())
+		pthread_rwlock_unlock(&reload_lock);
+	pthread_mutex_unlock(&meta_lock);
+}
+
+static void objdb_wrunlock()
+{
+	pthread_mutex_lock(&meta_lock);
+	pthread_rwlock_unlock(&reload_lock);
+	lock_thread = 0;
+	pthread_mutex_unlock(&meta_lock);
+}
+
 static int objdb_init (void)
 {
 	unsigned int handle;
@@ -135,6 +171,8 @@
 	list_init (&instance->child_list);
 	list_init (&instance->track_head);
 	list_init (&objdb_trackers_head);
+	pthread_rwlock_init(&reload_lock, NULL);
+	pthread_mutex_init(&meta_lock, NULL);
 
 	hdb_handle_put (&object_instance_database, handle);
 	return (0);
@@ -293,6 +331,30 @@
 	} while (obj_pt->object_handle != OBJECT_PARENT_HANDLE);
 }
 
+static void object_reload_notification(int startstop, int flush)
+{
+	struct list_head * list;
+	struct object_instance * obj_pt;
+	struct object_tracker * tracker_pt;
+	unsigned int res;
+
+	res = hdb_handle_get (&object_instance_database,
+			      OBJECT_PARENT_HANDLE, (void *)&obj_pt);
+
+	for (list = obj_pt->track_head.next;
+	     list != &obj_pt->track_head; list = list->next) {
+
+		tracker_pt = list_entry (list, struct object_tracker, object_list);
+
+		if (tracker_pt->object_reload_notify_fn != NULL) {
+		        tracker_pt->object_reload_notify_fn(startstop, flush,
+							    tracker_pt->data_pt);
+		}
+	}
+	hdb_handle_put (&object_instance_database, OBJECT_PARENT_HANDLE);
+}
+
+
 /*
  * object db create/destroy/set
  */
@@ -308,6 +370,7 @@
 	int found = 0;
 	int i;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		parent_object_handle, (void *)&parent_instance);
 	if (res != 0) {
@@ -380,7 +443,7 @@
 								object_instance->parent_handle,
 								object_instance->object_name,
 								object_instance->object_name_len);
-
+	objdb_rdunlock();
 	return (0);
 
 error_put_destroy:
@@ -393,6 +456,7 @@
 	hdb_handle_put (&object_instance_database, parent_object_handle);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -403,6 +467,8 @@
 	int res;
 	struct object_instance *object_instance;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&object_instance);
 	if (res != 0) {
@@ -412,9 +478,11 @@
 	object_instance->priv = priv;
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 	return (0);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -432,6 +500,8 @@
 	int i;
 	unsigned int val;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -493,7 +563,7 @@
 	list_add_tail (&object_key->list, &instance->key_head);
 	object_key_changed_notification(object_handle, key_name, key_len,
 								value, value_len, OBJECT_KEY_CREATED);
-
+	objdb_rdunlock();
 	return (0);
 
 error_put_key:
@@ -506,6 +576,7 @@
 	hdb_handle_put (&object_instance_database, object_handle);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -554,9 +625,12 @@
 	struct object_instance *instance;
 	unsigned int res;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
+		objdb_rdunlock();
 		return (res);
 	}
 
@@ -572,6 +646,7 @@
 	free(instance->object_name);
 	free(instance);
 
+	objdb_rdunlock();
 	return (res);
 }
 
@@ -583,6 +658,7 @@
 	struct object_instance *instance;
 	unsigned int res;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -594,9 +670,11 @@
 
 	hdb_handle_put (&object_instance_database, object_handle);
 
+	objdb_rdunlock();
 	return (0);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -608,6 +686,7 @@
 	struct object_instance *instance;
 	unsigned int res;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -619,9 +698,11 @@
 
 	hdb_handle_put (&object_instance_database, object_handle);
 
+	objdb_rdunlock();
 	return (0);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -638,6 +719,7 @@
 	struct object_instance *object_instance;
 	struct object_find_instance *object_find_instance;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&object_instance);
 	if (res != 0) {
@@ -662,6 +744,8 @@
 
 	hdb_handle_put (&object_instance_database, object_handle);
 	hdb_handle_put (&object_find_instance_database, *object_find_handle);
+
+	objdb_rdunlock();
 	return (0);
 
 error_destroy:
@@ -671,6 +755,7 @@
 	hdb_handle_put (&object_instance_database, object_handle);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -684,6 +769,7 @@
 	struct list_head *list;
 	unsigned int found = 0;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_find_instance_database,
 		object_find_handle, (void *)&object_find_instance);
 	if (res != 0) {
@@ -714,16 +800,35 @@
 		*object_handle = object_instance->object_handle;
 		res = 0;
 	}
+	objdb_rdunlock();
 	return (res);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
 static int object_find_destroy (
 	unsigned int object_find_handle)
 {
+	struct object_find_instance *object_find_instance;
+	unsigned int res;
+
+	objdb_rdlock();
+	res = hdb_handle_get (&object_find_instance_database,
+		object_find_handle, (void *)&object_find_instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	hdb_handle_put(&object_find_instance_database, object_find_handle);
+	hdb_handle_destroy(&object_find_instance_database, object_find_handle);
+
+	objdb_rdunlock();
 	return (0);
+
+error_exit:
+	objdb_rdunlock();
+	return (-1);
 }
 
 static int object_key_get (
@@ -739,6 +844,7 @@
 	struct list_head *list;
 	int found = 0;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -766,9 +872,11 @@
 	}
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 	return (res);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -784,6 +892,7 @@
 	struct list_head *list;
 	int found = 0;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -809,9 +918,11 @@
 	}
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 	return (res);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -827,6 +938,7 @@
 	struct list_head *list;
 	int found = 0;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -852,9 +964,11 @@
 	}
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 	return (res);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -872,6 +986,7 @@
 	struct list_head *list;
 	int found = 0;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -906,9 +1021,11 @@
 	if (ret == 0)
 		object_key_changed_notification(object_handle, key_name, key_len,
 										value, value_len, OBJECT_KEY_DELETED);
+	objdb_rdunlock();
 	return (ret);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -928,6 +1045,8 @@
 	struct list_head *list;
 	int found = 0;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&instance);
 	if (res != 0) {
@@ -950,6 +1069,7 @@
 
 	if (found) {
 		int i;
+		int found_validator = 0;
 
 		/*
 		 * Do validation check if validation is configured for the parent object
@@ -962,7 +1082,7 @@
 					     instance->object_key_valid_list[i].key_name,
 					     key_len) == 0)) {
 
-					found = 1;
+					found_validator = 1;
 					break;
 				}
 			}
@@ -970,7 +1090,7 @@
 			/*
 			 * Item not found in validation list
 			 */
-			if (found == 0) {
+			if (found_validator == 0) {
 				goto error_put;
 			} else {
 				if (instance->object_key_valid_list[i].validate_callback) {
@@ -983,7 +1103,7 @@
 			}
 		}
 
-		if (new_value_len <= object_key->value_len) {
+		if (new_value_len != object_key->value_len) {
 			void *replacement_value;
 			replacement_value = malloc(new_value_len);
 			if (!replacement_value)
@@ -1003,11 +1123,13 @@
 	if (ret == 0)
 		object_key_changed_notification(object_handle, key_name, key_len,
 										new_value, new_value_len, OBJECT_KEY_REPLACED);
+	objdb_rdunlock();
 	return (ret);
 
 error_put:
 	hdb_handle_put (&object_instance_database, object_handle);
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -1018,6 +1140,7 @@
 	int res;
 	struct object_instance *object_instance;
 
+	objdb_rdunlock();
 	res = hdb_handle_get (&object_instance_database,
 		object_handle, (void *)&object_instance);
 	if (res != 0) {
@@ -1027,9 +1150,11 @@
 	*priv = object_instance->priv;
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 	return (0);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -1092,6 +1217,8 @@
 	unsigned int res;
 	struct object_instance *instance;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 			      object_handle, (void *)&instance);
 	if (res != 0) {
@@ -1100,9 +1227,11 @@
 	instance->iter_key_list = &instance->key_head;
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 	return (0);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -1119,6 +1248,8 @@
 	struct list_head *list;
 	unsigned int found = 0;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 		parent_object_handle, (void *)&instance);
 	if (res != 0) {
@@ -1145,9 +1276,11 @@
 	}
 
 	hdb_handle_put (&object_instance_database, parent_object_handle);
+	objdb_rdunlock();
 	return (res);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -1165,6 +1298,8 @@
 	struct list_head *list;
 	unsigned int found = 0;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 		parent_object_handle, (void *)&instance);
 	if (res != 0) {
@@ -1197,9 +1332,11 @@
 	}
 
 	hdb_handle_put (&object_instance_database, parent_object_handle);
+	objdb_rdunlock();
 	return (res);
 
 error_exit:
+	objdb_rdunlock();
 	return (-1);
 }
 
@@ -1210,9 +1347,12 @@
 	struct object_instance *instance;
 	unsigned int res;
 
+	objdb_rdlock();
+
 	res = hdb_handle_get (&object_instance_database,
 			      object_handle, (void *)&instance);
 	if (res != 0) {
+		objdb_rdunlock();
 		return (res);
 	}
 
@@ -1222,6 +1362,7 @@
 		*parent_handle = instance->parent_handle;
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 
 	return (0);
 }
@@ -1233,9 +1374,11 @@
 	struct object_instance *instance;
 	unsigned int res;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 			      object_handle, (void *)&instance);
 	if (res != 0) {
+		objdb_rdunlock();
 		return (res);
 	}
 
@@ -1243,6 +1386,7 @@
 	*object_name_len = instance->object_name_len;
 
 	hdb_handle_put (&object_instance_database, object_handle);
+	objdb_rdunlock();
 
 	return (0);
 }
@@ -1253,6 +1397,7 @@
 							  object_key_change_notify_fn_t key_change_notify_fn,
 							  object_create_notify_fn_t object_create_notify_fn,
 							  object_destroy_notify_fn_t object_destroy_notify_fn,
+			                                  object_reload_notify_fn_t object_reload_notify_fn,
 							  void * priv_data_pt)
 {
 	struct object_instance *instance;
@@ -1271,6 +1416,7 @@
 	tracker_pt->key_change_notify_fn = key_change_notify_fn;
 	tracker_pt->object_create_notify_fn = object_create_notify_fn;
 	tracker_pt->object_destroy_notify_fn = object_destroy_notify_fn;
+	tracker_pt->object_reload_notify_fn = object_reload_notify_fn;
 	tracker_pt->data_pt = priv_data_pt;
 
 	list_init(&tracker_pt->object_list);
@@ -1287,6 +1433,7 @@
 static void object_track_stop(object_key_change_notify_fn_t key_change_notify_fn,
 							  object_create_notify_fn_t object_create_notify_fn,
 							  object_destroy_notify_fn_t object_destroy_notify_fn,
+			                                  object_reload_notify_fn_t object_reload_notify_fn,
 							  void * priv_data_pt)
 {
 	struct object_instance *instance;
@@ -1305,6 +1452,7 @@
 		if (tracker_pt && (tracker_pt->data_pt == priv_data_pt) &&
 			(tracker_pt->object_create_notify_fn == object_create_notify_fn) &&
 			(tracker_pt->object_destroy_notify_fn == object_destroy_notify_fn) &&
+		        (tracker_pt->object_reload_notify_fn == object_reload_notify_fn) &&
 			(tracker_pt->key_change_notify_fn == key_change_notify_fn)) {
 
 			/* get the object & take this tracker off of it's list. */
@@ -1337,9 +1485,11 @@
 	struct object_instance *instance;
 	unsigned int res;
 
+	objdb_rdlock();
 	res = hdb_handle_get (&object_instance_database,
 			      object_handle, (void *)&instance);
 	if (res != 0) {
+		objdb_rdunlock();
 		return (res);
 	}
 
@@ -1347,6 +1497,7 @@
 
 	hdb_handle_put (&object_instance_database, object_handle);
 
+	objdb_rdunlock();
 	return (res);
 }
 
@@ -1358,13 +1509,19 @@
 	int res;
 
 	main_get_config_modules(&modules, &num_modules);
+
+	objdb_wrlock();
+
 	for (i=0; i<num_modules; i++) {
 		if (modules[i]->config_writeconfig) {
 			res = modules[i]->config_writeconfig(&objdb_iface, error_string);
-			if (res)
+			if (res) {
+				objdb_wrunlock();
 				return res;
+			}
 		}
 	}
+	objdb_wrunlock();
 	return 0;
 }
 
@@ -1376,14 +1533,22 @@
 	int res;
 
 	main_get_config_modules(&modules, &num_modules);
+	object_reload_notification(OBJDB_RELOAD_NOTIFY_START, flush);
+
+	objdb_wrlock();
 
 	for (i=0; i<num_modules; i++) {
 		if (modules[i]->config_reloadconfig) {
 			res = modules[i]->config_reloadconfig(&objdb_iface, flush, error_string);
-			if (res)
+			if (res) {
+				object_reload_notification(OBJDB_RELOAD_NOTIFY_FAILED, flush);
+				objdb_wrunlock();
 				return res;
+			}
 		}
 	}
+	objdb_wrunlock();
+	object_reload_notification(OBJDB_RELOAD_NOTIFY_END, flush);
 	return 0;
 }
 
diff -Naurd corosync-0.92/exec/quorum.c corosync-trunk/exec/quorum.c
--- corosync-0.92/exec/quorum.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/exec/quorum.c	2008-12-09 14:48:47.000000000 +0100
@@ -0,0 +1,115 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <corosync/corotypes.h>
+#include <corosync/swab.h>
+#include <corosync/totem/totempg.h>
+#include <corosync/totem/totem.h>
+#include <corosync/lcr/lcr_ifact.h>
+#include <corosync/engine/logsys.h>
+
+#include "quorum.h"
+#include "main.h"
+#include "sync.h"
+#include "vsf.h"
+
+LOGSYS_DECLARE_SUBSYS ("QUORUM", LOG_INFO);
+
+
+static struct quorum_callin_functions *corosync_quorum_fns = NULL;
+
+int corosync_quorum_is_quorate (void)
+{
+	if (corosync_quorum_fns) {
+		return corosync_quorum_fns->quorate();
+	}
+	else {
+		return 1;
+	}
+}
+
+int corosync_quorum_register_callback (quorum_callback_fn_t fn, void *context)
+{
+	if (corosync_quorum_fns) {
+		return corosync_quorum_fns->register_callback(fn, context);
+	}
+	else {
+		return 0;
+	}
+}
+
+int corosync_quorum_unregister_callback (quorum_callback_fn_t fn, void *context)
+{
+	if (corosync_quorum_fns) {
+		return corosync_quorum_fns->unregister_callback(fn, context);
+	}
+	else {
+		return 0;
+	}
+}
+
+int corosync_quorum_initialize (struct quorum_callin_functions *fns,
+				sync_callback_fn_t *sync_callback_fn)
+{
+	if (corosync_quorum_fns)
+		return -1;
+
+	corosync_quorum_fns = fns;
+	*sync_callback_fn = sync_primary_callback_fn;
+	return 0;
+}
+
+int quorum_none(void)
+{
+	if (corosync_quorum_fns)
+		return 0;
+	else
+		return 1;
+}
diff -Naurd corosync-0.92/exec/quorum.h corosync-trunk/exec/quorum.h
--- corosync-0.92/exec/quorum.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/exec/quorum.h	2008-12-08 16:55:41.000000000 +0100
@@ -0,0 +1,68 @@
+/*
+ * 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 Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef QUORUM_H_DEFINED
+#define QUORUM_H_DEFINED
+
+struct memb_ring_id;
+
+typedef void (*quorum_callback_fn_t) (int quorate, void *context);
+
+typedef void (*sync_callback_fn_t) (
+	unsigned int *view_list,
+	int view_list_entries,
+	int primary_designated,
+	struct memb_ring_id *ring_id);
+
+struct quorum_callin_functions
+{
+	int (*quorate) (void);
+	int (*register_callback) (quorum_callback_fn_t, void*);
+	int (*unregister_callback) (quorum_callback_fn_t, void*);
+};
+
+extern int corosync_quorum_is_quorate (void);
+
+extern int corosync_quorum_register_callback (quorum_callback_fn_t fn, void *context);
+
+extern int corosync_quorum_unregister_callback (quorum_callback_fn_t fn, void *context);
+
+extern int corosync_quorum_initialize (struct quorum_callin_functions *fns,
+				       sync_callback_fn_t *sync_callback_fn);
+
+
+extern int quorum_none(void);
+
+
+#endif /* QUORUM_H_DEFINED */
diff -Naurd corosync-0.92/exec/service.c corosync-trunk/exec/service.c
--- corosync-0.92/exec/service.c	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/exec/service.c	2009-01-27 09:59:14.000000000 +0100
@@ -78,6 +78,10 @@
 		.name			 = "corosync_confdb",
 		.ver			 = 0,
 	},
+	{
+		.name			 = "corosync_pload",
+		.ver			 = 0,
+	}
 };
 
 struct corosync_service_engine *ais_service[SERVICE_HANDLER_MAXIMUM_COUNT];
diff -Naurd corosync-0.92/exec/sync.c corosync-trunk/exec/sync.c
--- corosync-0.92/exec/sync.c	2008-09-17 21:04:19.000000000 +0200
+++ corosync-trunk/exec/sync.c	2008-12-08 16:55:41.000000000 +0100
@@ -49,16 +49,17 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/swab.h>
 #include <corosync/totem/totempg.h>
 #include <corosync/totem/totem.h>
 #include <corosync/lcr/lcr_ifact.h>
 #include <corosync/engine/logsys.h>
+#include "quorum.h"
 
 #include "main.h"
 #include "sync.h"
-#include "vsf.h"
+
 
 LOGSYS_DECLARE_SUBSYS ("SYNC", LOG_INFO);
 
@@ -72,8 +73,6 @@
 
 static struct memb_ring_id *sync_ring_id;
 
-static int vsf_none = 0;
-
 static int (*sync_callbacks_retrieve) (int sync_id, struct sync_callbacks *callack);
 
 static struct sync_callbacks sync_callbacks;
@@ -93,8 +92,6 @@
 
 static struct barrier_data barrier_data_process[PROCESSOR_COUNT_MAX];
 
-static struct corosync_vsf_iface_ver0 *vsf_iface;
-
 static int sync_barrier_send (struct memb_ring_id *ring_id);
 
 static int sync_start_process (enum totem_callback_token_type type, void *data);
@@ -116,12 +113,6 @@
 	unsigned int *joined_list, int joined_list_entries,
 	struct memb_ring_id *ring_id);
 
-static void sync_primary_callback_fn (
-	unsigned int *view_list,
-	int view_list_entries,
-	int primary_designated,
-	struct memb_ring_id *ring_id);
-
 static struct totempg_group sync_group = {
     .group      = "sync",
     .group_len  = 4
@@ -266,13 +257,10 @@
 
 int sync_register (
 	int (*callbacks_retrieve) (int sync_id, struct sync_callbacks *callack),
-	void (*synchronization_completed) (void),
-	char *vsf_type)
+	void (*synchronization_completed) (void))
+
 {
 	unsigned int res;
-	unsigned int vsf_handle;
-	void *vsf_iface_p;
-	char corosync_vsf_type[1024];
 
 	res = totempg_groups_initialize (
 		&sync_group_handle,
@@ -292,42 +280,13 @@
 		log_printf (LOG_LEVEL_ERROR, "Couldn't join group.\n");
 		return (-1);
 	}
-		
-	if (strcmp (vsf_type, "none") == 0) {
-		log_printf (LOG_LEVEL_NOTICE,
-			"Not using a virtual synchrony filter.\n");
-		vsf_none = 1;
-	} else {
-		vsf_none = 0;
-
-		sprintf (corosync_vsf_type, "corosync_vsf_%s", vsf_type);
-		res = lcr_ifact_reference (
-			&vsf_handle,
-			corosync_vsf_type,
-			0,
-			&vsf_iface_p,
-			0);
-
-		if (res == -1) {
-			log_printf (LOG_LEVEL_NOTICE,
-				"Couldn't load virtual synchrony filter %s\n",
-				vsf_type);
-			return (-1);
-		}
-
-		log_printf (LOG_LEVEL_NOTICE,
-			"Using virtual synchrony filter %s\n", corosync_vsf_type);
-
-		vsf_iface = (struct corosync_vsf_iface_ver0 *)vsf_iface_p;
-		vsf_iface->init (sync_primary_callback_fn);
-	}
 
 	sync_callbacks_retrieve = callbacks_retrieve;
 	sync_synchronization_completed = synchronization_completed;
 	return (0);
 }
 
-static void sync_primary_callback_fn (
+void sync_primary_callback_fn (
 	unsigned int *view_list,
 	int view_list_entries,
 	int primary_designated,
@@ -335,13 +294,6 @@
 {
 	int i;
 
-	if (primary_designated) {
-		log_printf (LOG_LEVEL_NOTICE, "This node is within the primary component and will provide service.\n");
-	} else {
-		log_printf (LOG_LEVEL_NOTICE, "This node is within the non-primary component and will NOT provide any services.\n");
-		return;
-	}
-
 	/*
 	 * Execute configuration change for synchronization service
 	 */
@@ -521,7 +473,7 @@
 	 * If no virtual synchrony filter configured, then start
 	 * synchronization process
 	 */
-	if (vsf_none == 1) {
+	if (quorum_none() == 1) {
 		sync_primary_callback_fn (
 			member_list,
 			member_list_entries,
@@ -546,7 +498,7 @@
 	struct iovec iovec[2];
 	int name_len;
 
-	ENTER("'%s'", name);
+	ENTER();
 
 	name_len = strlen (name) + 1;
 	msg.header.size = sizeof (msg) + name_len;
@@ -589,15 +541,6 @@
 	return (sync_processing);
 }
 
-int sync_primary_designated (void)
-{
-	if (vsf_none == 1) {
-		return (1);
-	} else {
-		return (vsf_iface->primary());
-	}
-}
-
 /**
  * Execute synchronization upon request for the named service
  * @param name
@@ -608,7 +551,7 @@
 {
 	assert (name != NULL);
 
-	ENTER("'%s'", name);
+	ENTER();
 
 	if (sync_processing) {
 		return -1;
@@ -618,7 +561,7 @@
 		TOTEM_CALLBACK_TOKEN_SENT, 0, /* don't delete after callback */
 		sync_request_send, name);
 
-	LEAVE("");
+	LEAVE();
 
 	return 0;
 }
diff -Naurd corosync-0.92/exec/sync.h corosync-trunk/exec/sync.h
--- corosync-0.92/exec/sync.h	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/sync.h	2008-12-08 16:55:41.000000000 +0100
@@ -47,10 +47,10 @@
 	char *name;
 };
 
+struct corosync_api_v1;
 int sync_register (
 	int (*sync_callbacks_retrieve) (int sync_id, struct sync_callbacks *callbacks),
-	void (*synchronization_completed) (void),
-	char *vsf_type);
+	void (*synchronization_completed) (void));
 
 int sync_in_process (void);
 
@@ -64,4 +64,11 @@
  */
 extern int sync_request (char *name);
 
+extern void sync_primary_callback_fn (
+	unsigned int *view_list,
+	int view_list_entries,
+	int primary_designated,
+	struct memb_ring_id *ring_id);
+
+
 #endif /* SYNC_H_DEFINED */
diff -Naurd corosync-0.92/exec/timer.c corosync-trunk/exec/timer.c
--- corosync-0.92/exec/timer.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/exec/timer.c	2008-11-06 22:49:07.000000000 +0100
@@ -56,7 +56,7 @@
 #include <time.h>
 
 #include <corosync/swab.h>
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/list.h>
 #include <corosync/queue.h>
 #include <corosync/lcr/lcr_ifact.h>
diff -Naurd corosync-0.92/exec/totemconfig.c corosync-trunk/exec/totemconfig.c
--- corosync-0.92/exec/totemconfig.c	2008-08-20 02:57:40.000000000 +0200
+++ corosync-trunk/exec/totemconfig.c	2008-12-12 12:27:27.000000000 +0100
@@ -76,6 +76,13 @@
 #define RRP_PROBLEM_COUNT_THRESHOLD_MIN		5
 
 static char error_string_response[512];
+static struct objdb_iface_ver0 *global_objdb;
+
+static void add_totem_config_notification(
+	struct objdb_iface_ver0 *objdb,
+	struct totem_config *totem_config,
+	unsigned int totem_object_handle);
+
 
 /* These just makes the code below a little neater */
 static inline int objdb_get_string (
@@ -163,6 +170,50 @@
 	return (0);
 }
 
+static void totem_volatile_config_read (
+	struct objdb_iface_ver0 *objdb,
+	struct totem_config *totem_config,
+	unsigned int object_totem_handle)
+{
+	objdb_get_int (objdb,object_totem_handle, "token", &totem_config->token_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "token_retransmit", &totem_config->token_retransmit_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "hold", &totem_config->token_hold_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "token_retransmits_before_loss_const", &totem_config->token_retransmits_before_loss_const);
+
+	objdb_get_int (objdb,object_totem_handle, "join", &totem_config->join_timeout);
+	objdb_get_int (objdb,object_totem_handle, "send_join", &totem_config->send_join_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "consensus", &totem_config->consensus_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "merge", &totem_config->merge_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "downcheck", &totem_config->downcheck_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "fail_recv_const", &totem_config->fail_to_recv_const);
+
+	objdb_get_int (objdb,object_totem_handle, "seqno_unchanged_const", &totem_config->seqno_unchanged_const);
+
+	objdb_get_int (objdb,object_totem_handle, "rrp_token_expired_timeout", &totem_config->rrp_token_expired_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "rrp_problem_count_timeout", &totem_config->rrp_problem_count_timeout);
+
+	objdb_get_int (objdb,object_totem_handle, "rrp_problem_count_threshold", &totem_config->rrp_problem_count_threshold);
+
+	objdb_get_int (objdb,object_totem_handle, "heartbeat_failures_allowed", &totem_config->heartbeat_failures_allowed);
+
+	objdb_get_int (objdb,object_totem_handle, "max_network_delay", &totem_config->max_network_delay);
+
+	objdb_get_int (objdb,object_totem_handle, "window_size", &totem_config->window_size);
+	objdb_get_string (objdb, object_totem_handle, "vsftype", &totem_config->vsf_type);
+
+	objdb_get_int (objdb,object_totem_handle, "max_messages", &totem_config->max_messages);
+
+}
+
+
 extern int totem_config_read (
 	struct objdb_iface_ver0 *objdb,
 	struct totem_config *totem_config,
@@ -222,41 +273,10 @@
 
 	objdb_get_int (objdb,object_totem_handle, "netmtu", &totem_config->net_mtu);
 
-	objdb_get_int (objdb,object_totem_handle, "token", &totem_config->token_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "token_retransmit", &totem_config->token_retransmit_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "hold", &totem_config->token_hold_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "token_retransmits_before_loss_const", &totem_config->token_retransmits_before_loss_const);
-
-	objdb_get_int (objdb,object_totem_handle, "join", &totem_config->join_timeout);
-	objdb_get_int (objdb,object_totem_handle, "send_join", &totem_config->send_join_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "consensus", &totem_config->consensus_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "merge", &totem_config->merge_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "downcheck", &totem_config->downcheck_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "fail_recv_const", &totem_config->fail_to_recv_const);
-
-	objdb_get_int (objdb,object_totem_handle, "seqno_unchanged_const", &totem_config->seqno_unchanged_const);
-
-	objdb_get_int (objdb,object_totem_handle, "rrp_token_expired_timeout", &totem_config->rrp_token_expired_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "rrp_problem_count_timeout", &totem_config->rrp_problem_count_timeout);
-
-	objdb_get_int (objdb,object_totem_handle, "rrp_problem_count_threshold", &totem_config->rrp_problem_count_threshold);
-
-	objdb_get_int (objdb,object_totem_handle, "heartbeat_failures_allowed", &totem_config->heartbeat_failures_allowed);
-
-	objdb_get_int (objdb,object_totem_handle, "max_network_delay", &totem_config->max_network_delay);
-
-	objdb_get_int (objdb,object_totem_handle, "window_size", &totem_config->window_size);
-	objdb_get_string (objdb, object_totem_handle, "vsftype", &totem_config->vsf_type);
-
-	objdb_get_int (objdb,object_totem_handle, "max_messages", &totem_config->max_messages);
+	/*
+	 * Get things that might change in the future
+	 */
+	totem_volatile_config_read (objdb, totem_config, object_totem_handle);
 
 	objdb->object_find_create (
 		object_totem_handle,
@@ -297,6 +317,8 @@
 
 	objdb->object_find_destroy (object_find_interface_handle);
 
+	add_totem_config_notification(objdb, totem_config, object_totem_handle);
+
 	return 0;
 }
 
@@ -323,7 +345,7 @@
 			error_reason = "No multicast address specified";
 			goto parse_error;
 		}
-	
+
 		if (totem_config->interfaces[i].ip_port == 0) {
 			error_reason = "No multicast port specified";
 			goto parse_error;
@@ -331,7 +353,7 @@
 
 		if (totem_config->interfaces[i].mcast_addr.family == AF_INET6 &&
 			totem_config->node_id == 0) {
-	
+
 			error_reason = "An IPV6 network requires that a node ID be specified.";
 			goto parse_error;
 		}
@@ -498,7 +520,7 @@
 		totem_config->rrp_token_expired_timeout =
 			totem_config->token_retransmit_timeout;
 	}
-		
+
 	if (totem_config->rrp_token_expired_timeout < MINIMUM_TIMEOUT) {
 		sprintf (local_error_reason, "The RRP token expired timeout parameter (%d ms) may not be less then (%d ms).",
 			totem_config->rrp_token_expired_timeout, MINIMUM_TIMEOUT);
@@ -658,3 +680,92 @@
 	return (-1);
 
 }
+
+static void totem_key_change_notify(object_change_type_t change_type,
+			      unsigned int parent_object_handle,
+			      unsigned int object_handle,
+			      void *object_name_pt, int object_name_len,
+			      void *key_name_pt, int key_len,
+			      void *key_value_pt, int key_value_len,
+			      void *priv_data_pt)
+{
+	struct totem_config *totem_config = priv_data_pt;
+
+	if (memcmp(object_name_pt, "totem", object_name_len) == 0)
+		totem_volatile_config_read(global_objdb,
+					   totem_config,
+					   object_handle); // CHECK
+}
+
+static void totem_objdb_reload_notify(objdb_reload_notify_type_t type, int flush,
+				      void *priv_data_pt)
+{
+	struct totem_config *totem_config = priv_data_pt;
+	unsigned int totem_object_handle;
+
+	/*
+	 * A new totem {} key might exist, cancel the
+	 * existing notification at the start of reload,
+	 * and start a new one on the new object when
+	 * it's all settled.
+	 */
+
+	if (type == OBJDB_RELOAD_NOTIFY_START) {
+		global_objdb->object_track_stop(
+			totem_key_change_notify,
+			NULL,
+			NULL,
+			NULL,
+			NULL);
+	}
+
+	if (type == OBJDB_RELOAD_NOTIFY_END ||
+	    type == OBJDB_RELOAD_NOTIFY_FAILED) {
+
+
+		if (!totem_handle_find(global_objdb,
+				      &totem_object_handle)) {
+			add_totem_config_notification(global_objdb, totem_config, totem_object_handle);
+
+			/*
+			 * Reload the configuration
+			 */
+			totem_volatile_config_read(global_objdb,
+						   totem_config,
+						   totem_object_handle);
+
+		}
+		else {
+			log_printf(LOG_LEVEL_ERROR, "totem objdb tracking stopped, cannot find totem{} handle on objdb\n");
+		}
+	}
+}
+
+
+static void add_totem_config_notification(
+	struct objdb_iface_ver0 *objdb,
+	struct totem_config *totem_config,
+	unsigned int totem_object_handle)
+{
+
+	global_objdb = objdb;
+	objdb->object_track_start(totem_object_handle,
+				  1,
+				  totem_key_change_notify,
+				  NULL, // object_create_notify,
+				  NULL, // object_destroy_notify,
+				  NULL, // object_reload_notify
+				  totem_config); // priv_data
+
+	/*
+	 * Reload notify must be on the parent object
+	 */
+	objdb->object_track_start(OBJECT_PARENT_HANDLE,
+				  1,
+				  NULL, // key_change_notify,
+				  NULL, // object_create_notify,
+				  NULL, // object_destroy_notify,
+				  totem_objdb_reload_notify, // object_reload_notify
+				  totem_config); // priv_data
+
+}
diff -Naurd corosync-0.92/exec/totemconfig.h corosync-trunk/exec/totemconfig.h
--- corosync-0.92/exec/totemconfig.h	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/totemconfig.h	2008-11-06 22:49:07.000000000 +0100
@@ -36,7 +36,7 @@
 #define TOTEMCONFIG_H_DEFINED
 
 #include <netinet/in.h>
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/list.h>
 #include <corosync/totem/coropoll.h>
 #include <corosync/totem/totempg.h>
diff -Naurd corosync-0.92/exec/totemip.c corosync-trunk/exec/totemip.c
--- corosync-0.92/exec/totemip.c	2008-09-16 17:35:09.000000000 +0200
+++ corosync-trunk/exec/totemip.c	2009-01-26 21:46:45.000000000 +0100
@@ -226,7 +226,7 @@
 		sin->sin_len = sizeof(struct sockaddr_in);
 #endif
 		sin->sin_family = ip_addr->family;
-		sin->sin_port = port;
+		sin->sin_port = ntohs(port);
 		memcpy(&sin->sin_addr, ip_addr->addr, sizeof(struct in_addr));
 		*addrlen = sizeof(struct sockaddr_in);
 		ret = 0;
@@ -240,7 +240,7 @@
 		sin->sin6_len = sizeof(struct sockaddr_in6);
 #endif
 		sin->sin6_family = ip_addr->family;
-		sin->sin6_port = port;
+		sin->sin6_port = ntohs(port);
 		sin->sin6_scope_id = 2;
 		memcpy(&sin->sin6_addr, ip_addr->addr, sizeof(struct in6_addr));
 
@@ -376,7 +376,8 @@
 int totemip_iface_check(struct totem_ip_address *bindnet,
 			struct totem_ip_address *boundto,
 			int *interface_up,
-			int *interface_num)
+			int *interface_num,
+			int mask_high_bit)
 {
 	int fd;
 	struct {
@@ -472,7 +473,7 @@
 					memcpy(&network, RTA_DATA(tb[IFA_BROADCAST]), sizeof(uint32_t));
 					memcpy(&addr, bindnet->addr, sizeof(uint32_t));
 
-					if (addr == (network & netmask)) {
+					if ((addr & netmask) == (network & netmask)) {
 						memcpy(ipaddr.addr, RTA_DATA(tb[IFA_ADDRESS]), TOTEMIP_ADDRLEN);
 						found_if = 1;
 					}
@@ -514,6 +515,18 @@
 		}
 	}
 finished:
+	/*
+	 * Mask 32nd bit off to workaround bugs in other poeples code
+	 * if configuration requests it.
+	 */
+	if (ipaddr.family == AF_INET && ipaddr.nodeid == 0) {
+                unsigned int nodeid = 0;
+                memcpy (&nodeid, ipaddr.addr, sizeof (int));
+		if (mask_high_bit) {
+                        nodeid &= 0x7FFFFFFF;
+		}
+                ipaddr.nodeid = nodeid;
+        }
 	totemip_copy (boundto, &ipaddr);
 	close(fd);
 	return 0;
diff -Naurd corosync-0.92/exec/totemmrp.c corosync-trunk/exec/totemmrp.c
--- corosync-0.92/exec/totemmrp.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/totemmrp.c	2008-12-01 19:44:55.000000000 +0100
@@ -192,7 +192,7 @@
 	return (res);
 }
 
-int totemmrp_my_nodeid_get (void)
+unsigned int totemmrp_my_nodeid_get (void)
 {
 	return (totemsrp_my_nodeid_get (totemsrp_handle_in));
 }
diff -Naurd corosync-0.92/exec/totemnet.c corosync-trunk/exec/totemnet.c
--- corosync-0.92/exec/totemnet.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/totemnet.c	2009-01-25 22:15:25.000000000 +0100
@@ -137,7 +137,11 @@
 
 	int totemnet_log_level_debug;
 
-	void (*totemnet_log_printf) (char *file, int line, int level, char *format, ...) __attribute__((format(printf, 4, 5)));
+	int totemnet_subsys_id;
+
+	void (*totemnet_log_printf) (int subsys, char *function, char *file,
+		int line, unsigned int level, char *format,
+		...)__attribute__((format(printf, 6, 7)));
 
 	totemnet_handle handle;
 
@@ -226,8 +230,12 @@
 	instance->my_memb_entries = 1;
 }
 
-#define log_printf(level, format, args...) \
-    instance->totemnet_log_printf (__FILE__, __LINE__, level, format, ##args)
+#define log_printf(level, format, args...)				\
+do {									\
+        instance->totemnet_log_printf (instance->totemnet_subsys_id,	\
+                (char *)__FUNCTION__, __FILE__, __LINE__, level,	\
+                format, ##args);					\
+} while (0);
 
 static int authenticate_and_decrypt (
 	struct totemnet_instance *instance,
@@ -691,18 +699,9 @@
 	int res;
 
 	res = totemip_iface_check (bindnet, bound_to,
-		interface_up, interface_num);
+		interface_up, interface_num,
++               0); // TODO andrew can address this instance->totem_config->clear_node_high_bit);
 
-	/*
-	 * If the desired binding is to an IPV4 network and nodeid isn't
-	 * specified, retrieve the node id from this_ip network address
-	 *
-	 * IPV6 networks must have a node ID specified since the node id
-	 * field is only 32 bits.
-	 */
-	if (bound_to->family == AF_INET && bound_to->nodeid == 0) {
-		memcpy (&bound_to->nodeid, bound_to->addr, sizeof (int));
-	}
 
 	return (res);
 }
@@ -1192,6 +1191,7 @@
 	instance->totemnet_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
 	instance->totemnet_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
 	instance->totemnet_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
+	instance->totemnet_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
 	instance->totemnet_log_printf = totem_config->totem_logging_configuration.log_printf;
 
 	/*
diff -Naurd corosync-0.92/exec/totempg.c corosync-trunk/exec/totempg.c
--- corosync-0.92/exec/totempg.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/totempg.c	2009-01-25 22:25:25.000000000 +0100
@@ -153,7 +153,10 @@
 static int totempg_log_level_warning;
 static int totempg_log_level_notice;
 static int totempg_log_level_debug;
-static void (*totempg_log_printf) (char *file, int line, int level, char *format, ...) __attribute__((format(printf, 4, 5))) = NULL;
+static int totempg_subsys_id;
+static void (*totempg_log_printf) (int subsys_id, char *function, char *file,
+        int line, unsigned int level, char *format,
+        ...) __attribute__((format(printf, 6, 7)));
 
 struct totem_config *totempg_totem_config;
 
@@ -165,6 +168,13 @@
 	struct list_head list;
 };
 
+enum throw_away_mode_t {
+	THROW_AWAY_INACTIVE,
+	THROW_AWAY_ACTIVE
+};
+
+static enum throw_away_mode_t throw_away_mode = THROW_AWAY_INACTIVE;
+
 DECLARE_LIST_INIT(assembly_list_inuse);
 
 DECLARE_LIST_INIT(assembly_list_free);
@@ -225,8 +235,11 @@
 
 static pthread_mutex_t mcast_msg_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-#define log_printf(level, format, args...) \
-    totempg_log_printf (__FILE__, __LINE__, level, format, ##args)
+#define log_printf(level, format, args...)				\
+do {									\
+        totempg_log_printf (totempg_subsys_id, (char *)__FUNCTION__,	\
+		__FILE__, __LINE__, level, format, ##args);		\
+} while (0);
 
 static struct assembly *assembly_ref (unsigned int nodeid)
 {
@@ -558,43 +571,32 @@
 	 * the continued message.
 	 */
 	start = 0;
-	if (continuation) {
 
-		if (continuation != assembly->last_frag_num) {
-			log_printf (totempg_log_level_error,
-				"Message continuation doesn't match previous frag e: %u - a: %u\n",
-				assembly->last_frag_num, continuation);
-			continuation = 0;
-		}
+	if (throw_away_mode == THROW_AWAY_ACTIVE) {
+		 /* Throw away the first msg block */
+		if (mcast->fragmented == 0 || mcast->fragmented == 1) {
+			throw_away_mode = THROW_AWAY_INACTIVE;
 
-		if ((assembly->index == 0) ||
-							(!continuation && assembly->index)) {
-			log_printf (totempg_log_level_error,
-				"Throwing away broken message: continuation %u, index %u\n",
-				continuation, assembly->index);
-			continuation = 0;
-		}
-		
-		/* 
-		 * we decided to throw away the first continued message
-		 * in this buffer, if continuation was set to zero.
-		 */
-		if (!continuation) {
 			assembly->index += msg_lens[0];
 			iov_delv.iov_base = &assembly->data[assembly->index];
 			iov_delv.iov_len = msg_lens[1];
 			start = 1;
 		}
-			
-	}
-
-	for  (i = start; i < msg_count; i++) {
-		app_deliver_fn(nodeid, &iov_delv, 1,
-			endian_conversion_required);
-		assembly->index += msg_lens[i];
-		iov_delv.iov_base = &assembly->data[assembly->index];
-		if (i < (msg_count - 1)) {
-			iov_delv.iov_len = msg_lens[i + 1];
+	} else 
+	if (throw_away_mode == THROW_AWAY_INACTIVE) {
+		if (continuation == assembly->last_frag_num) {
+			assembly->last_frag_num = mcast->fragmented;
+			for  (i = start; i < msg_count; i++) {
+				app_deliver_fn(nodeid, &iov_delv, 1,
+					endian_conversion_required);
+				assembly->index += msg_lens[i];
+				iov_delv.iov_base = &assembly->data[assembly->index];
+				if (i < (msg_count - 1)) {
+					iov_delv.iov_len = msg_lens[i + 1];
+				}
+			}
+		} else {
+			throw_away_mode = THROW_AWAY_ACTIVE;
 		}
 	}
 
@@ -609,7 +611,6 @@
 		/*
 		 * Message is fragmented, keep around assembly list
 		 */
-		assembly->last_frag_num = mcast->fragmented;
 		if (mcast->msg_count > 1) {
 			memmove (&assembly->data[0],
 				&assembly->data[assembly->index],
@@ -686,6 +687,7 @@
 	totempg_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
 	totempg_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
 	totempg_log_printf = totem_config->totem_logging_configuration.log_printf;
+	totempg_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
 
 	fragmentation_data = malloc (TOTEMPG_PACKET_SIZE);
 	if (fragmentation_data == 0) {
@@ -721,14 +723,16 @@
  * Multicast a message
  */
 static int mcast_msg (
-	struct iovec *iovec,
+	struct iovec *iovec_in,
 	int iov_len,
 	int guarantee)
 {
 	int res = 0;
 	struct totempg_mcast mcast;
 	struct iovec iovecs[3];
+	struct iovec iovec[64];
 	int i;
+	int dest, src;
 	int max_packet_size = 0;
 	int copy_len = 0; 
 	int copy_base = 0;
@@ -737,6 +741,18 @@
 	pthread_mutex_lock (&mcast_msg_mutex);
 	totemmrp_new_msg_signal ();
 
+	/*
+	 * Remove zero length iovectors from the list
+	 */
+	assert (iov_len < 64);
+	for (dest = 0, src = 0; src < iov_len; src++) {
+		if (iovec_in[src].iov_len) {
+			memcpy (&iovec[dest++], &iovec_in[src],
+				sizeof (struct iovec));
+		}
+	}
+	iov_len = dest;
+
 	max_packet_size = TOTEMPG_PACKET_SIZE -
 		(sizeof (unsigned short) * (mcast_packed_msg_count + 1));
 
@@ -774,6 +790,7 @@
 				iovec[i].iov_base + copy_base, copy_len);
 			fragment_size += copy_len;
 			mcast_packed_msg_lens[mcast_packed_msg_count] += copy_len;
+			next_fragment = 1;
 			copy_len = 0;
 			copy_base = 0;
 			i++;
@@ -1243,7 +1260,7 @@
 	return (iface_string);
 }
 
-int totempg_my_nodeid_get (void)
+unsigned int totempg_my_nodeid_get (void)
 {
 	return (totemmrp_my_nodeid_get());
 }
diff -Naurd corosync-0.92/exec/totemrrp.c corosync-trunk/exec/totemrrp.c
--- corosync-0.92/exec/totemrrp.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/totemrrp.c	2008-10-30 23:25:56.000000000 +0100
@@ -194,7 +194,11 @@
 
 	int totemrrp_log_level_debug;
 
-	void (*totemrrp_log_printf) (char *file, int line, int level, char *format, ...) __attribute__((format(printf, 4, 5)));
+	int totemrrp_subsys_id;
+
+	void (*totemrrp_log_printf) (int subsys, char *function, char *file,
+		int line, unsigned int level, char *format,
+		...)__attribute__((format(printf, 6, 7)));
 
 	totemrrp_handle handle;
 
@@ -459,8 +463,14 @@
 	.mutex		= PTHREAD_MUTEX_INITIALIZER
 };
 
-#define log_printf(level, format, args...) \
-    rrp_instance->totemrrp_log_printf (__FILE__, __LINE__, level, format, ##args)
+
+#define log_printf(level, format, args...)				\
+do {									\
+	rrp_instance->totemrrp_log_printf (				\
+		rrp_instance->totemrrp_subsys_id,			\
+		(char *)__FUNCTION__, __FILE__, __LINE__, level,	\
+		format, ##args);					\
+} while (0);
 
 /*
  * None Replication Implementation
@@ -1426,6 +1436,7 @@
 	instance->totemrrp_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
 	instance->totemrrp_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
 	instance->totemrrp_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
+	instance->totemrrp_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
 	instance->totemrrp_log_printf = totem_config->totem_logging_configuration.log_printf;
 
 	instance->interfaces = totem_config->interfaces;
diff -Naurd corosync-0.92/exec/totemsrp.c corosync-trunk/exec/totemsrp.c
--- corosync-0.92/exec/totemsrp.c	2008-08-20 03:07:29.000000000 +0200
+++ corosync-trunk/exec/totemsrp.c	2009-01-20 18:41:45.000000000 +0100
@@ -429,7 +429,11 @@
 
 	int totemsrp_log_level_debug;
 
-	void (*totemsrp_log_printf) (char *file, int line, int level, char *format, ...) __attribute__((format(printf, 4, 5)));
+	int totemsrp_subsys_id;
+
+	void (*totemsrp_log_printf) (int subsys, char *function, char *file,
+		int line, unsigned int level, char *format,
+		...)__attribute__((format(printf, 6, 7)));;
 
 	enum memb_state memb_state;
 
@@ -607,8 +611,12 @@
 
 static char *rundir = NULL;
 
-#define log_printf(level, format, args...) \
-    instance->totemsrp_log_printf (__FILE__, __LINE__, level, format, ##args)
+#define log_printf(level, format, args...)				\
+do {									\
+	instance->totemsrp_log_printf (instance->totemsrp_subsys_id,	\
+		(char *)__FUNCTION__, __FILE__, __LINE__, level,	\
+		format, ##args);					\
+} while (0);
 
 void totemsrp_instance_initialize (struct totemsrp_instance *instance)
 {
@@ -618,7 +626,7 @@
 
 	list_init (&instance->token_callback_sent_listhead);
 
-	instance->my_received_flg = 0;
+	instance->my_received_flg = 1;
 
 	instance->my_token_seq = SEQNO_START_TOKEN - 1;
 
@@ -709,6 +717,7 @@
 	instance->totemsrp_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
 	instance->totemsrp_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
 	instance->totemsrp_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
+	instance->totemsrp_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
 	instance->totemsrp_log_printf = totem_config->totem_logging_configuration.log_printf;
 
 	/*
@@ -904,11 +913,11 @@
 	return (res);
 }
 
-int totemsrp_my_nodeid_get (
+unsigned int totemsrp_my_nodeid_get (
 	totemsrp_handle handle)
 {
 	struct totemsrp_instance *instance;
-	int res;
+	unsigned int res;
 
 	res = hdb_handle_get (&totemsrp_instance_database, handle,
 		(void *)&instance);
@@ -1686,7 +1695,7 @@
 		"entering OPERATIONAL state.\n");
 	instance->memb_state = MEMB_STATE_OPERATIONAL;
 
-	instance->my_received_flg = 0;
+	instance->my_received_flg = 1;
 
 	return;
 }
@@ -2634,6 +2643,8 @@
 {
 	struct srp_addr *addr;
 	struct memb_commit_token_memb_entry *memb_list;
+	unsigned int high_aru;
+	unsigned int i;
 
 	addr = (struct srp_addr *)commit_token->end_of_commit_token;
 	memb_list = (struct memb_commit_token_memb_entry *)(addr + commit_token->addr_entries);
@@ -2655,9 +2666,40 @@
 	instance->my_received_flg =
 		(instance->my_aru == instance->my_high_seq_received);
 
-	memb_list[commit_token->memb_index].high_delivered = instance->my_high_delivered;
 	memb_list[commit_token->memb_index].received_flg = instance->my_received_flg;
 
+	memb_list[commit_token->memb_index].high_delivered = instance->my_high_delivered;
+	/*
+	 * find high aru up to current memb_index for all matching ring ids
+	 * if any ring id matching memb_index has aru less then high aru set
+	 * received flag for that entry to false
+	 */
+	high_aru = memb_list[commit_token->memb_index].aru;
+	for (i = 0; i <= commit_token->memb_index; i++) {
+		if (memcmp (&memb_list[commit_token->memb_index].ring_id,
+			&memb_list[i].ring_id,
+			sizeof (struct memb_ring_id)) == 0) {
+
+			if (sq_lt_compare (high_aru, memb_list[i].aru)) {
+				high_aru = memb_list[i].aru;
+			}
+		}
+	}
+
+	for (i = 0; i <= commit_token->memb_index; i++) {
+		if (memcmp (&memb_list[commit_token->memb_index].ring_id,
+			&memb_list[i].ring_id,
+			sizeof (struct memb_ring_id)) == 0) {
+
+			if (sq_lt_compare (memb_list[i].aru, high_aru)) {
+				memb_list[i].received_flg = 0;
+				if (i == commit_token->memb_index) {
+					instance->my_received_flg = 0;
+				}
+			}
+		}
+	}
+
 	commit_token->header.nodeid = instance->my_id.addr[0].nodeid;
 	commit_token->memb_index += 1;
 	assert (commit_token->memb_index <= commit_token->addr_entries);
@@ -2944,6 +2986,8 @@
 		goto error_exit;
 	}
 
+	token_hold_cancel_send (instance);
+
 	callback_handle = (struct token_callback_instance *)malloc (sizeof (struct token_callback_instance));
 	if (callback_handle == 0) {
 		return (-1);
diff -Naurd corosync-0.92/exec/totemsrp.h corosync-trunk/exec/totemsrp.h
--- corosync-0.92/exec/totemsrp.h	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/exec/totemsrp.h	2008-12-01 19:44:55.000000000 +0100
@@ -104,7 +104,7 @@
 	char ***status,
 	unsigned int *iface_count);
 
-extern int totemsrp_my_nodeid_get (
+extern unsigned int totemsrp_my_nodeid_get (
 	totemsrp_handle handle);
 
 extern int totemsrp_my_family_get (
diff -Naurd corosync-0.92/exec/util.c corosync-trunk/exec/util.c
--- corosync-0.92/exec/util.c	2008-09-17 21:04:19.000000000 +0200
+++ corosync-trunk/exec/util.c	2008-12-18 09:28:46.000000000 +0100
@@ -39,7 +39,7 @@
 #include <errno.h>
 #include <sys/time.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/list.h>
 #include <corosync/engine/logsys.h>
 #include "util.h"
@@ -49,7 +49,7 @@
 /*
  * Compare two names.  returns non-zero on match.
  */
-int name_match(SaNameT *name1, SaNameT *name2) 
+int name_match(cs_name_t *name1, cs_name_t *name2) 
 {
 	if (name1->length == name2->length) {
 		return ((strncmp ((char *)name1->value, (char *)name2->value,
@@ -61,17 +61,17 @@
 /*
  * Get the time of day and convert to nanoseconds
  */
-SaTimeT clust_time_now(void)
+cs_time_t clust_time_now(void)
 {
 	struct timeval tv;
-	SaTimeT time_now;
+	cs_time_t time_now;
 
 	if (gettimeofday(&tv, 0)) {
 		return 0ULL;
 	}
 
-	time_now = (SaTimeT)(tv.tv_sec) * 1000000000ULL;
-	time_now += (SaTimeT)(tv.tv_usec) * 1000ULL;
+	time_now = (cs_time_t)(tv.tv_sec) * 1000000000ULL;
+	time_now += (cs_time_t)(tv.tv_usec) * 1000ULL;
 
 	return time_now;
 }
@@ -87,20 +87,19 @@
 {
 	log_printf (LOG_LEVEL_ERROR, "AIS Executive exiting "
 		"with status %d at %s:%u.\n", err, file, line);
-	logsys_flush();
-	exit (EXIT_FAILURE);
+	exit (err);
 }
 
 #define min(a,b) ((a) < (b) ? (a) : (b))
 
-char *getSaNameT (SaNameT *name)
+char *getcs_name_t (cs_name_t *name)
 {
-	static char ret_name[SA_MAX_NAME_LENGTH];
+	static char ret_name[CS_MAX_NAME_LENGTH];
 
 	/* if string is corrupt (non-terminated), ensure it's displayed safely */
-	if (name->length >= SA_MAX_NAME_LENGTH || name->value[name->length] != '\0') {
+	if (name->length >= CS_MAX_NAME_LENGTH || name->value[name->length] != '\0') {
 		memset (ret_name, 0, sizeof (ret_name));
-		memcpy (ret_name, name->value, min(name->length, SA_MAX_NAME_LENGTH -1));
+		memcpy (ret_name, name->value, min(name->length, CS_MAX_NAME_LENGTH -1));
 		return (ret_name);
 	}
 	return ((char *)name->value);
@@ -134,16 +133,16 @@
 	return (end_address);
 }
 
-void setSaNameT (SaNameT *name, char *str) {
-	strncpy ((char *)name->value, str, SA_MAX_NAME_LENGTH);
-	if (strlen ((char *)name->value) > SA_MAX_NAME_LENGTH) {
-		name->length = SA_MAX_NAME_LENGTH;
+void setcs_name_t (cs_name_t *name, char *str) {
+	strncpy ((char *)name->value, str, CS_MAX_NAME_LENGTH);
+	if (strlen ((char *)name->value) > CS_MAX_NAME_LENGTH) {
+		name->length = CS_MAX_NAME_LENGTH;
 	} else {
 		name->length = strlen (str);
 	}
 }
 
-int SaNameTisEqual (SaNameT *str1, char *str2) {
+int cs_name_tisEqual (cs_name_t *str1, char *str2) {
 	if (str1->length == strlen (str2)) {
 		return ((strncmp ((char *)str1->value, (char *)str2,
 			str1->length)) == 0);
diff -Naurd corosync-0.92/exec/util.h corosync-trunk/exec/util.h
--- corosync-0.92/exec/util.h	2008-09-17 21:04:19.000000000 +0200
+++ corosync-trunk/exec/util.h	2008-11-06 22:49:07.000000000 +0100
@@ -37,12 +37,12 @@
 
 #include <sys/time.h>
 #include <corosync/mar_gen.h>
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 
 /*
  * Get the time of day and convert to nanoseconds
  */
-extern SaTimeT clust_time_now(void);
+extern cs_time_t clust_time_now(void);
 
 enum e_ais_done {
 	AIS_DONE_EXIT = -1,
@@ -66,15 +66,15 @@
 /*
  * Compare two names.  returns non-zero on match.
  */
-extern int name_match(SaNameT *name1, SaNameT *name2);
+extern int name_match(cs_name_t *name1, cs_name_t *name2);
 extern int mar_name_match(mar_name_t *name1, mar_name_t *name2);
 #define corosync_exit_error(err) _corosync_exit_error ((err), __FILE__, __LINE__)
 extern void _corosync_exit_error (
 	enum e_ais_done err, const char *file, unsigned int line);
 void _corosync_out_of_memory_error (void);
-extern char *getSaNameT (SaNameT *name);
+extern char *getcs_name_t (cs_name_t *name);
 extern char *strstr_rs (const char *haystack, const char *needle);
-extern void setSaNameT (SaNameT *name, char *str);
+extern void setcs_name_t (cs_name_t *name, char *str);
 char *get_mar_name_t (mar_name_t *name);
-extern int SaNameTisEqual (SaNameT *str1, char *str2);
+extern int cs_name_tisEqual (cs_name_t *str1, char *str2);
 #endif /* UTIL_H_DEFINED */
diff -Naurd corosync-0.92/exec/vsf.h corosync-trunk/exec/vsf.h
--- corosync-0.92/exec/vsf.h	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/exec/vsf.h	2008-12-08 16:55:41.000000000 +0100
@@ -34,12 +34,14 @@
 #ifndef VSF_H_DEFINED
 #define VSF_H_DEFINED
 
+struct corosync_api_v1;
 struct corosync_vsf_iface_ver0 {
 
 	/*
 	 * Executes a callback whenever component changes
 	 */
 	int (*init) (
+	    struct corosync_api_v1 *api,
 	    void (*primary_callback_fn) (
 		unsigned int *view_list,
 		int view_list_entries,
diff -Naurd corosync-0.92/exec/vsf_quorum.c corosync-trunk/exec/vsf_quorum.c
--- corosync-0.92/exec/vsf_quorum.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/exec/vsf_quorum.c	2009-01-08 12:12:10.000000000 +0100
@@ -0,0 +1,468 @@
+/*
+ * 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 Red Hat Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <sched.h>
+#include <time.h>
+
+#include <corosync/engine/logsys.h>
+#include <corosync/swab.h>
+#include <corosync/list.h>
+#include <corosync/ipc_gen.h>
+#include <corosync/ipc_quorum.h>
+#include <corosync/lcr/lcr_comp.h>
+#include <corosync/lcr/lcr_ifact.h>
+#include <corosync/engine/coroapi.h>
+#include <corosync/engine/quorum.h>
+
+LOGSYS_DECLARE_SUBSYS ("QUORUM", LOG_INFO);
+
+struct quorum_pd {
+	unsigned char track_flags;
+	int tracking_enabled;
+	struct list_head list;
+	void *conn;
+};
+
+struct internal_callback_pd {
+	struct list_head list;
+	quorum_callback_fn_t callback;
+	void *context;
+};
+
+static void message_handler_req_lib_quorum_getquorate (void *conn, void *msg);
+static void message_handler_req_lib_quorum_trackstart (void *conn, void *msg);
+static void message_handler_req_lib_quorum_trackstop (void *conn, void *msg);
+static void send_library_notification(void *conn);
+static void send_internal_notification(void);
+static int quorum_exec_init_fn (struct corosync_api_v1 *api);
+static int quorum_lib_init_fn (void *conn);
+static int quorum_lib_exit_fn (void *conn);
+
+static int primary_designated = 0;
+static struct corosync_api_v1 *corosync_api;
+static struct list_head lib_trackers_list;
+static struct list_head internal_trackers_list;
+static struct memb_ring_id quorum_ring_id;
+static int quorum_view_list_entries = 0;
+static int quorum_view_list[PROCESSOR_COUNT_MAX];
+struct quorum_services_api_ver1 *quorum_iface = NULL;
+
+static void (*sync_primary_callback_fn) (
+	unsigned int *view_list,
+	int view_list_entries,
+	int primary_designated,
+	struct memb_ring_id *ring_id);
+
+/* Internal quorum API function */
+static void quorum_api_set_quorum(unsigned int *view_list,
+				  int view_list_entries,
+				  int quorum, struct memb_ring_id *ring_id)
+{
+	primary_designated = quorum;
+
+	if (primary_designated) {
+		log_printf (LOG_LEVEL_NOTICE, "This node is within the primary component and will provide service.\n");
+	} else {
+		log_printf (LOG_LEVEL_NOTICE, "This node is within the non-primary component and will NOT provide any services.\n");
+	}
+
+	memcpy(&quorum_ring_id, ring_id, sizeof (quorum_ring_id));
+
+	quorum_view_list_entries = view_list_entries;
+	memcpy(quorum_view_list, view_list, sizeof(unsigned int)*view_list_entries);
+
+	/* Tell sync() */
+	sync_primary_callback_fn(view_list, view_list_entries,
+				 primary_designated, &quorum_ring_id);
+
+	/* Tell internal listeners */
+	send_internal_notification();
+
+	/* Tell IPC listeners */
+	send_library_notification(NULL);
+}
+
+static struct corosync_lib_handler quorum_lib_service[] =
+{
+	{ /* 0 */
+		.lib_handler_fn				= message_handler_req_lib_quorum_getquorate,
+		.response_size				= sizeof (struct res_lib_quorum_getquorate),
+		.response_id				= MESSAGE_RES_QUORUM_GETQUORATE,
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 1 */
+		.lib_handler_fn				= message_handler_req_lib_quorum_trackstart,
+		.response_size				= sizeof (mar_res_header_t),
+		.response_id				= MESSAGE_RES_QUORUM_NOTIFICATION,
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 2 */
+		.lib_handler_fn				= message_handler_req_lib_quorum_trackstop,
+		.response_size				= sizeof (mar_res_header_t),
+		.response_id				= MESSAGE_RES_QUORUM_TRACKSTOP,
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	}
+};
+
+static struct corosync_service_engine quorum_service_handler = {
+	.name				        = "corosync cluster quorum service v0.1",
+	.id					= QUORUM_SERVICE,
+	.private_data_size			= sizeof (struct quorum_pd),
+	.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
+	.allow_inquorate			= CS_LIB_ALLOW_INQUORATE,
+	.lib_init_fn				= quorum_lib_init_fn,
+	.lib_exit_fn				= quorum_lib_exit_fn,
+	.lib_engine				= quorum_lib_service,
+	.exec_init_fn				= quorum_exec_init_fn,
+	.lib_engine_count			= sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler),
+};
+
+static struct lcr_iface corosync_quorum_ver0[1] = {
+	{
+		.name			= "corosync_quorum",
+		.version		= 0,
+		.versions_replace	= 0,
+		.versions_replace_count	= 0,
+		.dependencies		= 0,
+		.dependency_count	= 0,
+		.constructor		= NULL,
+		.destructor		= NULL,
+		.interfaces		= NULL,
+	},
+};
+
+static struct corosync_service_engine *quorum_get_service_handler_ver0 (void)
+{
+	return (&quorum_service_handler);
+}
+
+static struct lcr_comp quorum_comp_ver0 = {
+	.iface_count			= 1,
+	.ifaces				= corosync_quorum_ver0
+};
+
+static struct corosync_service_engine_iface_ver0 quorum_service_handler_iface = {
+	.corosync_get_service_engine_ver0 = quorum_get_service_handler_ver0
+};
+
+__attribute__ ((constructor)) static void quorum_comp_register (void) {
+	lcr_component_register (&quorum_comp_ver0);
+	lcr_interfaces_set (&corosync_quorum_ver0[0], &quorum_service_handler_iface);
+}
+
+/* -------------------------------------------------- */
+
+
+/*
+ * Internal API functions for corosync
+ */
+
+static int quorum_quorate(void)
+{
+	return primary_designated;
+}
+
+
+static int quorum_register_callback(quorum_callback_fn_t function, void *context)
+{
+	struct internal_callback_pd *pd = malloc(sizeof(struct internal_callback_pd));
+	if (!pd)
+		return -1;
+
+	pd->context  = context;
+	pd->callback = function;
+	list_add (&pd->list, &internal_trackers_list);
+
+	return 0;
+}
+
+static int quorum_unregister_callback(quorum_callback_fn_t function, void *context)
+{
+	struct internal_callback_pd *pd;
+	struct list_head *tmp;
+
+	for (tmp = internal_trackers_list.next; tmp != &internal_trackers_list; tmp = tmp->next) {
+
+		pd = list_entry(tmp, struct internal_callback_pd, list);
+		if (pd->callback == function && pd->context == context) {
+			list_del(&pd->list);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+static struct quorum_callin_functions callins = {
+	.quorate = quorum_quorate,
+	.register_callback = quorum_register_callback,
+	.unregister_callback = quorum_unregister_callback
+};
+
+/* --------------------------------------------------------------------- */
+
+static int quorum_exec_init_fn (struct corosync_api_v1 *api)
+{
+	unsigned int find_handle;
+	unsigned int quorum_handle = 0;
+	unsigned int q_handle;
+	char *quorum_module;
+	int res;
+	void *quorum_iface_p;
+
+	corosync_api = api;
+	list_init (&lib_trackers_list);
+	list_init (&internal_trackers_list);
+
+	/*
+	 * Tell corosync we have a quorum engine.
+	 */
+	api->quorum_initialize(&callins, &sync_primary_callback_fn);
+
+	/*
+	 * Look for a quorum provider
+	 */
+	api->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle);
+        api->object_find_next(find_handle, &quorum_handle);
+	api->object_find_destroy(find_handle);
+
+	if (quorum_handle) {
+		if ( !(res = api->object_key_get(quorum_handle,
+						 "provider",
+						 strlen("provider"),
+						 (void *)&quorum_module,
+						 NULL))) {
+
+			res = lcr_ifact_reference (
+				&q_handle,
+				quorum_module,
+				0,
+				&quorum_iface_p,
+				0);
+
+			if (res == -1) {
+				log_printf (LOG_LEVEL_NOTICE,
+					    "Couldn't load quorum provider %s\n",
+					    quorum_module);
+				return (-1);
+			}
+
+			log_printf (LOG_LEVEL_NOTICE,
+				    "Using quorum provider %s\n", quorum_module);
+
+			quorum_iface = (struct quorum_services_api_ver1 *)quorum_iface_p;
+			quorum_iface->init (api, quorum_api_set_quorum);
+		}
+	}
+	if (!quorum_iface) {
+		/*
+                 * With no quorum provider, we are always quorate 
+                 */
+		primary_designated = 1;
+	}
+
+	return (0);
+}
+
+static int quorum_lib_init_fn (void *conn)
+{
+	struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+
+	log_printf(LOG_LEVEL_DEBUG, "lib_init_fn: conn=%p\n", conn);
+
+	list_init (&pd->list);
+	pd->conn = conn;
+
+	return (0);
+}
+
+static int quorum_lib_exit_fn (void *conn)
+{
+	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+
+	log_printf(LOG_LEVEL_DEBUG, "lib_exit_fn: conn=%p\n", conn);
+
+	if (quorum_pd->tracking_enabled) {
+		list_del (&quorum_pd->list);
+		list_init (&quorum_pd->list);
+	}
+	return (0);
+}
+
+
+static void send_internal_notification(void)
+{
+	struct list_head *tmp;
+	struct internal_callback_pd *pd;
+
+	for (tmp = internal_trackers_list.next; tmp != &internal_trackers_list; tmp = tmp->next) {
+
+		pd = list_entry(tmp, struct internal_callback_pd, list);
+
+		pd->callback(primary_designated, pd->context);
+	}
+}
+
+static void send_library_notification(void *conn)
+{
+	int size = sizeof(struct res_lib_quorum_notification) + sizeof(unsigned int)*quorum_view_list_entries;
+	char buf[size];
+	struct res_lib_quorum_notification *res_lib_quorum_notification = (struct res_lib_quorum_notification *)buf;
+	struct list_head *tmp;
+	int i;
+
+	log_printf(LOG_LEVEL_DEBUG, "sending quorum notification to %p, length = %d\n", conn, size);
+
+	res_lib_quorum_notification->quorate = primary_designated;
+	res_lib_quorum_notification->ring_seq = quorum_ring_id.seq;
+	res_lib_quorum_notification->view_list_entries = quorum_view_list_entries;
+	for (i=0; i<quorum_view_list_entries; i++) {
+		res_lib_quorum_notification->view_list[i] = quorum_view_list[i];
+	}
+
+	res_lib_quorum_notification->header.id = MESSAGE_RES_QUORUM_NOTIFICATION;
+	res_lib_quorum_notification->header.size = size;
+	res_lib_quorum_notification->header.error = CS_OK;
+
+	/* Send it to all interested parties */
+	if (conn) {
+		corosync_api->ipc_conn_send_response(conn, res_lib_quorum_notification, size);
+	}
+	else {
+		struct quorum_pd *qpd;
+
+		for (tmp = lib_trackers_list.next; tmp != &lib_trackers_list; tmp = tmp->next) {
+
+			qpd = list_entry(tmp, struct quorum_pd, list);
+
+			corosync_api->ipc_conn_send_response(corosync_api->ipc_conn_partner_get(qpd->conn),
+							     res_lib_quorum_notification, size);
+		}
+	}
+	return;
+}
+
+static void message_handler_req_lib_quorum_getquorate (void *conn, void *msg)
+{
+	struct res_lib_quorum_getquorate res_lib_quorum_getquorate;
+
+	log_printf(LOG_LEVEL_DEBUG, "got quorate request on %p\n", conn);
+
+	/* send status */
+	res_lib_quorum_getquorate.quorate = primary_designated;
+	res_lib_quorum_getquorate.header.size = sizeof(res_lib_quorum_getquorate);
+	res_lib_quorum_getquorate.header.id = MESSAGE_RES_QUORUM_GETQUORATE;
+	res_lib_quorum_getquorate.header.error = CS_OK;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_quorum_getquorate, sizeof(res_lib_quorum_getquorate));
+}
+
+
+static void message_handler_req_lib_quorum_trackstart (void *conn, void *msg)
+{
+	struct req_lib_quorum_trackstart *req_lib_quorum_trackstart = (struct req_lib_quorum_trackstart *)msg;
+	mar_res_header_t res;
+	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+
+	log_printf(LOG_LEVEL_DEBUG, "got trackstart request on %p\n", conn);
+
+	/*
+	 * If an immediate listing of the current cluster membership
+	 * is requested, generate membership list
+	 */
+	if (req_lib_quorum_trackstart->track_flags & CS_TRACK_CURRENT ||
+	    req_lib_quorum_trackstart->track_flags & CS_TRACK_CHANGES) {
+		log_printf(LOG_LEVEL_DEBUG, "sending initial status to %p\n", conn);
+		send_library_notification(corosync_api->ipc_conn_partner_get (conn));
+	}
+
+	/*
+	 * Record requests for tracking
+	 */
+	if (req_lib_quorum_trackstart->track_flags & CS_TRACK_CHANGES ||
+	    req_lib_quorum_trackstart->track_flags & CS_TRACK_CHANGES_ONLY) {
+
+		quorum_pd->track_flags = req_lib_quorum_trackstart->track_flags;
+		quorum_pd->tracking_enabled = 1;
+
+		list_add (&quorum_pd->list, &lib_trackers_list);
+	}
+
+	/* send status */
+	res.size = sizeof(res);
+	res.id = MESSAGE_RES_QUORUM_TRACKSTART;
+	res.error = CS_OK;
+	corosync_api->ipc_conn_send_response(conn, &res, sizeof(mar_res_header_t));
+}
+
+static void message_handler_req_lib_quorum_trackstop (void *conn, void *msg)
+{
+	mar_res_header_t res;
+	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+
+	log_printf(LOG_LEVEL_DEBUG, "got trackstop request on %p\n", conn);
+
+	if (quorum_pd->tracking_enabled) {
+		res.error = CS_OK;
+		quorum_pd->tracking_enabled = 0;
+		list_del (&quorum_pd->list);
+		list_init (&quorum_pd->list);
+	} else {
+		res.error = CS_ERR_NOT_EXIST;
+	}
+
+	/* send status */
+	res.size = sizeof(res);
+	res.id = MESSAGE_RES_QUORUM_TRACKSTOP;
+	res.error = CS_OK;
+	corosync_api->ipc_conn_send_response(conn, &res, sizeof(mar_res_header_t));
+}
+
diff -Naurd corosync-0.92/exec/vsf_ykd.c corosync-trunk/exec/vsf_ykd.c
--- corosync-0.92/exec/vsf_ykd.c	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/exec/vsf_ykd.c	2008-12-08 16:55:41.000000000 +0100
@@ -56,12 +56,12 @@
 #include <time.h>
 
 #include <corosync/engine/logsys.h>
+#include <corosync/ipc_gen.h>
+#include <corosync/engine/coroapi.h>
+#include <corosync/engine/quorum.h>
 #include <corosync/swab.h>
 #include <corosync/lcr/lcr_comp.h>
 
-#include "main.h"
-#include "vsf.h"
-
 LOGSYS_DECLARE_SUBSYS ("YKD", LOG_INFO);
 
 #define YKD_PROCESSOR_COUNT_MAX 32
@@ -108,7 +108,7 @@
 
 struct ykd_state ykd_state;
 
-static totempg_groups_handle ykd_group_handle;
+static cs_tpg_handle ykd_group_handle;
 
 static struct state_received state_received_confchg[YKD_PROCESSOR_COUNT_MAX];
 
@@ -140,6 +140,8 @@
 
 static void *ykd_state_send_callback_token_handle = 0;
 
+static struct corosync_api_v1 *api;
+
 static void (*ykd_primary_callback_fn) (
 	unsigned int *view_list,
 	int view_list_entries,
@@ -168,15 +170,15 @@
 	iovec[1].iov_base = (char *)&ykd_state;
 	iovec[1].iov_len = sizeof (struct ykd_state);
 
-	res = totempg_groups_mcast_joined (ykd_group_handle, iovec, 2,
-		TOTEMPG_AGREED);
+	res = api->tpg_joined_mcast (ykd_group_handle, iovec, 2,
+		TOTEM_AGREED);
 
 	return (res);
 }
 
 static void ykd_state_send (void)
 {
-        totempg_callback_token_create (
+        api->totem_callback_token_create (
                 &ykd_state_send_callback_token_handle,
                 TOTEM_CALLBACK_TOKEN_SENT,
                 1, /* delete after callback */
@@ -195,15 +197,15 @@
 	iovec.iov_base = (char *)&header;
 	iovec.iov_len = sizeof (struct ykd_header);
 
-	res = totempg_groups_mcast_joined (ykd_group_handle, &iovec, 1,
-		TOTEMPG_AGREED);
+	res = api->tpg_joined_mcast (ykd_group_handle, &iovec, 1,
+		TOTEM_AGREED);
 
 	return (res);
 }
 
 static void ykd_attempt_send (void)
 {
-        totempg_callback_token_create (
+        api->totem_callback_token_create (
                 &ykd_attempt_send_callback_token_handle,
                 TOTEM_CALLBACK_TOKEN_SENT,
                 1, /* delete after callback */
@@ -460,7 +462,7 @@
 	memcpy (&ykd_ring_id, ring_id, sizeof (struct memb_ring_id));
 
 	if (first_run) {
-		ykd_state.last_primary.member_list[0] = totempg_my_nodeid_get();
+		ykd_state.last_primary.member_list[0] = api->totem_nodeid_get();
 		ykd_state.last_primary.member_list_entries = 1;
 		ykd_state.last_primary.session_id = 0;
 		first_run = 0;
@@ -493,53 +495,41 @@
 	ykd_state_send ();
 }
 
-struct totempg_group ykd_group = {
+struct corosync_tpg_group ykd_group = {
 	.group		= "ykd",
 	.group_len	= 3
 };
 
-static int ykd_init (
-	void (*primary_callback_fn) (
-		unsigned int *view_list,
-		int view_list_entries,
-		int primary_designated,
-		struct memb_ring_id *ring_id))
+static void ykd_init (
+	struct corosync_api_v1 *corosync_api,
+	quorum_set_quorate_fn_t set_primary)
 {
-	ykd_primary_callback_fn = primary_callback_fn;
+	ykd_primary_callback_fn = set_primary;
+	api = corosync_api;
 
-	totempg_groups_initialize (
+	api->tpg_init (
 		&ykd_group_handle,
 		ykd_deliver_fn,
 		ykd_confchg_fn);
 
-	totempg_groups_join (
+	api->tpg_join (
 		ykd_group_handle,
 		&ykd_group,
 		1);
 
 	ykd_state_init ();
-
-	return (0);
-}
-
-/*
- * Returns 1 if this processor is in the primary 
- */
-static int ykd_primary (void) {
-	return (primary_designated);
 }
 
 /*
  * lcrso object definition
  */
-static struct corosync_vsf_iface_ver0 vsf_ykd_iface_ver0 = {
+static struct quorum_services_api_ver1 vsf_ykd_iface_ver0 = {
 	.init				= ykd_init,
-	.primary			= ykd_primary
 };
 
 static struct lcr_iface corosync_vsf_ykd_ver0[1] = {
 	{
-		.name			= "corosync_vsf_ykd",
+		.name			= "corosync_quorum_ykd",
 		.version		= 0,
 		.versions_replace	= 0,
 		.versions_replace_count	= 0,
diff -Naurd corosync-0.92/include/corosync/ais_util.h corosync-trunk/include/corosync/ais_util.h
--- corosync-0.92/include/corosync/ais_util.h	2008-08-14 16:59:50.000000000 +0200
+++ corosync-trunk/include/corosync/ais_util.h	2008-11-06 22:49:07.000000000 +0100
@@ -67,71 +67,71 @@
 
 struct saVersionDatabase {
 	int versionCount;
-	SaVersionT *versionsSupported;
+	cs_version_t *versionsSupported;
 };
 
-SaAisErrorT saSendMsgRetry (
+cs_error_t saSendMsgRetry (
 	int s,
 	struct iovec *iov,
 	int iov_len);
 
-SaAisErrorT saSendMsgReceiveReply (
+cs_error_t saSendMsgReceiveReply (
 	int s,
 	struct iovec *iov,
 	int iov_len,
 	void *responseMessage,
 	int responseLen);
 
-SaAisErrorT saSendReceiveReply (
+cs_error_t saSendReceiveReply (
 	int s,
 	void *requestMessage,
 	int requestLen,
 	void *responseMessage,
 	int responseLen);
 
-SaAisErrorT
+cs_error_t
 saPollRetry (
 	struct pollfd *ufds,
 	unsigned int nfds,
 	int timeout);
 
-SaAisErrorT
+cs_error_t
 saHandleCreate (
 	struct saHandleDatabase *handleDatabase,
 	int instanceSize,
-	SaUint64T *handleOut);
+	uint64_t *handleOut);
 
-SaAisErrorT
+cs_error_t
 saHandleDestroy (
 	struct saHandleDatabase *handleDatabase,
-	SaUint64T handle);
+	uint64_t handle);
 
-SaAisErrorT
+cs_error_t
 saHandleInstanceGet (
 	struct saHandleDatabase *handleDatabase,
-	SaUint64T handle,
+	uint64_t handle,
 	void **instance);
 
-SaAisErrorT
+cs_error_t
 saHandleInstancePut (
 	struct saHandleDatabase *handleDatabase,
-	SaUint64T handle);
+	uint64_t handle);
 
-SaAisErrorT
+cs_error_t
 saVersionVerify (
 	struct saVersionDatabase *versionDatabase,
-	SaVersionT *version);
+	cs_version_t *version);
 
 #define offset_of(type,member) (int)(&(((type *)0)->member))
 
-SaTimeT
+cs_time_t
 clustTimeNow(void);
 
-extern SaAisErrorT saServiceConnect (
+extern cs_error_t saServiceConnect (
     int *responseOut, int *callbackOut, enum service_types service);
 
-extern SaAisErrorT saRecvRetry (int s, void *msg, size_t len);
+extern cs_error_t saRecvRetry (int s, void *msg, size_t len);
 
-extern SaAisErrorT saSendRetry (int s, const void *msg, size_t len);
+extern cs_error_t saSendRetry (int s, const void *msg, size_t len);
 
 #endif /* AIS_UTIL_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/cfg.h corosync-trunk/include/corosync/cfg.h
--- corosync-0.92/include/corosync/cfg.h	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/include/corosync/cfg.h	2009-01-19 09:31:21.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005 MontaVista Software, Inc.
- * Copyright (c) 2006 Red Hat, Inc.
+ * Copyright (c) 2006-2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -36,33 +36,33 @@
 #define AIS_COROSYNCCFG_H_DEFINED
 
 #include <netinet/in.h>
-#include "saAis.h"
+#include <corosync/corotypes.h>
 
-typedef SaUint64T corosync_cfg_handle_t;
+typedef uint64_t corosync_cfg_handle_t;
 
 typedef enum {
 	COROSYNC_CFG_ADMINISTRATIVETARGET_SERVICEUNIT = 0,
 	COROSYNC_CFG_ADMINISTRATIVETARGET_SERVICEGROUP = 1,
 	COROSYNC_CFG_ADMINISTRATIVETARGET_COMPONENTSERVICEINSTANCE = 2,
 	COROSYNC_CFG_ADMINISTRATIVETARGET_NODE = 3
-} CorosyncCfgAdministrativeTargetT;
+} corosync_cfg_administrative_target_t;
 
 typedef enum {
 	COROSYNC_CFG_ADMINISTRATIVESTATE_UNLOCKED = 0,
 	COROSYNC_CFG_ADMINISTRATIVESTATE_LOCKED = 1,
 	COROSYNC_CFG_ADMINISTRATIVESTATE_STOPPING = 2
-} CorosyncCfgAdministrativeStateT;
+} corosync_cfg_administrative_state_t;
 
 typedef enum {
 	COROSYNC_CFG_OPERATIONALSTATE_ENABLED = 1,
 	COROSYNC_CFG_OPERATIONALSTATE_DISABLED = 2
-} CorosyncCfgOperationalStateT;
+} corosync_cfg_operational_state_t;
 
 typedef enum {
 	COROSYNC_CFG_READINESSSTATE_OUTOFSERVICE = 1,
 	COROSYNC_CFG_READINESSSTATE_INSERVICE = 2,
 	COROSYNC_CFG_READINESSSTATE_STOPPING = 3
-} CorosyncCfgReadinessStateT;
+} corosync_cfg_readiness_state_t;
 
 typedef enum {
 	COROSYNC_CFG_PRESENCESTATE_UNINSTANTIATED = 1,
@@ -72,7 +72,7 @@
 	COROSYNC_CFG_PRESENCESTATE_RESTARTING = 5,
 	COROSYNC_CFG_PRESENCESTATE_INSTANTIATION_FAILED = 6,
 	COROSYNC_CFG_PRESENCESTATE_TERMINATION_FAILED = 7
-} CorosyncCfgPresenceStateT;
+} corosync_cfg_presence_state_t;
 
 typedef enum {
 	COROSYNC_CFG_STATETYPE_OPERATIONAL = 0,
@@ -80,27 +80,63 @@
 	COROSYNC_CFG_STATETYPE_READINESS = 2,
 	COROSYNC_CFG_STATETYPE_HA = 3,
 	COROSYNC_CFG_STATETYPE_PRESENCE = 4
-} CorosyncCfgStateTypeT;
+} corosync_cfg_state_type_t;
+
+/* Shutdown types.
+   REQUEST is the normal shutdown. other daemons will be consulted
+   REGARDLESS will tell other daemons but ignore their opinions
+   IMMEDIATE will shut down straight away (but still tell other nodes)
+*/
+typedef enum {
+	COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST = 0,
+	COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS = 1,
+	COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE = 2,
+} corosync_cfg_shutdown_flags_t;
+
+typedef enum {
+	COROSYNC_CFG_SHUTDOWN_FLAG_NO = 0,
+	COROSYNC_CFG_SHUTDOWN_FLAG_YES = 1,
+} corosync_cfg_shutdown_reply_flags_t;
 
 typedef struct {
-	SaNameT name;
-	CorosyncCfgStateTypeT stateType;
-	CorosyncCfgAdministrativeStateT administrativeState;
-} CorosyncCfgStateNotificationT;
+	cs_name_t name;
+	corosync_cfg_state_type_t state_type;
+	corosync_cfg_administrative_state_t administrative_state;
+} corosync_cfg_state_notification_t;
 
 typedef struct {
-        SaUint32T numberOfItems;
-        CorosyncCfgStateNotificationT *notification;
-} CorosyncCfgStateNotificationBufferT;
+        uint32_t number_of_items;
+        corosync_cfg_state_notification_t *notification;
+} corosync_cfg_state_notification_buffer_t;
 
-typedef void (*CorosyncCfgStateTrackCallbackT) (
-	CorosyncCfgStateNotificationBufferT *notificationBuffer,
-	SaAisErrorT error);
+typedef void (*corosync_cfg_state_track_callback_t) (
+	corosync_cfg_state_notification_buffer_t *notification_buffer,
+	cs_error_t error);
+
+typedef void (*corosync_cfg_shutdown_callback_t) (
+	corosync_cfg_handle_t cfg_handle,
+	corosync_cfg_shutdown_flags_t flags);
 
 typedef struct {
-	CorosyncCfgStateTrackCallbackT
-		corosyncCfgStateTrackCallback;
-} CorosyncCfgCallbacksT;
+	corosync_cfg_state_track_callback_t corosync_cfg_state_track_callback;
+	corosync_cfg_shutdown_callback_t corosync_cfg_shutdown_callback;
+} corosync_cfg_callbacks_t;
+
+/*
+ * A node address. This is a complete sockaddr_in[6]
+ * To explain:
+ *  If you cast cna_address to a 'struct sockaddr', the sa_family field
+ *  will be AF_INET or AF_INET6. Armed with that knowledge you can then
+ *  cast it to a sockaddr_in or sockaddr_in6 and pull out the address.
+ *  No other sockaddr fields are valid.
+ *  Also, you must ignore any part of the sockaddr beyond the length supplied
+ */
+typedef struct
+{
+	int  addressLength;
+	char address[sizeof(struct sockaddr_in6)];
+} corosync_cfg_node_address_t;
+
 
 /*
  * Interfaces
@@ -109,70 +145,97 @@
 extern "C" {
 #endif
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_initialize (
 	corosync_cfg_handle_t *cfg_handle,
-	const CorosyncCfgCallbacksT *cfgCallbacks);
+	const corosync_cfg_callbacks_t *cfg_callbacks);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_fd_get (
 	corosync_cfg_handle_t cfg_handle,
-	SaSelectionObjectT *selectionObject);
+	int32_t *selection_fd);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_dispatch (
 	corosync_cfg_handle_t cfg_handle,
-	SaDispatchFlagsT dispatchFlags);
+	cs_dispatch_flags_t dispatch_flags);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_finalize (
 	corosync_cfg_handle_t cfg_handle);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_ring_status_get (
 	corosync_cfg_handle_t cfg_handle,
 	char ***interface_names,
 	char ***status,
 	unsigned int *interface_count);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_ring_reenable (
 	corosync_cfg_handle_t cfg_handle);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_service_load (
 	corosync_cfg_handle_t cfg_handle,
 	char *service_name,
 	unsigned int service_ver);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_service_unload (
 	corosync_cfg_handle_t cfg_handle,
 	char *service_name,
 	unsigned int service_ver);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_administrative_state_get (
 	corosync_cfg_handle_t cfg_handle,
-	CorosyncCfgAdministrativeTargetT administrativeTarget,
-	CorosyncCfgAdministrativeStateT *administrativeState);
+	corosync_cfg_administrative_target_t administrative_target,
+	corosync_cfg_administrative_state_t *administrative_state);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_administrative_state_set (
 	corosync_cfg_handle_t cfg_handle,
-	CorosyncCfgAdministrativeTargetT administrativeTarget,
-	CorosyncCfgAdministrativeStateT administrativeState);
+	corosync_cfg_administrative_target_t administrative_target,
+	corosync_cfg_administrative_state_t administrative_state);
 
-SaAisErrorT
+cs_error_t
+corosync_cfg_kill_node (
+	corosync_cfg_handle_t cfg_handle,
+	unsigned int nodeid,
+	char *reason);
+
+cs_error_t
+corosync_cfg_try_shutdown (
+	corosync_cfg_handle_t cfg_handle,
+	corosync_cfg_shutdown_flags_t flags);
+
+
+cs_error_t
+corosync_cfg_replyto_shutdown (
+	corosync_cfg_handle_t cfg_handle,
+	corosync_cfg_shutdown_reply_flags_t flags);
+
+cs_error_t
 corosync_cfg_state_track (
         corosync_cfg_handle_t cfg_handle,
-        SaUint8T trackFlags,
-        const CorosyncCfgStateNotificationT *notificationBuffer);
+        uint8_t track_flags,
+        const corosync_cfg_state_notification_t *notification_buffer);
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_state_track_stop (
         corosync_cfg_handle_t cfg_handle);
 
+
+cs_error_t
+corosync_cfg_get_node_addrs (
+	corosync_cfg_handle_t cfg_handle,
+	int nodeid,
+	int max_addrs,
+	int *num_addrs,
+	corosync_cfg_node_address_t *addrs);
+
+
 #ifdef __cplusplus
 }
 #endif
diff -Naurd corosync-0.92/include/corosync/confdb.h corosync-trunk/include/corosync/confdb.h
--- corosync-0.92/include/corosync/confdb.h	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/include/corosync/confdb.h	2008-11-06 22:49:07.000000000 +0100
@@ -34,6 +34,7 @@
 #ifndef COROSYNC_CONFDB_H_DEFINED
 #define COROSYNC_CONFDB_H_DEFINED
 
+#include <corosync/corotypes.h>
 /**
  * @addtogroup confdb_corosync
  *
@@ -44,33 +45,11 @@
 #define OBJECT_PARENT_HANDLE 0
 
 typedef enum {
-	CONFDB_DISPATCH_ONE,
-	CONFDB_DISPATCH_ALL,
-	CONFDB_DISPATCH_BLOCKING
-} confdb_dispatch_t;
-
-typedef enum {
 	CONFDB_TRACK_DEPTH_ONE,
 	CONFDB_TRACK_DEPTH_RECURSIVE
 } confdb_track_depth_t;
 
 typedef enum {
-	CONFDB_OK = 1,
-	CONFDB_ERR_LIBRARY = 2,
-	CONFDB_ERR_TIMEOUT = 5,
-	CONFDB_ERR_TRY_AGAIN = 6,
-	CONFDB_ERR_INVALID_PARAM = 7,
-	CONFDB_ERR_NO_MEMORY = 8,
-	CONFDB_ERR_BAD_HANDLE = 9,
-	CONFDB_ERR_ACCESS = 11,
-	CONFDB_ERR_NOT_EXIST = 12,
-	CONFDB_ERR_EXIST = 14,
-	CONFDB_ERR_CONTEXT_NOT_FOUND = 17,
-	CONFDB_ERR_NOT_SUPPORTED = 20,
-	CONFDB_ERR_SECURITY = 29,
-} confdb_error_t;
-
-typedef enum {
 	OBJECT_KEY_CREATED,
 	OBJECT_KEY_REPLACED,
 	OBJECT_KEY_DELETED
@@ -112,28 +91,28 @@
 /*
  * Create a new confdb connection
  */
-confdb_error_t confdb_initialize (
+cs_error_t confdb_initialize (
 	confdb_handle_t *handle,
 	confdb_callbacks_t *callbacks);
 
 /*
  * Close the confdb handle
  */
-confdb_error_t confdb_finalize (
+cs_error_t confdb_finalize (
 	confdb_handle_t handle);
 
 
 /*
  * Write back the configuration
  */
-confdb_error_t confdb_write (
+cs_error_t confdb_write (
 	confdb_handle_t handle,
 	char *error_text);
 
 /*
  * Reload the configuration
  */
-confdb_error_t confdb_reload (
+cs_error_t confdb_reload (
 	confdb_handle_t handle,
 	int flush,
 	char *error_text);
@@ -142,43 +121,43 @@
  * 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 (
+cs_error_t confdb_fd_get (
 	confdb_handle_t handle,
 	int *fd);
 
 /*
  * Dispatch configuration changes
  */
-confdb_error_t confdb_dispatch (
+cs_error_t confdb_dispatch (
 	confdb_handle_t handle,
-	confdb_dispatch_t dispatch_types);
+	cs_dispatch_flags_t dispatch_types);
 
 /*
  * Change notification
  */
-confdb_error_t confdb_track_changes (
+cs_error_t confdb_track_changes (
 	confdb_handle_t handle,
 	unsigned int object_handle,
 	unsigned int flags);
 
-confdb_error_t confdb_stop_track_changes (
+cs_error_t confdb_stop_track_changes (
 	confdb_handle_t handle);
 
 /*
  * Manipulate objects
  */
-confdb_error_t confdb_object_create (
+cs_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 (
+cs_error_t confdb_object_destroy (
 	confdb_handle_t handle,
 	unsigned int object_handle);
 
-confdb_error_t confdb_object_parent_get (
+cs_error_t confdb_object_parent_get (
 	confdb_handle_t handle,
 	unsigned int object_handle,
 	unsigned int *parent_object_handle);
@@ -186,7 +165,7 @@
 /*
  * Manipulate keys
  */
-confdb_error_t confdb_key_create (
+cs_error_t confdb_key_create (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -194,7 +173,7 @@
 	void *value,
 	int value_len);
 
-confdb_error_t confdb_key_delete (
+cs_error_t confdb_key_delete (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -205,7 +184,7 @@
 /*
  * Key queries
  */
-confdb_error_t confdb_key_get (
+cs_error_t confdb_key_get (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -213,7 +192,7 @@
 	void *value,
 	int *value_len);
 
-confdb_error_t confdb_key_replace (
+cs_error_t confdb_key_replace (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -223,14 +202,14 @@
 	void *new_value,
 	int new_value_len);
 
-confdb_error_t confdb_key_increment (
+cs_error_t confdb_key_increment (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
 	int key_name_len,
 	unsigned int *value);
 
-confdb_error_t confdb_key_decrement (
+cs_error_t confdb_key_decrement (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -243,44 +222,44 @@
  * a quick way of finding a specific object,
  * "iter" returns each object in sequence.
  */
-confdb_error_t confdb_object_find_start (
+cs_error_t confdb_object_find_start (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle);
 
-confdb_error_t confdb_object_find (
+cs_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_find_destroy(
+cs_error_t confdb_object_find_destroy(
 	confdb_handle_t handle,
 	unsigned int parent_object_handle);
 
-confdb_error_t confdb_object_iter_start (
+cs_error_t confdb_object_iter_start (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle);
 
-confdb_error_t confdb_object_iter (
+cs_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 confdb_object_iter_destroy(
+cs_error_t confdb_object_iter_destroy(
 	confdb_handle_t handle,
 	unsigned int parent_object_handle);
 
 /*
  * Key iterator
  */
-confdb_error_t confdb_key_iter_start (
+cs_error_t confdb_key_iter_start (
 	confdb_handle_t handle,
 	unsigned int object_handle);
 
-confdb_error_t confdb_key_iter (
+cs_error_t confdb_key_iter (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
diff -Naurd corosync-0.92/include/corosync/corotypes.h corosync-trunk/include/corosync/corotypes.h
--- corosync-0.92/include/corosync/corotypes.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/corotypes.h	2008-11-07 02:34:43.000000000 +0100
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2008 Allied Telesis Labs.
+ *
+ * All rights reserved.
+ *
+ * Author: Angus Salkeld (ahsalkeld@gmail.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 COROTYPES_H_DEFINED
+#define COROTYPES_H_DEFINED
+
+#ifndef COROSYNC_SOLARIS
+#include <stdint.h>
+#else
+#include <sys/types.h>
+#endif
+
+typedef int64_t cs_time_t;
+
+#define CS_FALSE 0
+#define CS_TRUE !CS_FALSE
+#define CS_MAX_NAME_LENGTH 256
+#define CS_TIME_END    ((cs_time_t)0x7FFFFFFFFFFFFFFFULL)
+
+typedef struct {
+   uint16_t length;
+   uint8_t value[CS_MAX_NAME_LENGTH];
+} cs_name_t;
+
+typedef struct {
+   char releaseCode;
+   unsigned char majorVersion;
+   unsigned char minorVersion;
+} cs_version_t;
+
+typedef enum {
+	CS_DISPATCH_ONE = 1,
+	CS_DISPATCH_ALL = 2,
+	CS_DISPATCH_BLOCKING = 3
+} cs_dispatch_flags_t;
+
+#define CS_TRACK_CURRENT 0x01
+#define CS_TRACK_CHANGES 0x02
+#define CS_TRACK_CHANGES_ONLY 0x04
+
+typedef enum {
+   CS_OK = 1,
+   CS_ERR_LIBRARY = 2,
+   CS_ERR_VERSION = 3,
+   CS_ERR_INIT = 4,
+   CS_ERR_TIMEOUT = 5,
+   CS_ERR_TRY_AGAIN = 6,
+   CS_ERR_INVALID_PARAM = 7,
+   CS_ERR_NO_MEMORY = 8,
+   CS_ERR_BAD_HANDLE = 9,
+   CS_ERR_BUSY = 10,
+   CS_ERR_ACCESS = 11,
+   CS_ERR_NOT_EXIST = 12,
+   CS_ERR_NAME_TOO_LONG = 13,
+   CS_ERR_EXIST = 14,
+   CS_ERR_NO_SPACE = 15,
+   CS_ERR_INTERRUPT = 16,
+   CS_ERR_NAME_NOT_FOUND = 17,
+   CS_ERR_NO_RESOURCES = 18,
+   CS_ERR_NOT_SUPPORTED = 19,
+   CS_ERR_BAD_OPERATION = 20,
+   CS_ERR_FAILED_OPERATION = 21,
+   CS_ERR_MESSAGE_ERROR = 22,
+   CS_ERR_QUEUE_FULL = 23,
+   CS_ERR_QUEUE_NOT_AVAILABLE = 24,
+   CS_ERR_BAD_FLAGS = 25,
+   CS_ERR_TOO_BIG = 26,
+   CS_ERR_NO_SECTIONS = 27,
+   CS_ERR_CONTEXT_NOT_FOUND = 28,
+   CS_ERR_TOO_MANY_GROUPS = 30
+} cs_error_t;
+
+
+/*
+ * DEPRECATED
+ */
+#define EVS_DISPATCH_ONE			CS_DISPATCH_ONE
+#define EVS_DISPATCH_ALL			CS_DISPATCH_ALL
+#define EVS_DISPATCH_BLOCKING		CS_DISPATCH_BLOCKING
+#define EVS_OK						CS_OK
+#define EVS_ERR_LIBRARY				CS_ERR_ERR_LIBRARY
+#define EVS_ERR_TIMEOUT				CS_ERR_TIMEOUT
+#define EVS_ERR_TRY_AGAIN			CS_ERR_TRY_AGAIN
+#define EVS_ERR_INVALID_PARAM		CS_ERR_INVALID_PARAM
+#define EVS_ERR_NO_MEMORY			CS_ERR_NO_MEMORY
+#define EVS_ERR_BAD_HANDLE			CS_ERR_BAD_HANDLE
+#define EVS_ERR_ACCESS				CS_ERR_ACCESS
+#define EVS_ERR_NOT_EXIST			CS_ERR_NOT_EXIST
+#define EVS_ERR_EXIST				CS_ERR_EXIST
+#define EVS_ERR_NOT_SUPPORTED		CS_ERR_NOT_SUPPORTED
+#define EVS_ERR_SECURITY			CS_ERR_SECURITY
+#define EVS_ERR_TOO_MANY_GROUPS		CS_ERR_TOO_MANY_GROUPS
+#define evs_error_t cs_error_t
+
+#define CPG_DISPATCH_ONE			CS_DISPATCH_ONE
+#define CPG_DISPATCH_ALL			CS_DISPATCH_ALL
+#define CPG_DISPATCH_BLOCKING		CS_DISPATCH_BLOCKING
+#define CPG_OK						CS_OK
+#define CPG_ERR_LIBRARY				CS_ERR_ERR_LIBRARY
+#define CPG_ERR_TIMEOUT				CS_ERR_TIMEOUT
+#define CPG_ERR_TRY_AGAIN			CS_ERR_TRY_AGAIN
+#define CPG_ERR_INVALID_PARAM		CS_ERR_INVALID_PARAM
+#define CPG_ERR_NO_MEMORY			CS_ERR_NO_MEMORY
+#define CPG_ERR_BAD_HANDLE			CS_ERR_BAD_HANDLE
+#define CPG_ERR_ACCESS				CS_ERR_ACCESS
+#define CPG_ERR_NOT_EXIST			CS_ERR_NOT_EXIST
+#define CPG_ERR_EXIST				CS_ERR_EXIST
+#define CPG_ERR_NOT_SUPPORTED		CS_ERR_NOT_SUPPORTED
+#define CPG_ERR_SECURITY			CS_ERR_SECURITY
+#define cpg_error_t cs_error_t
+
+#define CONFDB_DISPATCH_ONE			CS_DISPATCH_ONE
+#define CONFDB_DISPATCH_ALL			CS_DISPATCH_ALL
+#define CONFDB_DISPATCH_BLOCKING	CS_DISPATCH_BLOCKING
+#define CONFDB_OK					CS_OK
+#define CONFDB_ERR_LIBRARY			CS_ERR_ERR_LIBRARY
+#define CONFDB_ERR_TIMEOUT			CS_ERR_TIMEOUT
+#define CONFDB_ERR_TRY_AGAIN		CS_ERR_TRY_AGAIN
+#define CONFDB_ERR_INVALID_PARAM	CS_ERR_INVALID_PARAM
+#define CONFDB_ERR_NO_MEMORY		CS_ERR_NO_MEMORY
+#define CONFDB_ERR_BAD_HANDLE		CS_ERR_BAD_HANDLE
+#define CONFDB_ERR_ACCESS			CS_ERR_ACCESS
+#define CONFDB_ERR_NOT_EXIST		CS_ERR_NOT_EXIST
+#define CONFDB_ERR_EXIST			CS_ERR_EXIST
+#define CONFDB_ERR_NOT_SUPPORTED	CS_ERR_NOT_SUPPORTED
+#define CONFDB_ERR_SECURITY			CS_ERR_SECURITY
+#define confdb_error_t cs_error_t
+
+#define QUORUM_DISPATCH_ONE			CS_DISPATCH_ONE
+#define QUORUM_DISPATCH_ALL			CS_DISPATCH_ALL
+#define QUORUM_DISPATCH_BLOCKING	CS_DISPATCH_BLOCKING
+#define QUORUM_OK					CS_OK
+#define QUORUM_ERR_LIBRARY			CS_ERR_ERR_LIBRARY
+#define QUORUM_ERR_TIMEOUT			CS_ERR_TIMEOUT
+#define QUORUM_ERR_TRY_AGAIN		CS_ERR_TRY_AGAIN
+#define QUORUM_ERR_INVALID_PARAM	CS_ERR_INVALID_PARAM
+#define QUORUM_ERR_NO_MEMORY		CS_ERR_NO_MEMORY
+#define QUORUM_ERR_BAD_HANDLE		CS_ERR_BAD_HANDLE
+#define QUORUM_ERR_ACCESS			CS_ERR_ACCESS
+#define QUORUM_ERR_NOT_EXIST		CS_ERR_NOT_EXIST
+#define QUORUM_ERR_EXIST			CS_ERR_EXIST
+#define QUORUM_ERR_NOT_SUPPORTED	CS_ERR_NOT_SUPPORTED
+#define QUORUM_ERR_SECURITY			CS_ERR_SECURITY
+#define quorum_error_t cs_error_t
+
+#endif
+
diff -Naurd corosync-0.92/include/corosync/cpg.h corosync-trunk/include/corosync/cpg.h
--- corosync-0.92/include/corosync/cpg.h	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/include/corosync/cpg.h	2008-11-06 22:49:07.000000000 +0100
@@ -35,6 +35,7 @@
 #define COROSYNC_CPG_H_DEFINED
 
 #include <netinet/in.h>
+#include <corosync/corotypes.h>
 
 /**
  * @addtogroup cpg_corosync
@@ -44,12 +45,6 @@
 typedef uint64_t cpg_handle_t;
 
 typedef enum {
-	CPG_DISPATCH_ONE,
-	CPG_DISPATCH_ALL,
-	CPG_DISPATCH_BLOCKING
-} cpg_dispatch_t;
-
-typedef enum {
 	CPG_TYPE_UNORDERED, /* not implemented */
 	CPG_TYPE_FIFO,		/* same as agreed */
 	CPG_TYPE_AGREED,
@@ -61,21 +56,6 @@
 	CPG_FLOW_CONTROL_ENABLED	/* flow control is enabled - new messages should not be sent */
 } cpg_flow_control_state_t;
 
-typedef enum {
-	CPG_OK = 1,
-	CPG_ERR_LIBRARY = 2,
-	CPG_ERR_TIMEOUT = 5,
-	CPG_ERR_TRY_AGAIN = 6,
-	CPG_ERR_INVALID_PARAM = 7,
-	CPG_ERR_NO_MEMORY = 8,
-	CPG_ERR_BAD_HANDLE = 9,
-	CPG_ERR_ACCESS = 11,
-	CPG_ERR_NOT_EXIST = 12,
-	CPG_ERR_EXIST = 14,
-	CPG_ERR_NOT_SUPPORTED = 20,
-	CPG_ERR_SECURITY = 29,
-	CPG_ERR_TOO_MANY_GROUPS=30
-} cpg_error_t;
 
 typedef enum {
 	CPG_REASON_JOIN = 1,
@@ -132,32 +112,32 @@
 /*
  * Create a new cpg connection
  */
-cpg_error_t cpg_initialize (
+cs_error_t cpg_initialize (
 	cpg_handle_t *handle,
 	cpg_callbacks_t *callbacks);
 
 /*
  * Close the cpg handle
  */
-cpg_error_t cpg_finalize (
+cs_error_t cpg_finalize (
 	cpg_handle_t handle);
 
 /*
  * Get a file descriptor on which to poll.  cpg_handle_t is NOT a
  * file descriptor and may not be used directly.
  */
-cpg_error_t cpg_fd_get (
+cs_error_t cpg_fd_get (
 	cpg_handle_t handle,
 	int *fd);
 
 /* 
  * Get and set contexts for a CPG handle
  */
-cpg_error_t cpg_context_get (
+cs_error_t cpg_context_get (
 	cpg_handle_t handle,
 	void **context);
 
-cpg_error_t cpg_context_set (
+cs_error_t cpg_context_set (
 	cpg_handle_t handle,
 	void *context);
 
@@ -165,9 +145,9 @@
 /*
  * Dispatch messages and configuration changes
  */
-cpg_error_t cpg_dispatch (
+cs_error_t cpg_dispatch (
 	cpg_handle_t handle,
-	cpg_dispatch_t dispatch_types);
+	cs_dispatch_flags_t dispatch_types);
 
 /*
  * Join one or more groups.
@@ -175,14 +155,14 @@
  * group that has been joined on handle handle.  Any message multicasted
  * to a group that has been previously joined will be delivered in cpg_dispatch
  */
-cpg_error_t cpg_join (
+cs_error_t cpg_join (
 	cpg_handle_t handle,
 	struct cpg_name *group);
 
 /*
  * Leave one or more groups
  */
-cpg_error_t cpg_leave (
+cs_error_t cpg_leave (
 	cpg_handle_t handle,
 	struct cpg_name *group);
 
@@ -191,7 +171,7 @@
  * The iovec described by iovec will be multicasted to all groups joined with
  * the cpg_join interface for handle.
  */
-cpg_error_t cpg_mcast_joined (
+cs_error_t cpg_mcast_joined (
 	cpg_handle_t handle,
 	cpg_guarantee_t guarantee,
 	struct iovec *iovec,
@@ -200,21 +180,21 @@
 /*
  * Get membership information from cpg
  */
-cpg_error_t cpg_membership_get (
+cs_error_t cpg_membership_get (
 	cpg_handle_t handle,
 	struct cpg_name *groupName,
 	struct cpg_address *member_list,
 	int *member_list_entries);
 
-cpg_error_t cpg_local_get (
+cs_error_t cpg_local_get (
 	cpg_handle_t handle,
 	unsigned int *local_nodeid);
 
-cpg_error_t cpg_groups_get (
+cs_error_t cpg_groups_get (
 	cpg_handle_t handle,
 	unsigned int *num_groups);
 
-cpg_error_t cpg_flow_control_state_get (
+cs_error_t cpg_flow_control_state_get (
 	cpg_handle_t handle,
 	cpg_flow_control_state_t *flow_control_enabled);
 
diff -Naurd corosync-0.92/include/corosync/engine/coroapi.h corosync-trunk/include/corosync/engine/coroapi.h
--- corosync-0.92/include/corosync/engine/coroapi.h	2008-09-17 21:15:00.000000000 +0200
+++ corosync-trunk/include/corosync/engine/coroapi.h	2009-01-20 14:19:05.000000000 +0100
@@ -41,7 +41,7 @@
 
 typedef void * corosync_timer_handle_t;
 
-typedef unsigned int corosync_tpg_handle;
+typedef unsigned int cs_tpg_handle;
 
 struct corosync_tpg_group {
 	void *group;
@@ -88,17 +88,36 @@
 };
 #endif
 
-enum corosync_lib_flow_control {
-	COROSYNC_LIB_FLOW_CONTROL_REQUIRED = 1,
-	COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED = 2
+#if !defined(TOTEM_CALLBACK_TOKEN_TYPE)
+enum totem_callback_token_type {
+	TOTEM_CALLBACK_TOKEN_RECEIVED = 1,
+	TOTEM_CALLBACK_TOKEN_SENT = 2
+};
+#endif
+
+enum cs_lib_flow_control {
+	CS_LIB_FLOW_CONTROL_REQUIRED = 1,
+	CS_LIB_FLOW_CONTROL_NOT_REQUIRED = 2
+};
+#define corosync_lib_flow_control cs_lib_flow_control
+#define COROSYNC_LIB_FLOW_CONTROL_REQUIRED CS_LIB_FLOW_CONTROL_REQUIRED
+#define COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+
+enum cs_lib_allow_inquorate {
+	CS_LIB_DISALLOW_INQUORATE = 0, /* default */
+	CS_LIB_ALLOW_INQUORATE = 1
 };
 
 #if !defined (COROSYNC_FLOW_CONTROL_STATE)
-enum corosync_flow_control_state {
-	COROSYNC_FLOW_CONTROL_STATE_DISABLED,
-	COROSYNC_FLOW_CONTROL_STATE_ENABLED
+enum cs_flow_control_state {
+	CS_FLOW_CONTROL_STATE_DISABLED,
+	CS_FLOW_CONTROL_STATE_ENABLED
 };
-#endif
+#define corosync_flow_control_state cs_flow_control_state
+#define CS_FLOW_CONTROL_STATE_DISABLED CS_FLOW_CONTROL_STATE_DISABLED
+#define CS_FLOW_CONTROL_STATE_ENABLED CS_FLOW_CONTROL_STATE_ENABLED
+
+#endif /* COROSYNC_FLOW_CONTROL_STATE */
 
 typedef enum {
 	COROSYNC_FATAL_ERROR_EXIT = -1,
@@ -109,7 +128,8 @@
 	COROSYNC_DYNAMICLOAD = -12,
 	COROSYNC_OUT_OF_MEMORY = -15,
 	COROSYNC_FATAL_ERR = -16
-} corosync_fatal_error_t;
+} cs_fatal_error_t;
+#define corosync_fatal_error_t cs_fatal_error_t;
 
 #ifndef OBJECT_PARENT_HANDLE
 
@@ -125,6 +145,7 @@
 	int key_len;
 	int (*validate_callback) (void *key, int key_len, void *value, int value_len);
 };
+/* deprecated */
 
 typedef enum {
 	OBJECT_TRACK_DEPTH_ONE,
@@ -137,6 +158,12 @@
 	OBJECT_KEY_DELETED
 } object_change_type_t;
 
+typedef enum {
+        OBJDB_RELOAD_NOTIFY_START,
+        OBJDB_RELOAD_NOTIFY_END,
+	OBJDB_RELOAD_NOTIFY_FAILED
+} objdb_reload_notify_type_t;
+
 typedef void (*object_key_change_notify_fn_t)(object_change_type_t change_type,
 											  unsigned int parent_object_handle,
 											  unsigned int object_handle,
@@ -159,8 +186,30 @@
 											object_change_type_t type,
 											void * priv_data_pt);
 
+typedef void (*object_reload_notify_fn_t) (objdb_reload_notify_type_t, int flush,
+											void *priv_data_pt);
+
 #endif /* OBJECT_PARENT_HANDLE_DEFINED */
 
+#ifndef QUORUM_H_DEFINED
+typedef void (*quorum_callback_fn_t) (int quorate, void *context);
+
+struct quorum_callin_functions
+{
+	int (*quorate) (void);
+	int (*register_callback) (quorum_callback_fn_t callback_fn, void *context);
+	int (*unregister_callback) (quorum_callback_fn_t callback_fn, void *context);
+};
+
+typedef void (*sync_callback_fn_t) (
+	unsigned int *view_list,
+	int view_list_entries,
+	int primary_designated,
+	struct memb_ring_id *ring_id);
+
+#endif /* QUORUM_H_DEFINED */
+
+
 struct corosync_api_v1 {
 	/*
 	 * Object and configuration APIs
@@ -280,12 +329,14 @@
 		object_key_change_notify_fn_t key_change_notify_fn,
 		object_create_notify_fn_t object_create_notify_fn,
 		object_destroy_notify_fn_t object_destroy_notify_fn,
+		object_reload_notify_fn_t object_reload_notify_fn,
 		void * priv_data_pt);
 
 	void (*object_track_stop) (
 		object_key_change_notify_fn_t key_change_notify_fn,
 		object_create_notify_fn_t object_create_notify_fn,
 		object_destroy_notify_fn_t object_destroy_notify_fn,
+		object_reload_notify_fn_t object_reload_notify_fn,
 		void * priv_data_pt);
 
 	int (*object_write_config) (char **error_string);
@@ -357,7 +408,7 @@
 		int id_len,
 		void (*flow_control_state_set_fn)
 			(void *context,
-				enum corosync_flow_control_state flow_control_state_set),
+				enum cs_flow_control_state flow_control_state_set),
 		void *context);
 
 	void (*ipc_fc_destroy) (
@@ -373,7 +424,7 @@
 	/*
 	 * Totem APIs
 	 */
-	int (*totem_nodeid_get) (void);
+	unsigned int (*totem_nodeid_get) (void);
 
 	int (*totem_family_get) (void);
 
@@ -393,12 +444,20 @@
 
 	char *(*totem_ip_print) (struct totem_ip_address *addr);
 
+
+	int (*totem_callback_token_create) (
+		void **handle_out,
+		enum totem_callback_token_type type,
+		int delete,
+		int (*callback_fn) (enum totem_callback_token_type type, void *),
+		void *data);
+
 	/*
 	 * Totem open process groups API for those service engines
 	 * wanting their own groups
 	 */
 	int (*tpg_init) (
-		corosync_tpg_handle *handle,
+		cs_tpg_handle *handle,
 
 		void (*deliver_fn) (
 			unsigned int nodeid,
@@ -414,31 +473,31 @@
 			struct memb_ring_id *ring_id));
 
 	int (*tpg_exit) (
-       		corosync_tpg_handle handle);
+       		cs_tpg_handle handle);
 
 	int (*tpg_join) (
-		corosync_tpg_handle handle,
+		cs_tpg_handle handle,
 		struct corosync_tpg_group *groups,
 		int gruop_cnt);
 
 	int (*tpg_leave) (
-		corosync_tpg_handle handle,
+		cs_tpg_handle handle,
 		struct corosync_tpg_group *groups,
 		int gruop_cnt);
 
 	int (*tpg_joined_mcast) (
-		corosync_tpg_handle handle,
+		cs_tpg_handle handle,
 		struct iovec *iovec,
 		int iov_len,
 		int guarantee);
 
 	int (*tpg_joined_send_ok) (
-		corosync_tpg_handle handle,
+		cs_tpg_handle handle,
 		struct iovec *iovec,
 		int iov_len);
 
 	int (*tpg_groups_mcast) (
-		corosync_tpg_handle handle,
+		cs_tpg_handle handle,
 		int guarantee,
 		struct corosync_tpg_group *groups,
 		int groups_cnt,
@@ -446,7 +505,7 @@
 		int iov_len);
 
 	int (*tpg_groups_send_ok) (
-		corosync_tpg_handle handle,
+		cs_tpg_handle handle,
 		struct corosync_tpg_group *groups,
 		int groups_cnt,
 		struct iovec *iovec,
@@ -456,6 +515,19 @@
 		char *service_name);
 
 	/*
+	 * User plugin-callable functions for quorum
+	 */
+	int (*quorum_is_quorate) (void);
+	int (*quorum_register_callback) (quorum_callback_fn_t callback_fn, void *context);
+	int (*quorum_unregister_callback) (quorum_callback_fn_t callback_fn, void *context);
+
+	/*
+	 * This one is for the quorum management plugin's use
+	 */
+	int (*quorum_initialize)(struct quorum_callin_functions *fns,
+				 sync_callback_fn_t *sync_callback_fn);
+
+	/*
 	 * Plugin loading and unloading
 	 */
 	int (*plugin_interface_reference) (
@@ -485,7 +557,7 @@
 	 */
 	void (*error_memory_failure) (void);
 #define corosync_fatal_error(err) api->fatal_error ((err), __FILE__, __LINE__)
-	void (*fatal_error) (corosync_fatal_error_t err, const char *file, unsigned int line);
+	void (*fatal_error) (cs_fatal_error_t err, const char *file, unsigned int line);
 };
 
 #define SERVICE_ID_MAKE(a,b) ( ((a)<<16) | (b) )
@@ -496,7 +568,7 @@
 	void (*lib_handler_fn) (void *conn, void *msg);
 	int response_size;
 	int response_id;
-	enum corosync_lib_flow_control flow_control;
+	enum cs_lib_flow_control flow_control;
 };
 
 struct corosync_exec_handler {
@@ -512,7 +584,8 @@
 	char *name;
 	unsigned short id;
 	unsigned int private_data_size;
-	enum corosync_lib_flow_control flow_control;
+	enum cs_lib_flow_control flow_control;
+	enum cs_lib_allow_inquorate allow_inquorate;
 	int (*exec_init_fn) (struct corosync_api_v1 *);
 	int (*exec_exit_fn) (void);
 	void (*exec_dump_fn) (void);
diff -Naurd corosync-0.92/include/corosync/engine/logsys.h corosync-trunk/include/corosync/engine/logsys.h
--- corosync-0.92/include/corosync/engine/logsys.h	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/include/corosync/engine/logsys.h	2009-01-16 09:59:09.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002-2004 MontaVista Software, Inc.
- * Copyright (c) 2006-2007 Red Hat, Inc.
+ * Copyright (c) 2006-2008 Red Hat, Inc.
  *
  * Author: Steven Dake (sdake@redhat.com)
  * Author: Lon Hohberger (lhh@redhat.com)
@@ -41,21 +41,14 @@
 #include <assert.h>
 
 /*
- * MODE_OUTPUT_SYSLOG_* modes are mutually exclusive
+ * All of the LOG_MODE's can be ORed together for combined behavior
  */
 #define LOG_MODE_OUTPUT_FILE		(1<<0)
 #define LOG_MODE_OUTPUT_STDERR		(1<<1)
-#define LOG_MODE_OUTPUT_SYSLOG_THREADED	(1<<2)
-#define LOG_MODE_OUTPUT_SYSLOG_LOSSY	(1<<3)
-#define LOG_MODE_OUTPUT_SYSLOG_BLOCKING	(1<<4)
-#define LOG_MODE_DISPLAY_PRIORITY	(1<<5)
-#define LOG_MODE_DISPLAY_FILELINE	(1<<6)
-#define LOG_MODE_DISPLAY_TIMESTAMP	(1<<7)
-#define LOG_MODE_BUFFER_BEFORE_CONFIG	(1<<8)
-#define LOG_MODE_FLUSH_AFTER_CONFIG	(1<<9)
-#define LOG_MODE_SHORT_FILELINE		(1<<10)
-#define LOG_MODE_NOSUBSYS		(1<<11)
-#define LOG_MODE_FILTER_DEBUG_FROM_SYSLOG	(1<<12)
+#define LOG_MODE_OUTPUT_SYSLOG		(1<<3)
+#define LOG_MODE_NOSUBSYS		(1<<4)
+#define LOG_MODE_FORK			(1<<5)
+#define LOG_MODE_THREADED		(1<<6)
 
 /*
  * Log priorities, compliant with syslog and SA Forum Log spec.
@@ -71,37 +64,23 @@
 #define LOG_LEVEL_DEBUG			LOG_DEBUG
 
 /*
-** Log tags, used by _logsys_trace macros, uses 32 bits => 32 different tags
-*/	
-#define LOGSYS_TAG_LOG	    		(1<<0)
-#define LOGSYS_TAG_ENTER		(1<<1)
-#define LOGSYS_TAG_LEAVE		(1<<2)
-#define LOGSYS_TAG_TRACE1		(1<<3)
-#define LOGSYS_TAG_TRACE2		(1<<4)
-#define LOGSYS_TAG_TRACE3		(1<<5)
-#define LOGSYS_TAG_TRACE4		(1<<6)
-#define LOGSYS_TAG_TRACE5		(1<<7)
-#define LOGSYS_TAG_TRACE6		(1<<8)
-#define LOGSYS_TAG_TRACE7		(1<<9)
-#define LOGSYS_TAG_TRACE8		(1<<10)
+ * The tag masks are all mutually exclusive
+ */	
+#define LOGSYS_TAG_LOG			(0xff<<28)
+#define LOGSYS_TAG_ENTER		(1<<27)
+#define LOGSYS_TAG_LEAVE		(1<<26)
+#define LOGSYS_TAG_TRACE1		(1<<25)
+#define LOGSYS_TAG_TRACE2		(1<<24)
+#define LOGSYS_TAG_TRACE3		(1<<23)
+#define LOGSYS_TAG_TRACE4		(1<<22)
+#define LOGSYS_TAG_TRACE5		(1<<21)
+#define LOGSYS_TAG_TRACE6		(1<<20)
+#define LOGSYS_TAG_TRACE7		(1<<19)
+#define LOGSYS_TAG_TRACE8		(1<<18)
 
 /*
  * External API
  */
-
-struct logsys_logger {
-	char subsys[6];
-	unsigned int priority;
-	unsigned int tags;
-	unsigned int mode;
-};
-
-extern struct logsys_logger logsys_loggers[];
-
-extern int logsys_single_id;
-
-extern inline int logsys_mkpri (int priority, int id);
-
 extern void logsys_config_mode_set (
 	unsigned int mode);
 
@@ -115,6 +94,9 @@
 	char *name,
 	unsigned int facility);
 
+extern void logsys_format_set (
+	char *format);
+
 extern unsigned int logsys_config_subsys_set (
 	const char *subsys,
 	unsigned int tags,
@@ -137,33 +119,60 @@
 extern const char *logsys_priority_name_get (
 	unsigned int priority);
 
+extern int logsys_tag_id_get (
+	const char *name);
+
+extern const char *logsys_tag_name_get (
+	unsigned int tag);
+
+extern void logsys_fork_completed (void);
+
 extern void logsys_flush (void);
 
 extern void logsys_atsegv (void);
 
+extern int logsys_log_rec_store (char *filename);
+
 /*
  * Internal APIs that must be globally exported
  */
-extern unsigned int _logsys_subsys_create (const char *ident,
+extern unsigned int _logsys_subsys_create (
+	const char *ident,
 	unsigned int priority);
 
 extern void _logsys_nosubsys_set (void);
 
-extern int _logsys_wthread_create (void);
+extern int _logsys_rec_init (unsigned int size);
 
-extern void logsys_log_printf (char *file, int line, int priority,
-	char *format, ...) __attribute__((format(printf, 4, 5)));
+extern void _logsys_log_printf (
+	int subsys,
+	char *function_name,
+	char *file_name,
+	int file_line,
+	unsigned int level,
+	char *format,
+	...) __attribute__((format(printf, 6, 7)));
 
-extern void _logsys_log_printf2 (char *file, int line, int priority,
-	int id, char *format, ...) __attribute__((format(printf, 5, 6)));
+extern void _logsys_log_rec (
+	int subsys,
+	char *function_name,
+	char *file_name,
+	int file_line,
+	unsigned int rec_ident,
+	...);
 
-extern void _logsys_trace (char *file, int line, int tag, int id,
-	char *format, ...) __attribute__((format(printf, 5, 6)));
+extern int _logsys_wthread_create (void);
 
+static unsigned int logsys_subsys_id __attribute__((unused)) = -1;
+									
 /*
  * External definitions
  */
-#define LOGSYS_DECLARE_SYSTEM(name,mode,file,facility)			\
+extern void *logsys_rec_end;
+
+#define LOG_REC_END (&logsys_rec_end)
+
+#define LOGSYS_DECLARE_SYSTEM(name,mode,file,facility,format,rec_size)	\
 __attribute__ ((constructor)) static void logsys_system_init (void)	\
 {									\
 	char *error_string;						\
@@ -171,13 +180,11 @@
 	logsys_config_mode_set (mode);					\
 	logsys_config_file_set (&error_string, (file));			\
 	logsys_config_facility_set (name, (facility));			\
-        if (((mode) & LOG_MODE_BUFFER_BEFORE_CONFIG) == 0) {		\
-		_logsys_wthread_create ();				\
-	}								\
+	logsys_format_set (format);					\
+	_logsys_rec_init (rec_size);					\
+	_logsys_wthread_create();					\
 }
 
-static unsigned int logsys_subsys_id __attribute__((unused)) = -1;	\
-
 #define LOGSYS_DECLARE_NOSUBSYS(priority)				\
 __attribute__ ((constructor)) static void logsys_nosubsys_init (void)	\
 {									\
@@ -206,161 +213,88 @@
 			_logsys_subsys_create ((subsys), (priority));	\
 }
 
-#define log_printf(lvl, format, args...) do {				\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if ((lvl) <= logsys_loggers[logsys_subsys_id].priority)	{	\
-		_logsys_log_printf2 (__FILE__, __LINE__, lvl,		\
-			logsys_subsys_id, (format), ##args);		\
-	}								\
-} while(0)
-
-#define dprintf(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_log_printf2 (__FILE__, __LINE__, LOG_DEBUG,	\
-			logsys_subsys_id, (format), ##args);		\
-	}								\
-} while(0)
-
-#define ENTER_VOID() do {						\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_ENTER,	\
-			logsys_subsys_id, ">%s\n", __FUNCTION__);	\
-	}								\
+#define log_rec(rec_ident, args...)					\
+do {									\
+	_logsys_log_rec (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, rec_ident, ##args);		\
 } while(0)
 
-#define ENTER(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_ENTER,	\
-			logsys_subsys_id, ">%s: " format, __FUNCTION__,	\
-			##args);					\
-	}								\
+#define log_printf(lvl, format, args...)				\
+ do {									\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__, __LINE__, lvl, format, ##args);		\
 } while(0)
 
-#define LEAVE_VOID() do {						\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_LEAVE,	\
-			logsys_subsys_id, "<%s\n", __FUNCTION__);	\
-	}								\
+#define ENTER() do {							\
+	_logsys_log_rec (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_ENTER, LOG_REC_END);	\
 } while(0)
 
-#define LEAVE(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_LEAVE,	\
-			logsys_subsys_id, "<%s: " format,		\
-			__FUNCTION__, ##args);				\
-	}								\
+#define LEAVE() do {							\
+	_logsys_log_rec (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_LEAVE, LOG_REC_END);	\
 } while(0)
 
 #define TRACE1(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE1,	\
-			logsys_subsys_id, (format), ##args);		\
-	}								\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE1, format, ##args);\
 } while(0)
 
 #define TRACE2(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE2,	\
-			logsys_subsys_id, (format), ##args);		\
-	}								\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE2, format, ##args);\
 } while(0)
 
-#define TRACE3(format, args...) do { \
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE3,	\
-			logsys_subsys_id, (format), ##args);		\
-    }									\
+#define TRACE3(format, args...) do {					\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE3, format, ##args);\
 } while(0)
 
-#define TRACE4(format, args...) do { \
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE4,	\
-			logsys_subsys_id, (format), ##args);		\
-	}								\
+#define TRACE4(format, args...) do {					\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE4, format, ##args);\
 } while(0)
 
 #define TRACE5(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE5,	\
-		logsys_subsys_id, (format), ##args);			\
-	}								\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE5, format, ##args);\
 } while(0)
 
 #define TRACE6(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE6,	\
-			logsys_subsys_id, (format), ##args);		\
-	}								\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE6, format, ##args);\
 } while(0)
 
 #define TRACE7(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-		_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE7,	\
-			 logsys_subsys_id, (format), ##args);		\
-	}								\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE7, format, ##args);\
 } while(0)
 
 #define TRACE8(format, args...) do {					\
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	if (LOG_LEVEL_DEBUG <= logsys_loggers[logsys_subsys_id].priority) { \
-	_logsys_trace (__FILE__, __LINE__, LOGSYS_TAG_TRACE8,		\
-	 logsys_subsys_id, (format), ##args);				\
-	}								\
+	_logsys_log_printf (logsys_subsys_id, (char *) __FUNCTION__,	\
+		__FILE__,  __LINE__, LOGSYS_TAG_TRACE8, format, ##args);\
 } while(0)
 
-extern void _logsys_config_priority_set (unsigned int id, unsigned int priority);
-
-#define logsys_config_priority_set(priority) do {		        \
-	if (logsys_single_id)						\
-		logsys_subsys_id = 0;					\
-	assert (logsys_subsys_id != -1);				\
-	_logsys_config_priority_set (logsys_subsys_id, priority);       \
-} while(0)
+/*
+ * For one-time programmatic initialization and configuration of logsys
+ * instead of using the DECLARE macros.  These APIs do not allow subsystems
+ */
+int logsys_init (
+	char *name,
+	int mode,
+	int facility,
+	int priority,
+	char *file,
+	char *format,
+	int rec_size);
 
-/* simple, function-based api */
+int logsys_conf (
+	char *name,
+	int mode,
+	int facility,
+	int priority,
+	char *file);
 
-int logsys_init (char *name, int mode, int facility, int priority, char *file);
-int logsys_conf (char *name, int mode, int facility, int priority, char *file);
 void logsys_exit (void);
 
 #endif /* LOGSYS_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/engine/objdb.h corosync-trunk/include/corosync/engine/objdb.h
--- corosync-0.92/include/corosync/engine/objdb.h	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/include/corosync/engine/objdb.h	2008-10-27 09:25:53.000000000 +0100
@@ -51,6 +51,13 @@
 	OBJECT_KEY_DELETED
 } object_change_type_t;
 
+typedef enum {
+        OBJDB_RELOAD_NOTIFY_START,
+        OBJDB_RELOAD_NOTIFY_END,
+	OBJDB_RELOAD_NOTIFY_FAILED
+} objdb_reload_notify_type_t;
+
+
 typedef void (*object_key_change_notify_fn_t)(object_change_type_t change_type,
 											  unsigned int parent_object_handle,
 											  unsigned int object_handle,
@@ -68,6 +75,9 @@
 											void *name_pt, int name_len,
 											void *priv_data_pt);
 
+typedef void (*object_reload_notify_fn_t) (objdb_reload_notify_type_t, int flush,
+											void *priv_data_pt);
+
 struct object_valid {
 	char *object_name;
 	int object_len;
@@ -198,12 +208,14 @@
 		object_key_change_notify_fn_t key_change_notify_fn,
 		object_create_notify_fn_t object_create_notify_fn,
 		object_destroy_notify_fn_t object_destroy_notify_fn,
+		object_reload_notify_fn_t object_reload_notify_fn,
 		void * priv_data_pt);
 
 	void (*object_track_stop) (
 		object_key_change_notify_fn_t key_change_notify_fn,
 		object_create_notify_fn_t object_create_notify_fn,
 		object_destroy_notify_fn_t object_destroy_notify_fn,
+		object_reload_notify_fn_t object_reload_notify_fn,
 		void * priv_data_pt);
 
 	int (*object_write_config) (char **error_string);
diff -Naurd corosync-0.92/include/corosync/engine/quorum.h corosync-trunk/include/corosync/engine/quorum.h
--- corosync-0.92/include/corosync/engine/quorum.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/engine/quorum.h	2008-12-09 14:51:23.000000000 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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 Red Hat Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef QUORUM_H_DEFINED
+#define QUORUM_H_DEFINED
+
+typedef void (*quorum_set_quorate_fn_t) (unsigned int *view_list, int view_list_entries,
+					 int quorate, struct memb_ring_id *);
+
+struct quorum_services_api_ver1 {
+	void (*init) (struct corosync_api_v1 *api, quorum_set_quorate_fn_t);
+};
+#endif /* QUORUM_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/evs.h corosync-trunk/include/corosync/evs.h
--- corosync-0.92/include/corosync/evs.h	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/include/corosync/evs.h	2008-11-06 22:49:07.000000000 +0100
@@ -36,6 +36,7 @@
 
 #include <sys/types.h>
 #include <netinet/in.h>
+#include <corosync/corotypes.h>
 
 /**
  * @defgroup corosync Other API services provided by corosync
@@ -49,34 +50,12 @@
 typedef uint64_t evs_handle_t;
 
 typedef enum {
-	EVS_DISPATCH_ONE,
-	EVS_DISPATCH_ALL,
-	EVS_DISPATCH_BLOCKING
-} evs_dispatch_t;
-
-typedef enum {
 	EVS_TYPE_UNORDERED, /* not implemented */
 	EVS_TYPE_FIFO,		/* same as agreed */
 	EVS_TYPE_AGREED,
 	EVS_TYPE_SAFE		/* not implemented */
 } evs_guarantee_t;
 
-typedef enum {
-	EVS_OK = 1,
-	EVS_ERR_LIBRARY = 2,
-	EVS_ERR_TIMEOUT = 5,
-	EVS_ERR_TRY_AGAIN = 6,
-	EVS_ERR_INVALID_PARAM = 7,
-	EVS_ERR_NO_MEMORY = 8,
-	EVS_ERR_BAD_HANDLE = 9,
-	EVS_ERR_ACCESS = 11,
-	EVS_ERR_NOT_EXIST = 12,
-	EVS_ERR_EXIST = 14,
-	EVS_ERR_NOT_SUPPORTED = 20,
-	EVS_ERR_SECURITY = 29,
-	EVS_ERR_TOO_MANY_GROUPS=30
-} evs_error_t;
-
 #define TOTEMIP_ADDRLEN (sizeof(struct in6_addr))
 
 /** These are the things that get passed around */
@@ -110,30 +89,30 @@
 /*
  * Create a new evs connection
  */
-evs_error_t evs_initialize (
+cs_error_t evs_initialize (
 	evs_handle_t *handle,
 	evs_callbacks_t *callbacks);
 
 /*
  * Close the evs handle
  */
-evs_error_t evs_finalize (
+cs_error_t evs_finalize (
 	evs_handle_t handle);
 
 /*
  * Get a file descriptor on which to poll.  evs_handle_t is NOT a
  * file descriptor and may not be used directly.
  */
-evs_error_t evs_fd_get (
+cs_error_t evs_fd_get (
 	evs_handle_t handle,
 	int *fd);
 
 /*
  * Dispatch messages and configuration changes
  */
-evs_error_t evs_dispatch (
+cs_error_t evs_dispatch (
 	evs_handle_t handle,
-	evs_dispatch_t dispatch_types);
+	cs_dispatch_flags_t dispatch_types);
 
 /*
  * Join one or more groups.
@@ -141,7 +120,7 @@
  * group that has been joined on handle handle.  Any message multicasted
  * to a group that has been previously joined will be delivered in evs_dispatch
  */
-evs_error_t evs_join (
+cs_error_t evs_join (
 	evs_handle_t handle,
 	struct evs_group *groups,
 	int group_cnt);
@@ -149,7 +128,7 @@
 /*
  * Leave one or more groups
  */
-evs_error_t evs_leave (
+cs_error_t evs_leave (
 	evs_handle_t handle,
 	struct evs_group *groups,
 	int group_cnt);
@@ -159,7 +138,7 @@
  * The iovec described by iovec will be multicasted to all groups joined with
  * the evs_join interface for handle.
  */
-evs_error_t evs_mcast_joined (
+cs_error_t evs_mcast_joined (
 	evs_handle_t handle,
 	evs_guarantee_t guarantee,
 	struct iovec *iovec,
@@ -170,7 +149,7 @@
  * Messages will be multicast to groups specified in the api call and not those
  * that have been joined (unless they are in the groups parameter).
  */
-evs_error_t evs_mcast_groups (
+cs_error_t evs_mcast_groups (
 	evs_handle_t handle,
 	evs_guarantee_t guarantee,
 	struct evs_group *groups,
@@ -181,7 +160,7 @@
 /*
  * Get membership information from evs
  */
-evs_error_t evs_membership_get (
+cs_error_t evs_membership_get (
 	evs_handle_t handle,
 	unsigned int *local_nodeid,
 	unsigned int *member_list,
diff -Naurd corosync-0.92/include/corosync/ipc_cfg.h corosync-trunk/include/corosync/ipc_cfg.h
--- corosync-0.92/include/corosync/ipc_cfg.h	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/include/corosync/ipc_cfg.h	2009-01-19 09:31:21.000000000 +0100
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 MontaVista Software, Inc.
+ * Copyright (c) 2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -35,8 +36,8 @@
 #define AIS_IPC_CFG_H_DEFINED
 
 #include <netinet/in.h>
+#include <corosync/corotypes.h>
 #include "ipc_gen.h"
-#include "saAis.h"
 #include "cfg.h"
 
 enum req_lib_cfg_types {
@@ -47,7 +48,11 @@
         MESSAGE_REQ_CFG_ADMINISTRATIVESTATESET = 4,
         MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET = 5,
         MESSAGE_REQ_CFG_SERVICELOAD = 6,
-        MESSAGE_REQ_CFG_SERVICEUNLOAD = 7
+        MESSAGE_REQ_CFG_SERVICEUNLOAD = 7,
+	MESSAGE_REQ_CFG_KILLNODE = 8,
+	MESSAGE_REQ_CFG_TRYSHUTDOWN = 9,
+	MESSAGE_REQ_CFG_REPLYTOSHUTDOWN = 10,
+	MESSAGE_REQ_CFG_GET_NODE_ADDRS = 11
 };
 
 enum res_lib_cfg_types {
@@ -58,13 +63,17 @@
         MESSAGE_RES_CFG_ADMINISTRATIVESTATESET = 4,
         MESSAGE_RES_CFG_ADMINISTRATIVESTATEGET = 5,
         MESSAGE_RES_CFG_SERVICELOAD = 6,
-        MESSAGE_RES_CFG_SERVICEUNLOAD = 7
+        MESSAGE_RES_CFG_SERVICEUNLOAD = 7,
+	MESSAGE_RES_CFG_KILLNODE = 8,
+	MESSAGE_RES_CFG_TRYSHUTDOWN = 9,
+	MESSAGE_RES_CFG_TESTSHUTDOWN = 10,
+	MESSAGE_RES_CFG_GET_NODE_ADDRS = 11
 };
 
 struct req_lib_cfg_statetrack {
 	mar_req_header_t header;
-	SaUint8T trackFlags;
-	CorosyncCfgStateNotificationT *notificationBufferAddress;
+	uint8_t track_flags;
+	corosync_cfg_state_notification_t *notification_buffer_address;
 };
 
 struct res_lib_cfg_statetrack {
@@ -81,9 +90,9 @@
 
 struct req_lib_cfg_administrativestateset {
 	mar_req_header_t header;
-	SaNameT compName;
-	CorosyncCfgAdministrativeTargetT administrativeTarget;
-	CorosyncCfgAdministrativeStateT administrativeState;
+	cs_name_t comp_name;
+	corosync_cfg_administrative_target_t administrative_target;
+	corosync_cfg_administrative_state_t administrative_state;
 };
 
 struct res_lib_cfg_administrativestateset {
@@ -92,9 +101,9 @@
 
 struct req_lib_cfg_administrativestateget {
 	mar_req_header_t header;
-	SaNameT compName;
-	CorosyncCfgAdministrativeTargetT administrativeTarget;
-	CorosyncCfgAdministrativeStateT administrativeState;
+	cs_name_t comp_name;
+	corosync_cfg_administrative_target_t administrative_target;
+	corosync_cfg_administrative_state_t administrative_state;
 };
 
 struct res_lib_cfg_administrativestateget {
@@ -122,7 +131,7 @@
 
 struct req_lib_cfg_serviceload {
 	mar_res_header_t header __attribute__((aligned(8)));
-	char *service_name[256] __attribute__((aligned(8)));
+	char service_name[256] __attribute__((aligned(8)));
 	unsigned int service_ver;
 };
 
@@ -132,7 +141,7 @@
 
 struct req_lib_cfg_serviceunload {
 	mar_res_header_t header __attribute__((aligned(8)));
-	char *service_name[256] __attribute__((aligned(8)));
+	char service_name[256] __attribute__((aligned(8)));
 	unsigned int service_ver;
 };
 
@@ -140,17 +149,65 @@
 	mar_res_header_t header __attribute__((aligned(8)));
 };
 
+struct req_lib_cfg_killnode {
+	mar_req_header_t header __attribute__((aligned(8)));
+	unsigned int nodeid __attribute__((aligned(8)));
+	cs_name_t reason __attribute__((aligned(8)));
+};
+
+struct res_lib_cfg_killnode {
+	mar_res_header_t header __attribute__((aligned(8)));
+};
+
+struct req_lib_cfg_tryshutdown {
+	mar_req_header_t header __attribute__((aligned(8)));
+	unsigned int flags;
+};
+
+struct res_lib_cfg_tryshutdown {
+	mar_res_header_t header __attribute__((aligned(8)));
+};
+
+struct req_lib_cfg_replytoshutdown {
+	mar_res_header_t header __attribute__((aligned(8)));
+	unsigned int response;
+};
+
+struct res_lib_cfg_testshutdown {
+	mar_res_header_t header __attribute__((aligned(8)));
+	unsigned int flags;
+};
+
+struct req_lib_cfg_get_node_addrs {
+        mar_req_header_t header __attribute__((aligned(8)));
+	unsigned int nodeid;
+};
+
+struct res_lib_cfg_get_node_addrs {
+        mar_res_header_t header __attribute__((aligned(8)));
+	unsigned int family;
+	unsigned int num_addrs;
+	char addrs[TOTEMIP_ADDRLEN][0];
+};
+
 typedef enum {
 	AIS_AMF_ADMINISTRATIVETARGET_SERVICEUNIT = 0,
 	AIS_AMF_ADMINISTRATIVETARGET_SERVICEGROUP = 1,
 	AIS_AMF_ADMINISTRATIVETARGET_COMPONENTSERVICEINSTANCE = 2,
 	AIS_AMF_ADMINISTRATIVETARGET_NODE = 3
-} corosyncAdministrativeTarget;
+} corosync_administrative_target_t;
 
 typedef enum {
 	AIS_AMF_ADMINISTRATIVESTATE_UNLOCKED = 0,
 	AIS_AMF_ADMINISTRATIVESTATE_LOCKED = 1,
 	AIS_AMF_ADMINISTRATIVESTATE_STOPPING = 2
-} corosyncAdministrativeState;
+} corosync_administrative_state_t;
+
+typedef enum {
+	CFG_SHUTDOWN_FLAG_REQUEST = 0,
+	CFG_SHUTDOWN_FLAG_REGARDLESS = 1,
+	CFG_SHUTDOWN_FLAG_IMMEDIATE = 2,
+} corosync_shutdown_flags_t;
+
 
 #endif /* AIS_IPC_CFG_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/ipc_confdb.h corosync-trunk/include/corosync/ipc_confdb.h
--- corosync-0.92/include/corosync/ipc_confdb.h	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/include/corosync/ipc_confdb.h	2008-11-06 22:49:07.000000000 +0100
@@ -35,7 +35,7 @@
 #define IPC_CONFDB_H_DEFINED
 
 #include <netinet/in.h>
-#include "saAis.h"
+#include <corosync/corotypes.h>
 #include "ipc_gen.h"
 
 enum req_confdb_types {
diff -Naurd corosync-0.92/include/corosync/ipc_cpg.h corosync-trunk/include/corosync/ipc_cpg.h
--- corosync-0.92/include/corosync/ipc_cpg.h	2008-09-17 21:15:00.000000000 +0200
+++ corosync-trunk/include/corosync/ipc_cpg.h	2009-01-08 07:29:16.000000000 +0100
@@ -35,7 +35,7 @@
 #define IPC_CPG_H_DEFINED
 
 #include <netinet/in.h>
-#include "saAis.h"
+#include <corosync/corotypes.h>
 #include "ipc_gen.h"
 #include "mar_cpg.h"
 
@@ -143,7 +143,7 @@
 
 struct req_lib_cpg_membership {
 	mar_req_header_t header __attribute__((aligned(8)));
-	mar_cpg_name_t group_name __attribute__((aligned(8)));
+//	mar_cpg_name_t group_name __attribute__((aligned(8)));
 };
 
 struct res_lib_cpg_confchg_callback {
diff -Naurd corosync-0.92/include/corosync/ipc_evs.h corosync-trunk/include/corosync/ipc_evs.h
--- corosync-0.92/include/corosync/ipc_evs.h	2008-08-14 16:59:50.000000000 +0200
+++ corosync-trunk/include/corosync/ipc_evs.h	2008-11-06 22:49:07.000000000 +0100
@@ -34,8 +34,7 @@
 #ifndef IPC_EVS_H_DEFINED
 #define IPC_EVS_H_DEFINED
 
-//#include <netinet/in6.h>
-#include "saAis.h"
+#include <corosync/corotypes.h>
 #include "evs.h"
 #include "ipc_gen.h"
 
diff -Naurd corosync-0.92/include/corosync/ipc_gen.h corosync-trunk/include/corosync/ipc_gen.h
--- corosync-0.92/include/corosync/ipc_gen.h	2008-08-14 16:59:50.000000000 +0200
+++ corosync-trunk/include/corosync/ipc_gen.h	2008-11-06 22:49:07.000000000 +0100
@@ -46,7 +46,9 @@
 	MSG_SERVICE = 6,
 	CFG_SERVICE = 7,
 	CPG_SERVICE = 8,
-	CONFDB_SERVICE = 10
+	CONFDB_SERVICE = 10,
+	QUORUM_SERVICE = 11,
+	PLOAD_SERVICE = 12
 };
 
 enum req_init_types {
@@ -72,7 +74,7 @@
 typedef struct {
 	int size; __attribute__((aligned(8))) 
 	int id __attribute__((aligned(8)));
-	SaAisErrorT error __attribute__((aligned(8)));
+	cs_error_t error __attribute__((aligned(8)));
 } mar_res_header_t __attribute__((aligned(8)));
 
 typedef struct {
diff -Naurd corosync-0.92/include/corosync/ipc_pload.h corosync-trunk/include/corosync/ipc_pload.h
--- corosync-0.92/include/corosync/ipc_pload.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/ipc_pload.h	2008-11-06 22:49:07.000000000 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef IPC_PLOAD_H_DEFINED
+#define IPC_PLOAD_H_DEFINED
+
+#include <corosync/corotypes.h>
+#include "pload.h"
+#include "ipc_gen.h"
+
+enum req_lib_evs_types {
+	MESSAGE_REQ_PLOAD_START = 0,
+};
+
+enum res_lib_evs_types {
+	MESSAGE_RES_PLOAD_START = 0,
+};
+
+struct res_lib_pload_start {
+	mar_res_header_t header;
+	unsigned int dataset[1024];
+};
+
+struct res_lib_pload_mcast {
+	mar_res_header_t header;
+};
+
+struct req_lib_pload_start {
+	mar_req_header_t header;
+	unsigned int msg_code;
+	unsigned int msg_size;
+	unsigned int msg_count;
+	unsigned int time_interval;
+};
+
+struct req_lib_pload_mcast {
+	mar_req_header_t header;
+	unsigned int code;
+};
+
+#endif /* IPC_PLOAD_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/ipc_quorum.h corosync-trunk/include/corosync/ipc_quorum.h
--- corosync-0.92/include/corosync/ipc_quorum.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/ipc_quorum.h	2008-11-06 22:49:07.000000000 +0100
@@ -0,0 +1,73 @@
+/*
+ * 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_QUORUM_H_DEFINED
+#define IPC_QUORUM_H_DEFINED
+
+#include <netinet/in.h>
+#include <corosync/corotypes.h>
+#include "corosync/ipc_gen.h"
+
+enum req_quorum_types {
+	MESSAGE_REQ_QUORUM_GETQUORATE = 0,
+	MESSAGE_REQ_QUORUM_TRACKSTART,
+	MESSAGE_REQ_QUORUM_TRACKSTOP
+};
+
+enum res_quorum_types {
+	MESSAGE_RES_QUORUM_GETQUORATE = 0,
+	MESSAGE_RES_QUORUM_TRACKSTART,
+	MESSAGE_RES_QUORUM_TRACKSTOP,
+	MESSAGE_RES_QUORUM_NOTIFICATION
+};
+
+struct req_lib_quorum_trackstart {
+        mar_req_header_t header __attribute__((aligned(8)));
+	unsigned int track_flags;
+};
+
+
+struct res_lib_quorum_getquorate {
+        mar_res_header_t header __attribute__((aligned(8)));
+	mar_uint32_t quorate;
+};
+
+struct res_lib_quorum_notification {
+	mar_res_header_t header __attribute__((aligned(8)));
+	mar_int32_t quorate __attribute__((aligned(8)));
+	mar_uint64_t ring_seq __attribute__((aligned(8)));
+	mar_uint32_t view_list_entries __attribute__((aligned(8)));
+	mar_uint32_t view_list[];
+};
+
+#endif
diff -Naurd corosync-0.92/include/corosync/ipc_votequorum.h corosync-trunk/include/corosync/ipc_votequorum.h
--- corosync-0.92/include/corosync/ipc_votequorum.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/ipc_votequorum.h	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef IPC_VOTEQUORUM_H_DEFINED
+#define IPC_VOTEQUORUM_H_DEFINED
+
+#include "corosync/corotypes.h"
+#include "corosync/ipc_gen.h"
+
+// ILLEGAL value!!
+#define VOTEQUORUM_SERVICE 15
+
+#define VOTEQUORUM_MAX_QDISK_NAME_LEN 255
+
+
+enum req_votequorum_types {
+	MESSAGE_REQ_VOTEQUORUM_GETINFO = 0,
+	MESSAGE_REQ_VOTEQUORUM_SETEXPECTED,
+	MESSAGE_REQ_VOTEQUORUM_SETVOTES,
+	MESSAGE_REQ_VOTEQUORUM_QDISK_REGISTER,
+	MESSAGE_REQ_VOTEQUORUM_QDISK_UNREGISTER,
+	MESSAGE_REQ_VOTEQUORUM_QDISK_POLL,
+	MESSAGE_REQ_VOTEQUORUM_QDISK_GETINFO,
+	MESSAGE_REQ_VOTEQUORUM_SETSTATE,
+	MESSAGE_REQ_VOTEQUORUM_LEAVING,
+	MESSAGE_REQ_VOTEQUORUM_TRACKSTART,
+	MESSAGE_REQ_VOTEQUORUM_TRACKSTOP
+};
+
+enum res_votequorum_types {
+	MESSAGE_RES_VOTEQUORUM_STATUS = 0,
+	MESSAGE_RES_VOTEQUORUM_GETINFO,
+	MESSAGE_RES_VOTEQUORUM_QDISK_GETINFO,
+	MESSAGE_RES_VOTEQUORUM_TRACKSTART,
+	MESSAGE_RES_VOTEQUORUM_NOTIFICATION
+};
+
+struct req_lib_votequorum_setvotes {
+        mar_req_header_t header __attribute__((aligned(8)));
+	unsigned int votes;
+	int nodeid;
+};
+
+struct req_lib_votequorum_qdisk_register {
+        mar_req_header_t header __attribute__((aligned(8)));
+	unsigned int votes;
+	char name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
+};
+
+struct req_lib_votequorum_qdisk_poll {
+        mar_req_header_t header __attribute__((aligned(8)));
+	int state;
+};
+
+struct req_lib_votequorum_setexpected {
+        mar_req_header_t header __attribute__((aligned(8)));
+	unsigned int expected_votes;
+};
+
+struct req_lib_votequorum_trackstart {
+        mar_req_header_t header __attribute__((aligned(8)));
+	uint64_t context;
+	unsigned int track_flags;
+};
+
+struct req_lib_votequorum_general {
+        mar_req_header_t header __attribute__((aligned(8)));
+};
+
+#define VOTEQUORUM_REASON_KILL_REJECTED    1
+#define VOTEQUORUM_REASON_KILL_APPLICATION 2
+#define VOTEQUORUM_REASON_KILL_REJOIN      3
+
+struct req_lib_votequorum_getinfo {
+        mar_req_header_t header __attribute__((aligned(8)));
+	int nodeid;
+};
+
+struct res_lib_votequorum_status {
+        mar_res_header_t header __attribute__((aligned(8)));
+};
+
+#define VOTEQUORUM_INFO_FLAG_HASSTATE   1
+#define VOTEQUORUM_INFO_FLAG_DISALLOWED 2
+#define VOTEQUORUM_INFO_FLAG_TWONODE    4
+#define VOTEQUORUM_INFO_FLAG_QUORATE    8
+
+struct res_lib_votequorum_getinfo {
+        mar_res_header_t header __attribute__((aligned(8)));
+	int nodeid;
+	unsigned int votes;
+	unsigned int expected_votes;
+	unsigned int highest_expected;
+	unsigned int total_votes;
+	unsigned int quorum;
+	unsigned int flags;
+};
+
+struct res_lib_votequorum_qdisk_getinfo {
+        mar_res_header_t header __attribute__((aligned(8)));
+	unsigned int votes;
+	unsigned int state;
+	char name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
+};
+
+struct votequorum_node {
+	mar_uint32_t nodeid;
+	mar_uint32_t state;
+};
+
+struct res_lib_votequorum_notification {
+	mar_res_header_t header __attribute__((aligned(8)));
+	mar_uint32_t quorate __attribute__((aligned(8)));
+	mar_uint64_t context __attribute__((aligned(8)));
+	mar_uint32_t node_list_entries __attribute__((aligned(8)));
+	struct votequorum_node node_list[] __attribute__((aligned(8)));
+};
+
+#endif
diff -Naurd corosync-0.92/include/corosync/mar_gen.h corosync-trunk/include/corosync/mar_gen.h
--- corosync-0.92/include/corosync/mar_gen.h	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/include/corosync/mar_gen.h	2008-11-06 22:49:07.000000000 +0100
@@ -43,7 +43,7 @@
 #endif
 #include <string.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/swab.h>
 
 typedef int8_t mar_int8_t;
@@ -98,7 +98,7 @@
 
 typedef struct {
 	mar_uint16_t length __attribute__((aligned(8)));
-	mar_uint8_t value[SA_MAX_NAME_LENGTH] __attribute__((aligned(8)));
+	mar_uint8_t value[CS_MAX_NAME_LENGTH] __attribute__((aligned(8)));
 } mar_name_t;
 
 static inline char *get_mar_name_t (mar_name_t *name) {
@@ -121,19 +121,19 @@
 }
 
 static inline void marshall_from_mar_name_t (
-	SaNameT *dest,
+	cs_name_t *dest,
 	mar_name_t *src)
 {
 	dest->length = src->length;
-	memcpy (dest->value, src->value, SA_MAX_NAME_LENGTH);
+	memcpy (dest->value, src->value, CS_MAX_NAME_LENGTH);
 }
 
 static inline void marshall_to_mar_name_t (
 	mar_name_t *dest,
-	SaNameT *src)
+	cs_name_t *src)
 {
 	dest->length = src->length;
-	memcpy (dest->value, src->value, SA_MAX_NAME_LENGTH);
+	memcpy (dest->value, src->value, CS_MAX_NAME_LENGTH);
 }
 
 typedef enum {
@@ -148,7 +148,7 @@
 	swab_mar_uint64_t (to_swab);
 }
 
-#define MAR_TIME_END ((SaTimeT)0x7fffffffffffffffull)
+#define MAR_TIME_END ((int64_t)0x7fffffffffffffffull)
 #define MAR_TIME_BEGIN            0x0ULL
 #define MAR_TIME_UNKNOWN          0x8000000000000000ULL
 
@@ -158,7 +158,7 @@
 #define MAR_TIME_ONE_MINUTE      60000000000ULL
 #define MAR_TIME_ONE_HOUR        3600000000000ULL
 #define MAR_TIME_ONE_DAY         86400000000000ULL
-#define MAR_TIME_MAX             SA_TIME_END
+#define MAR_TIME_MAX             CS_TIME_END
 
 #define MAR_TRACK_CURRENT 0x01
 #define MAR_TRACK_CHANGES 0x02
diff -Naurd corosync-0.92/include/corosync/pload.h corosync-trunk/include/corosync/pload.h
--- corosync-0.92/include/corosync/pload.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/pload.h	2008-10-30 23:41:34.000000000 +0100
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef COROSYNC_PLOAD_H_DEFINED
+#define COROSYNC_PLOAD_H_DEFINED
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/**
+ * @defgroup corosync Other API services provided by corosync
+ */
+/**
+ * @addtogroup pload_corosync
+ *
+ * @{
+ */
+
+typedef uint64_t pload_handle_t;
+
+typedef enum {
+	PLOAD_OK = 1,
+	PLOAD_ERR_LIBRARY = 2,
+	PLOAD_ERR_TIMEOUT = 5,
+	PLOAD_ERR_TRY_AGAIN = 6,
+	PLOAD_ERR_INVALID_PARAM = 7,
+	PLOAD_ERR_NO_MEMORY = 8,
+	PLOAD_ERR_BAD_HANDLE = 9,
+	PLOAD_ERR_ACCESS = 11,
+	PLOAD_ERR_NOT_EXIST = 12,
+	PLOAD_ERR_EXIST = 14,
+	PLOAD_ERR_NOT_SUPPORTED = 20,
+	PLOAD_ERR_SECURITY = 29,
+	PLOAD_ERR_TOO_MANY_GROUPS=30
+} pload_error_t;
+
+typedef struct {
+	int callback;
+} pload_callbacks_t;
+
+/** @} */
+
+/*
+ * Create a new pload connection
+ */
+pload_error_t pload_initialize (
+	pload_handle_t *handle,
+	pload_callbacks_t *callbacks);
+
+/*
+ * Close the pload handle
+ */
+pload_error_t pload_finalize (
+	pload_handle_t handle);
+
+/*
+ * Get a file descriptor on which to poll.  pload_handle_t is NOT a
+ * file descriptor and may not be used directly.
+ */
+pload_error_t pload_fd_get (
+	pload_handle_t handle,
+	int *fd);
+
+unsigned int pload_start (
+        pload_handle_t handle,
+        unsigned int code,
+        unsigned int msg_count,
+        unsigned int msg_size);
+
+#endif /* COROSYNC_PLOAD_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/quorum.h corosync-trunk/include/corosync/quorum.h
--- corosync-0.92/include/corosync/quorum.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/quorum.h	2008-12-08 16:55:41.000000000 +0100
@@ -0,0 +1,97 @@
+/*
+ * 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 Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef COROSYNC_QUORUM_H_DEFINED
+#define COROSYNC_QUORUM_H_DEFINED
+
+#include <corosync/corotypes.h>
+
+typedef uint64_t quorum_handle_t;
+
+typedef struct {
+	uint32_t nodeid;
+	uint32_t state;
+} quorum_node_t;
+
+typedef void (*quorum_notification_fn_t) (
+	quorum_handle_t handle,
+	uint32_t quorate,
+	uint64_t ring_seq,
+	uint32_t view_list_entries,
+	uint32_t *view_list
+	);
+
+typedef struct {
+	quorum_notification_fn_t quorum_notify_fn;
+} quorum_callbacks_t;
+
+
+/*
+ * Create a new quorum connection
+ */
+cs_error_t quorum_initialize (
+	quorum_handle_t *handle,
+	quorum_callbacks_t *callbacks);
+
+/*
+ * Close the quorum handle
+ */
+cs_error_t quorum_finalize (
+	quorum_handle_t handle);
+
+
+/*
+ * Dispatch messages and configuration changes
+ */
+cs_error_t quorum_dispatch (
+	quorum_handle_t handle,
+	cs_dispatch_flags_t dispatch_types);
+
+
+/*
+ * Get quorum information.
+ */
+cs_error_t quorum_getquorate (
+	quorum_handle_t handle,
+	int *quorate);
+
+/* Track node and quorum changes */
+cs_error_t quorum_trackstart (
+	quorum_handle_t handle,
+	unsigned int flags );
+
+cs_error_t quorum_trackstop (
+	quorum_handle_t handle);
+
+
+#endif /* COROSYNC_QUORUM_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/saAis.h corosync-trunk/include/corosync/saAis.h
--- corosync-0.92/include/corosync/saAis.h	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/include/corosync/saAis.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2002-2003 MontaVista Software, Inc.
- * Copyright (c) 2006-2008 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake (sdake@redhat.com)
- *
- * This software licensed under BSD license, the text of which follows:
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- * - Neither the name of the MontaVista Software, Inc. nor the names of its
- *   contributors may be used to endorse or promote products derived from this
- *   software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef AIS_TYPES_H_DEFINED
-#define AIS_TYPES_H_DEFINED
-
-/**
- * @defgroup saf Service Availability Forum Application Interface Specification
- */
-
-typedef enum {
-	SA_FALSE = 0,
-	SA_TRUE = 1
-} SaBoolT;
-
-#ifndef COROSYNC_SOLARIS
-#include <stdint.h>
-#else
-#include <sys/types.h>
-#endif
-
-typedef int8_t SaInt8T;
-typedef int16_t SaInt16T;
-typedef int32_t SaInt32T;
-typedef int64_t SaInt64T;
-
-typedef uint8_t SaUint8T;
-typedef uint16_t SaUint16T;
-typedef uint32_t SaUint32T;
-typedef uint64_t SaUint64T;
-
-typedef float SaFloatT;
-typedef double SaDoubleT;
-typedef char * SaStringT;
-typedef SaInt64T SaTimeT;
-
-#define SA_TIME_END    ((SaTimeT)0x7FFFFFFFFFFFFFFFULL)
-#define SA_TIME_BEGIN            0x0ULL
-#define SA_TIME_UNKNOWN          0x8000000000000000ULL
-
-#define SA_TIME_ONE_MICROSECOND 1000ULL
-#define SA_TIME_ONE_MILLISECOND 1000000ULL
-#define SA_TIME_ONE_SECOND      1000000000ULL
-#define SA_TIME_ONE_MINUTE      60000000000ULL
-#define SA_TIME_ONE_HOUR        3600000000000ULL
-#define SA_TIME_ONE_DAY         86400000000000ULL
-#define SA_TIME_MAX             SA_TIME_END
-
-#define SA_MAX_NAME_LENGTH 256
-
-typedef struct {
-	SaUint16T length;
-	SaUint8T value[SA_MAX_NAME_LENGTH];
-} SaNameT;
-
-typedef struct {
-	char releaseCode;
-	unsigned char majorVersion;
-	unsigned char minorVersion;
-} SaVersionT;
-
-typedef SaUint64T SaNtfIdentifierT;
-
-#define SA_TRACK_CURRENT 0x01
-#define SA_TRACK_CHANGES 0x02
-#define SA_TRACK_CHANGES_ONLY 0x04
-
-typedef enum {
-	SA_DISPATCH_ONE = 1,
-	SA_DISPATCH_ALL = 2,
-	SA_DISPATCH_BLOCKING = 3
-} SaDispatchFlagsT;
-
-typedef enum {
-	SA_AIS_OK = 1,
-	SA_AIS_ERR_LIBRARY = 2,
-	SA_AIS_ERR_VERSION = 3,
-	SA_AIS_ERR_INIT = 4,
-	SA_AIS_ERR_TIMEOUT = 5,
-	SA_AIS_ERR_TRY_AGAIN = 6,
-	SA_AIS_ERR_INVALID_PARAM = 7,
-	SA_AIS_ERR_NO_MEMORY = 8,
-	SA_AIS_ERR_BAD_HANDLE = 9,
-	SA_AIS_ERR_BUSY = 10,
-	SA_AIS_ERR_ACCESS = 11,
-	SA_AIS_ERR_NOT_EXIST = 12,
-	SA_AIS_ERR_NAME_TOO_LONG = 13,
-	SA_AIS_ERR_EXIST = 14,
-	SA_AIS_ERR_NO_SPACE = 15,
-	SA_AIS_ERR_INTERRUPT = 16,
-	SA_AIS_ERR_NAME_NOT_FOUND = 17,
-	SA_AIS_ERR_NO_RESOURCES = 18,
-	SA_AIS_ERR_NOT_SUPPORTED = 19,
-	SA_AIS_ERR_BAD_OPERATION = 20,
-	SA_AIS_ERR_FAILED_OPERATION = 21,
-	SA_AIS_ERR_MESSAGE_ERROR = 22,
-	SA_AIS_ERR_QUEUE_FULL = 23,
-	SA_AIS_ERR_QUEUE_NOT_AVAILABLE = 24,
-	SA_AIS_ERR_BAD_FLAGS = 25,
-	SA_AIS_ERR_TOO_BIG = 26,
-	SA_AIS_ERR_NO_SECTIONS = 27
-} SaAisErrorT;
-
-typedef union {
-	SaInt64T int64Value;
-	SaUint64T uint64Value;
-	SaTimeT timeValue;
-	SaFloatT floatValue;
-	SaDoubleT doubleValue;
-} SaLimitValueT;
-
-typedef SaUint64T SaSelectionObjectT;
-
-typedef SaUint64T SaInvocationT;
-
-typedef SaUint64T SaSizeT;
-
-#define SA_HANDLE_INVALID 0x0ULL
-
-#endif /* AIS_TYPES_H_DEFINED */
diff -Naurd corosync-0.92/include/corosync/totem/totem.h corosync-trunk/include/corosync/totem/totem.h
--- corosync-0.92/include/corosync/totem/totem.h	2008-08-20 02:57:40.000000000 +0200
+++ corosync-trunk/include/corosync/totem/totem.h	2008-10-30 23:41:34.000000000 +0100
@@ -50,26 +50,6 @@
 #define SEND_THREADS_MAX	16
 #define INTERFACE_MAX		2
 
-/*
- * Array location of various timeouts as
- * specified in corosync.conf.  The last enum
- * specifies the size of the timeouts array and
- * needs to remain the last item in the list.
- */
-enum {
-	TOTEM_RETRANSMITS_BEFORE_LOSS,
-	TOTEM_TOKEN,
-	TOTEM_RETRANSMIT_TOKEN,
-	TOTEM_HOLD_TOKEN,
-	TOTEM_JOIN,
-	TOTEM_CONSENSUS,
-	TOTEM_MERGE,
-	TOTEM_DOWNCHECK,
-	TOTEM_FAIL_RECV_CONST,
-
-	MAX_TOTEM_TIMEOUTS	/* Last item */
-} totem_timeout_types;
-
 struct totem_interface {
 	struct totem_ip_address bindnet;
 	struct totem_ip_address boundto;
@@ -78,12 +58,21 @@
 };
 
 struct totem_logging_configuration {
-	void (*log_printf) (char *, int, int, char *, ...) __attribute__((format(printf, 4, 5)));
+        void (*log_printf) (
+                int subsys,
+                char *function_name,
+                char *file_name,
+                int file_line,
+                unsigned int level,
+                char *format,
+                ...) __attribute__((format(printf, 6, 7)));
+
 	int log_level_security;
 	int log_level_error;
 	int log_level_warning;
 	int log_level_notice;
 	int log_level_debug;
+	int log_subsys_id;
 };
 
 struct totem_config {
@@ -161,6 +150,7 @@
 	TOTEM_CONFIGURATION_TRANSITIONAL	
 };
 
+#define TOTEM_CALLBACK_TOKEN_TYPE
 enum totem_callback_token_type {
 	TOTEM_CALLBACK_TOKEN_RECEIVED = 1,
 	TOTEM_CALLBACK_TOKEN_SENT = 2
diff -Naurd corosync-0.92/include/corosync/totem/totemip.h corosync-trunk/include/corosync/totem/totemip.h
--- corosync-0.92/include/corosync/totem/totemip.h	2008-08-14 16:59:50.000000000 +0200
+++ corosync-trunk/include/corosync/totem/totemip.h	2009-01-25 22:15:25.000000000 +0100
@@ -72,7 +72,7 @@
 extern int totemip_totemip_to_sockaddr_convert(struct totem_ip_address *ip_addr,
 					       uint16_t port, struct sockaddr_storage *saddr, int *addrlen);
 extern int totemip_parse(struct totem_ip_address *totemip, char *addr, int family);
-extern int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num);
+extern int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num, int mask_high_bit);
 
 /* These two simulate a zero in_addr by clearing the family field */
 static inline void totemip_zero_set(struct totem_ip_address *addr)
diff -Naurd corosync-0.92/include/corosync/totem/totempg.h corosync-trunk/include/corosync/totem/totempg.h
--- corosync-0.92/include/corosync/totem/totempg.h	2008-08-14 16:59:50.000000000 +0200
+++ corosync-trunk/include/corosync/totem/totempg.h	2008-12-01 19:44:55.000000000 +0100
@@ -139,7 +139,7 @@
 
 extern char *totempg_ifaces_print (unsigned int nodeid);
 
-extern int totempg_my_nodeid_get (void);
+extern unsigned int totempg_my_nodeid_get (void);
 
 extern int totempg_my_family_get (void);
 
diff -Naurd corosync-0.92/include/corosync/votequorum.h corosync-trunk/include/corosync/votequorum.h
--- corosync-0.92/include/corosync/votequorum.h	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/include/corosync/votequorum.h	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef COROSYNC_VOTEQUORUM_H_DEFINED
+#define COROSYNC_VOTEQUORUM_H_DEFINED
+
+typedef uint64_t votequorum_handle_t;
+
+
+#define VOTEQUORUM_MAX_QDISK_NAME_LEN 255
+
+#define VOTEQUORUM_INFO_FLAG_HASSTATE   1
+#define VOTEQUORUM_INFO_FLAG_DISALLOWED 2
+#define VOTEQUORUM_INFO_FLAG_TWONODE    4
+#define VOTEQUORUM_INFO_FLAG_QUORATE    8
+
+#define NODESTATE_JOINING    1
+#define NODESTATE_MEMBER     2
+#define NODESTATE_DEAD       3
+#define NODESTATE_LEAVING    4
+#define NODESTATE_DISALLOWED 5
+
+
+/** @} */
+
+struct votequorum_info {
+	unsigned int node_id;
+	unsigned int node_votes;
+	unsigned int node_expected_votes;
+	unsigned int highest_expected;
+	unsigned int total_votes;
+	unsigned int quorum;
+	unsigned int flags;
+};
+
+struct votequorum_qdisk_info {
+	unsigned int votes;
+	unsigned int state;
+	char name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
+};
+
+typedef struct {
+	uint32_t nodeid;
+	uint32_t state;
+} votequorum_node_t;
+
+
+typedef void (*votequorum_notification_fn_t) (
+	votequorum_handle_t handle,
+	uint64_t context,
+	uint32_t quorate,
+	uint32_t node_list_entries,
+	votequorum_node_t node_list[]
+	);
+
+typedef struct {
+	votequorum_notification_fn_t votequorum_notify_fn;
+} votequorum_callbacks_t;
+
+
+/*
+ * Create a new quorum connection
+ */
+cs_error_t votequorum_initialize (
+	votequorum_handle_t *handle,
+	votequorum_callbacks_t *callbacks);
+
+/*
+ * Close the quorum handle
+ */
+cs_error_t votequorum_finalize (
+	votequorum_handle_t handle);
+
+
+/*
+ * Dispatch messages and configuration changes
+ */
+cs_error_t votequorum_dispatch (
+	votequorum_handle_t handle,
+	cs_dispatch_flags_t dispatch_types);
+
+
+/*
+ * Get quorum information.
+ */
+cs_error_t votequorum_getinfo (
+	votequorum_handle_t handle,
+	unsigned int nodeid,
+	struct votequorum_info *info);
+
+/*
+ * set expected_votes
+ */
+cs_error_t votequorum_setexpected (
+	votequorum_handle_t handle,
+	unsigned int expected_votes);
+
+/*
+ * set votes for a node
+ */
+cs_error_t votequorum_setvotes (
+	votequorum_handle_t handle,
+	unsigned int nodeid,
+	unsigned int votes);
+
+/*
+ * Register a quorum device
+ * it will be DEAD until polled
+ */
+cs_error_t votequorum_qdisk_register (
+	votequorum_handle_t handle,
+	char *name,
+	unsigned int votes);
+
+/*
+ * Unregister a quorum device
+ */
+cs_error_t votequorum_qdisk_unregister (
+	votequorum_handle_t handle);
+
+/*
+ * Poll a quorum device
+ */
+cs_error_t votequorum_qdisk_poll (
+	votequorum_handle_t handle,
+	unsigned int state);
+
+/*
+ * Get quorum device information
+ */
+cs_error_t votequorum_qdisk_getinfo (
+	votequorum_handle_t handle,
+	struct votequorum_qdisk_info *info);
+
+/*
+ * Set the "hasstate" bit for this node
+ */
+cs_error_t votequorum_setstate (
+	votequorum_handle_t handle);
+
+/* Track node and quorum changes */
+cs_error_t votequorum_trackstart (
+	votequorum_handle_t handle,
+	uint64_t context,
+	unsigned int flags );
+
+cs_error_t votequorum_trackstop (
+	votequorum_handle_t handle);
+
+/*
+ * Set our LEAVING flag. we should exit soon after this
+ */
+cs_error_t votequorum_leaving (
+	votequorum_handle_t handle);
+
+/*
+ * Save and retrieve private data/context
+ */
+cs_error_t votequorum_context_get (
+	votequorum_handle_t handle,
+	void **context);
+
+cs_error_t votequorum_context_set (
+	votequorum_handle_t handle,
+	void *context);
+
+#endif /* COROSYNC_VOTEQUORUM_H_DEFINED */
diff -Naurd corosync-0.92/lcr/Makefile corosync-trunk/lcr/Makefile
--- corosync-0.92/lcr/Makefile	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/lcr/Makefile	2008-11-11 18:26:58.000000000 +0100
@@ -84,3 +84,6 @@
 	rm -f test libtest.so* *.o uic liblcr.so* liblcr.a *.lcrso *.da *.ba *.bb *.bbg \
 	test_static
 
+lint:
+	-splint $(LINT_FLAGS) $(CFLAGS) lcr_ifact.c uic.c uis.c
+
diff -Naurd corosync-0.92/lcr/uic.c corosync-trunk/lcr/uic.c
--- corosync-0.92/lcr/uic.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/lcr/uic.c	2008-11-11 19:13:47.000000000 +0100
@@ -88,7 +88,7 @@
 	return 0;
 }
 
-struct req_msg {
+struct uic_req_msg {
 	int len;
 	char msg[0];
 };
@@ -97,12 +97,13 @@
 {
 	struct msghdr msg_send;
 	struct iovec iov_send[2];
-	struct req_msg req_msg;
+	struct uic_req_msg req_msg;
+	ssize_t send_res;
 	int res;
 
 	req_msg.len = strlen (msg) + 1;
 	iov_send[0].iov_base = (void *)&req_msg;
-	iov_send[0].iov_len = sizeof (struct req_msg);
+	iov_send[0].iov_len = sizeof (struct uic_req_msg);
 	iov_send[1].iov_base = (void *)msg;
 	iov_send[1].iov_len = req_msg.len;
 
@@ -120,12 +121,14 @@
 #endif
 
 	retry_send:
-	res = sendmsg (fd, &msg_send, 0);
-	if (res == -1 && errno == EINTR) {
+	send_res = sendmsg (fd, &msg_send, 0);
+	if (send_res == -1 && errno == EINTR) {
                 goto retry_send;
         }
-	if (res == -1) {
+	if (send_res == -1) {
 		res = -errno;
+	} else {
+		res = (int)send_res;
 	}
 	return (res);
 
diff -Naurd corosync-0.92/lcr/uis.c corosync-trunk/lcr/uis.c
--- corosync-0.92/lcr/uis.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/lcr/uis.c	2008-11-11 18:26:58.000000000 +0100
@@ -115,14 +115,14 @@
 	}
 };
 
-struct req_msg {
+struct uis_req_msg {
         int len;
         char msg[0];
 };
 
 static void lcr_uis_dispatch (int fd)
 {
-	struct req_msg header;
+	struct uis_req_msg header;
 	char msg_contents[512];
 	ssize_t readsize;
 
diff -Naurd corosync-0.92/lib/cfg.c corosync-trunk/lib/cfg.c
--- corosync-0.92/lib/cfg.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/lib/cfg.c	2009-01-19 09:31:21.000000000 +0100
@@ -1,13 +1,13 @@
 /*
  * Copyright (c) 2002-2005 MontaVista Software, Inc.
- * Copyright (c) 2006-2007 Red Hat, Inc.
+ * Copyright (c) 2006-2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
  * Author: Steven Dake (sdake@redhat.com)
  *
  * This software licensed under BSD license, the text of which follows:
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  *
@@ -40,19 +40,21 @@
 #include <errno.h>
 #include <signal.h>
 #include <pthread.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <sys/un.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/cfg.h>
+#include <corosync/totem/totemip.h>
 #include <corosync/mar_gen.h>
 #include <corosync/ipc_gen.h>
 #include <corosync/ipc_cfg.h>
 #include <corosync/ais_util.h>
 
-struct res_overlay {
+struct cfg_res_overlay {
 	mar_res_header_t header;
 	char data[4096];
 };
@@ -63,15 +65,15 @@
 struct cfg_instance {
 	int response_fd;
 	int dispatch_fd;
-	CorosyncCfgCallbacksT callbacks;
-	SaNameT compName;
-	int compRegistered;
+	corosync_cfg_callbacks_t callbacks;
+	cs_name_t comp_name;
+	int comp_registered;
 	int finalize;
 	pthread_mutex_t response_mutex;
 	pthread_mutex_t dispatch_mutex;
 };
 
-static void cfg_handleInstanceDestructor (void *);
+static void cfg_handle_instance_destructor (void *);
 
 /*
  * All instances in one database
@@ -80,13 +82,13 @@
 	.handleCount			= 0,
 	.handles			= 0,
 	.mutex				= PTHREAD_MUTEX_INITIALIZER,
-	.handleInstanceDestructor	= cfg_handleInstanceDestructor
+	.handleInstanceDestructor	= cfg_handle_instance_destructor
 };
 
 /*
  * Implementation
  */
-void cfg_handleInstanceDestructor (void *instance)
+void cfg_handle_instance_destructor (void *instance)
 {
 	struct cfg_instance *cfg_instance = instance;
 
@@ -94,84 +96,85 @@
 	pthread_mutex_destroy (&cfg_instance->dispatch_mutex);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_initialize (
 	corosync_cfg_handle_t *cfg_handle,
-	const CorosyncCfgCallbacksT *cfgCallbacks)
+	const corosync_cfg_callbacks_t *cfg_callbacks)
 {
 	struct cfg_instance *cfg_instance;
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 
 	error = saHandleCreate (&cfg_hdb, sizeof (struct cfg_instance), cfg_handle);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_no_destroy;
 	}
 
 	error = saHandleInstanceGet (&cfg_hdb, *cfg_handle, (void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_destroy;
 	}
 
 	cfg_instance->response_fd = -1;
 
 	cfg_instance->dispatch_fd = -1;
-	
+
 	error = saServiceConnect (&cfg_instance->response_fd,
 		&cfg_instance->dispatch_fd, CFG_SERVICE);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_put_destroy;
 	}
 
-	if (cfgCallbacks) {
-	memcpy (&cfg_instance->callbacks, cfgCallbacks, sizeof (CorosyncCfgCallbacksT));
+	if (cfg_callbacks) {
+	memcpy (&cfg_instance->callbacks, cfg_callbacks, sizeof (corosync_cfg_callbacks_t));
 	}
 
 	pthread_mutex_init (&cfg_instance->response_mutex, NULL);
 
 	pthread_mutex_init (&cfg_instance->dispatch_mutex, NULL);
 
-	saHandleInstancePut (&cfg_hdb, *cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, *cfg_handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 
 error_put_destroy:
-	saHandleInstancePut (&cfg_hdb, *cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, *cfg_handle);
 error_destroy:
-	saHandleDestroy (&cfg_hdb, *cfg_handle);
+	(void)saHandleDestroy (&cfg_hdb, *cfg_handle);
 error_no_destroy:
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_fd_get (
 	corosync_cfg_handle_t cfg_handle,
-	SaSelectionObjectT *selectionObject)
+	int32_t *selection_fd)
 {
 	struct cfg_instance *cfg_instance;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
-	*selectionObject = cfg_instance->dispatch_fd;
+	*selection_fd = cfg_instance->dispatch_fd;
 
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
-	return (SA_AIS_OK);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
+	return (CS_OK);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_dispatch (
 	corosync_cfg_handle_t cfg_handle,
-	SaDispatchFlagsT dispatchFlags)
+	cs_dispatch_flags_t dispatch_flags)
 {
 	struct pollfd ufds;
 	int timeout = -1;
-	SaAisErrorT error;
+	cs_error_t error;
 	int cont = 1; /* always continue do loop except when set to 0 */
 	int dispatch_avail;
 	struct cfg_instance *cfg_instance;
+	struct res_lib_cfg_testshutdown *res_lib_cfg_testshutdown;
 #ifdef COMPILE_OUT
 	struct res_lib_corosync_healthcheckcallback *res_lib_corosync_healthcheckcallback;
 	struct res_lib_corosync_readinessstatesetcallback *res_lib_corosync_readinessstatesetcallback;
@@ -179,19 +182,19 @@
 	struct res_lib_corosync_csiremovecallback *res_lib_corosync_csiremovecallback;
 	struct res_lib_cfg_statetrackcallback *res_lib_cfg_statetrackcallback;
 #endif
-	CorosyncCfgCallbacksT callbacks;
-	struct res_overlay dispatch_data;
+	corosync_cfg_callbacks_t callbacks;
+	struct cfg_res_overlay dispatch_data;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
 		(void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	/*
-	 * Timeout instantly for SA_DISPATCH_ALL
+	 * Timeout instantly for CS_DISPATCH_ALL
 	 */
-	if (dispatchFlags == SA_DISPATCH_ALL) {
+	if (dispatch_flags == CS_DISPATCH_ALL) {
 		timeout = 0;
 	}
 
@@ -204,14 +207,14 @@
 		ufds.revents = 0;
 
 		error = saPollRetry (&ufds, 1, timeout);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
 		pthread_mutex_lock (&cfg_instance->dispatch_mutex);
 
 		error = saPollRetry (&ufds, 1, 0);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
@@ -219,13 +222,13 @@
 		 * Handle has been finalized in another thread
 		 */
 		if (cfg_instance->finalize == 1) {
-			error = SA_AIS_OK;
+			error = CS_OK;
 			pthread_mutex_unlock (&cfg_instance->dispatch_mutex);
 			goto error_unlock;
 		}
 
 		dispatch_avail = ufds.revents & POLLIN;
-		if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) {
+		if (dispatch_avail == 0 && dispatch_flags == CS_DISPATCH_ALL) {
 			pthread_mutex_unlock (&cfg_instance->dispatch_mutex);
 			break; /* exit do while cont is 1 loop */
 		} else
@@ -240,13 +243,13 @@
 			 */
 			error = saRecvRetry (cfg_instance->dispatch_fd, &dispatch_data.header,
 				sizeof (mar_res_header_t));
-			if (error != SA_AIS_OK) {
+			if (error != CS_OK) {
 				goto error_unlock;
 			}
 			if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
 				error = saRecvRetry (cfg_instance->dispatch_fd, &dispatch_data.data,
 					dispatch_data.header.size - sizeof (mar_res_header_t));
-				if (error != SA_AIS_OK) {
+				if (error != CS_OK) {
 					goto error_unlock;
 				}
 			}
@@ -260,16 +263,21 @@
 		 * A risk of this dispatch method is that the callback routines may
 		 * operate at the same time that cfgFinalize has been called in another thread.
 		 */
-		memcpy (&callbacks, &cfg_instance->callbacks, sizeof (CorosyncCfgCallbacksT));
+		memcpy (&callbacks, &cfg_instance->callbacks, sizeof (corosync_cfg_callbacks_t));
 		pthread_mutex_unlock (&cfg_instance->dispatch_mutex);
 
 		/*
 		 * Dispatch incoming response
 		 */
 		switch (dispatch_data.header.id) {
-
+		case MESSAGE_RES_CFG_TESTSHUTDOWN:
+			if (callbacks.corosync_cfg_shutdown_callback) {
+				res_lib_cfg_testshutdown = (struct res_lib_cfg_testshutdown *)&dispatch_data;
+				callbacks.corosync_cfg_shutdown_callback(cfg_handle, res_lib_cfg_testshutdown->flags);
+			}
+			break;
 		default:
-			error = SA_AIS_ERR_LIBRARY;	
+			error = CS_ERR_LIBRARY;
 			goto error_nounlock;
 			break;
 		}
@@ -277,32 +285,32 @@
 		/*
 		 * Determine if more messages should be processed
 		 */
-		switch (dispatchFlags) {
-		case SA_DISPATCH_ONE:
+		switch (dispatch_flags) {
+		case CS_DISPATCH_ONE:
 			cont = 0;
 			break;
-		case SA_DISPATCH_ALL:
+		case CS_DISPATCH_ALL:
 			break;
-		case SA_DISPATCH_BLOCKING:
+		case CS_DISPATCH_BLOCKING:
 			break;
 		}
 	} while (cont);
 
 error_unlock:
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 error_nounlock:
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_finalize (
 	corosync_cfg_handle_t cfg_handle)
 {
 	struct cfg_instance *cfg_instance;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -316,8 +324,8 @@
 	if (cfg_instance->finalize) {
 		pthread_mutex_unlock (&cfg_instance->response_mutex);
 		pthread_mutex_unlock (&cfg_instance->dispatch_mutex);
-		saHandleInstancePut (&cfg_hdb, cfg_handle);
-		return (SA_AIS_ERR_BAD_HANDLE);
+		(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
+		return (CS_ERR_BAD_HANDLE);
 	}
 
 	cfg_instance->finalize = 1;
@@ -330,7 +338,7 @@
 
 	pthread_mutex_destroy (&cfg_instance->dispatch_mutex);
 
-	saHandleDestroy (&cfg_hdb, cfg_handle);
+	(void)saHandleDestroy (&cfg_hdb, cfg_handle);
 
 	if (cfg_instance->response_fd != -1) {
 		shutdown (cfg_instance->response_fd, 0);
@@ -341,12 +349,12 @@
 		close (cfg_instance->dispatch_fd);
 	}
 
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_ring_status_get (
 	corosync_cfg_handle_t cfg_handle,
 	char ***interface_names,
@@ -357,10 +365,10 @@
 	struct req_lib_cfg_ringstatusget req_lib_cfg_ringstatusget;
 	struct res_lib_cfg_ringstatusget res_lib_cfg_ringstatusget;
 	unsigned int i;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -380,13 +388,13 @@
 	*interface_count = res_lib_cfg_ringstatusget.interface_count;
 	*interface_names = malloc (sizeof (char *) * *interface_count);
 	if (*interface_names == NULL) {
-		return (SA_AIS_ERR_NO_MEMORY);
+		return (CS_ERR_NO_MEMORY);
 	}
 	memset (*interface_names, 0, sizeof (char *) * *interface_count);
 
 	*status = malloc (sizeof (char *) * *interface_count);
 	if (*status == NULL) {
-		error = SA_AIS_ERR_NO_MEMORY;
+		error = CS_ERR_NO_MEMORY;
 		goto error_free_interface_names;
 	}
 	memset (*status, 0, sizeof (char *) * *interface_count);
@@ -394,12 +402,12 @@
 	for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) {
 		(*(interface_names))[i] = strdup (res_lib_cfg_ringstatusget.interface_name[i]);
 		if ((*(interface_names))[i] == NULL) {
-			error = SA_AIS_ERR_NO_MEMORY;
+			error = CS_ERR_NO_MEMORY;
 			goto error_free_contents;
 		}
 		(*(status))[i] = strdup (res_lib_cfg_ringstatusget.interface_status[i]);
 		if ((*(status))[i] == NULL) {
-			error = SA_AIS_ERR_NO_MEMORY;
+			error = CS_ERR_NO_MEMORY;
 			goto error_free_contents;
 		}
 	}
@@ -416,27 +424,27 @@
 	}
 
 	free (*status);
-	
+
 error_free_interface_names:
 	free (*interface_names);
-	
+
 no_error:
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_ring_reenable (
 	corosync_cfg_handle_t cfg_handle)
 {
 	struct cfg_instance *cfg_instance;
 	struct req_lib_cfg_ringreenable req_lib_cfg_ringreenable;
 	struct res_lib_cfg_ringreenable res_lib_cfg_ringreenable;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -452,12 +460,12 @@
 		sizeof (struct res_lib_cfg_ringreenable));
 
 	pthread_mutex_unlock (&cfg_instance->response_mutex);
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_service_load (
 	corosync_cfg_handle_t cfg_handle,
 	char *service_name,
@@ -466,10 +474,10 @@
 	struct cfg_instance *cfg_instance;
 	struct req_lib_cfg_serviceload req_lib_cfg_serviceload;
 	struct res_lib_cfg_serviceload res_lib_cfg_serviceload;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -477,7 +485,7 @@
 	req_lib_cfg_serviceload.header.id = MESSAGE_REQ_CFG_SERVICELOAD;
 	memset (&req_lib_cfg_serviceload.service_name, 0,
 		sizeof (req_lib_cfg_serviceload.service_name));
-	strncpy ((char *)req_lib_cfg_serviceload.service_name, service_name,
+	strncpy (req_lib_cfg_serviceload.service_name, service_name,
 		sizeof (req_lib_cfg_serviceload.service_name) - 1);
 	req_lib_cfg_serviceload.service_ver = service_ver;
 
@@ -490,12 +498,12 @@
 		sizeof (struct res_lib_cfg_serviceload));
 
 	pthread_mutex_unlock (&cfg_instance->response_mutex);
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_service_unload (
 	corosync_cfg_handle_t cfg_handle,
 	char *service_name,
@@ -504,10 +512,10 @@
 	struct cfg_instance *cfg_instance;
 	struct req_lib_cfg_serviceunload req_lib_cfg_serviceunload;
 	struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle, (void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -515,7 +523,7 @@
 	req_lib_cfg_serviceunload.header.id = MESSAGE_REQ_CFG_SERVICEUNLOAD;
 	memset (&req_lib_cfg_serviceunload.service_name, 0,
 		sizeof (req_lib_cfg_serviceunload.service_name));
-	strncpy ((char *)req_lib_cfg_serviceunload.service_name, service_name,
+	strncpy (req_lib_cfg_serviceunload.service_name, service_name,
 		sizeof (req_lib_cfg_serviceunload.service_name) - 1);
 	req_lib_cfg_serviceunload.service_ver = service_ver;
 
@@ -528,29 +536,29 @@
 		sizeof (struct res_lib_cfg_serviceunload));
 
 	pthread_mutex_unlock (&cfg_instance->response_mutex);
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
 	return (error);
 }
-SaAisErrorT
+cs_error_t
 corosync_cfg_state_track (
 	corosync_cfg_handle_t cfg_handle,
-	SaUint8T trackFlags,
-	const CorosyncCfgStateNotificationT *notificationBuffer)
+	uint8_t track_flags,
+	const corosync_cfg_state_notification_t *notification_buffer)
 {
 	struct cfg_instance *cfg_instance;
 	struct req_lib_cfg_statetrack req_lib_cfg_statetrack;
 	struct res_lib_cfg_statetrack res_lib_cfg_statetrack;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	req_lib_cfg_statetrack.header.size = sizeof (struct req_lib_cfg_statetrack);
 	req_lib_cfg_statetrack.header.id = MESSAGE_REQ_CFG_STATETRACKSTART;
-	req_lib_cfg_statetrack.trackFlags = trackFlags;
-	req_lib_cfg_statetrack.notificationBufferAddress = (CorosyncCfgStateNotificationT *)notificationBuffer;
+	req_lib_cfg_statetrack.track_flags = track_flags;
+	req_lib_cfg_statetrack.notification_buffer_address = (corosync_cfg_state_notification_t *)notification_buffer;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
 		(void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -564,23 +572,23 @@
 
 	pthread_mutex_unlock (&cfg_instance->response_mutex);
 
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
-        return (error == SA_AIS_OK ? res_lib_cfg_statetrack.header.error : error);
+        return (error == CS_OK ? res_lib_cfg_statetrack.header.error : error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_state_track_stop (
 	corosync_cfg_handle_t cfg_handle)
 {
 	struct cfg_instance *cfg_instance;
 	struct req_lib_cfg_statetrackstop req_lib_cfg_statetrackstop;
 	struct res_lib_cfg_statetrackstop res_lib_cfg_statetrackstop;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
 		(void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -597,31 +605,33 @@
 
 	pthread_mutex_unlock (&cfg_instance->response_mutex);
 
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
-        return (error == SA_AIS_OK ? res_lib_cfg_statetrackstop.header.error : error);
+        return (error == CS_OK ? res_lib_cfg_statetrackstop.header.error : error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_admin_state_get (
 	corosync_cfg_handle_t cfg_handle,
-	CorosyncCfgAdministrativeTargetT administrativeTarget,
-	CorosyncCfgAdministrativeStateT *administrativeState)
+	corosync_cfg_administrative_target_t administrative_target,
+	corosync_cfg_administrative_state_t *administrative_state)
 {
 	struct cfg_instance *cfg_instance;
 	struct req_lib_cfg_administrativestateget req_lib_cfg_administrativestateget;
 	struct res_lib_cfg_administrativestateget res_lib_cfg_administrativestateget;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
 		(void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	req_lib_cfg_administrativestateget.header.id = MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET;
 	req_lib_cfg_administrativestateget.header.size = sizeof (struct req_lib_cfg_administrativestateget);
-	req_lib_cfg_administrativestateget.administrativeTarget = administrativeTarget;
+	req_lib_cfg_administrativestateget.administrative_target = administrative_target;
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
 
 	error = saSendReceiveReply (cfg_instance->response_fd,
 		&req_lib_cfg_administrativestateget,
@@ -633,32 +643,34 @@
 
 	pthread_mutex_unlock (&cfg_instance->response_mutex);
 
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
-        return (error == SA_AIS_OK ? res_lib_cfg_administrativestateget.header.error : error);
+        return (error == CS_OK ? res_lib_cfg_administrativestateget.header.error : error);
 }
 
-SaAisErrorT
+cs_error_t
 corosync_cfg_admin_state_set (
 	corosync_cfg_handle_t cfg_handle,
-	CorosyncCfgAdministrativeTargetT administrativeTarget,
-	CorosyncCfgAdministrativeStateT administrativeState)
+	corosync_cfg_administrative_target_t administrative_target,
+	corosync_cfg_administrative_state_t administrative_state)
 {
 	struct cfg_instance *cfg_instance;
 	struct req_lib_cfg_administrativestateset req_lib_cfg_administrativestateset;
 	struct res_lib_cfg_administrativestateset res_lib_cfg_administrativestateset;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
 		(void *)&cfg_instance);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	req_lib_cfg_administrativestateset.header.id = MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET;
 	req_lib_cfg_administrativestateset.header.size = sizeof (struct req_lib_cfg_administrativestateset);
-	req_lib_cfg_administrativestateset.administrativeTarget = administrativeTarget;
-	req_lib_cfg_administrativestateset.administrativeState = administrativeState;
+	req_lib_cfg_administrativestateset.administrative_target = administrative_target;
+	req_lib_cfg_administrativestateset.administrative_state = administrative_state;
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
 
 	error = saSendReceiveReply (cfg_instance->response_fd,
 		&req_lib_cfg_administrativestateset,
@@ -670,7 +682,191 @@
 
 	pthread_mutex_unlock (&cfg_instance->response_mutex);
 
-	saHandleInstancePut (&cfg_hdb, cfg_handle);
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
 
-        return (error == SA_AIS_OK ? res_lib_cfg_administrativestateset.header.error : error);
+        return (error == CS_OK ? res_lib_cfg_administrativestateset.header.error : error);
+}
+
+cs_error_t
+corosync_cfg_kill_node (
+	corosync_cfg_handle_t cfg_handle,
+	unsigned int nodeid,
+	char *reason)
+{
+	struct cfg_instance *cfg_instance;
+	struct req_lib_cfg_killnode req_lib_cfg_killnode;
+	struct res_lib_cfg_killnode res_lib_cfg_killnode;
+	cs_error_t error;
+
+	if (strlen(reason) >= CS_MAX_NAME_LENGTH)
+		return CS_ERR_NAME_TOO_LONG;
+
+	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
+		(void *)&cfg_instance);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_killnode.header.id = MESSAGE_REQ_CFG_KILLNODE;
+	req_lib_cfg_killnode.header.size = sizeof (struct req_lib_cfg_killnode);
+	req_lib_cfg_killnode.nodeid = nodeid;
+	strcpy((char *)req_lib_cfg_killnode.reason.value, reason);
+	req_lib_cfg_killnode.reason.length = strlen(reason)+1;
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
+
+	error = saSendReceiveReply (cfg_instance->response_fd,
+		&req_lib_cfg_killnode,
+		sizeof (struct req_lib_cfg_killnode),
+		&res_lib_cfg_killnode,
+		sizeof (struct res_lib_cfg_killnode));
+
+	error = res_lib_cfg_killnode.header.error;
+
+	pthread_mutex_unlock (&cfg_instance->response_mutex);
+
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
+
+        return (error == CS_OK ? res_lib_cfg_killnode.header.error : error);
+}
+
+cs_error_t
+corosync_cfg_try_shutdown (
+	corosync_cfg_handle_t cfg_handle,
+	corosync_cfg_shutdown_flags_t flags)
+{
+	struct cfg_instance *cfg_instance;
+	struct req_lib_cfg_tryshutdown req_lib_cfg_tryshutdown;
+	struct res_lib_cfg_tryshutdown res_lib_cfg_tryshutdown;
+	cs_error_t error;
+
+	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
+		(void *)&cfg_instance);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_tryshutdown.header.id = MESSAGE_REQ_CFG_TRYSHUTDOWN;
+	req_lib_cfg_tryshutdown.header.size = sizeof (struct req_lib_cfg_tryshutdown);
+	req_lib_cfg_tryshutdown.flags = flags;
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
+
+	error = saSendReceiveReply (cfg_instance->response_fd,
+		&req_lib_cfg_tryshutdown,
+		sizeof (struct req_lib_cfg_tryshutdown),
+		&res_lib_cfg_tryshutdown,
+		sizeof (struct res_lib_cfg_tryshutdown));
+
+	pthread_mutex_unlock (&cfg_instance->response_mutex);
+
+	(void)saHandleInstancePut (&cfg_hdb, cfg_handle);
+
+        return (error == CS_OK ? res_lib_cfg_tryshutdown.header.error : error);
+}
+
+cs_error_t
+corosync_cfg_replyto_shutdown (
+	corosync_cfg_handle_t cfg_handle,
+	corosync_cfg_shutdown_reply_flags_t response)
+{
+	struct cfg_instance *cfg_instance;
+	struct req_lib_cfg_replytoshutdown req_lib_cfg_replytoshutdown;
+	struct iovec iov;
+	cs_error_t error;
+
+	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
+		(void *)&cfg_instance);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_replytoshutdown.header.id = MESSAGE_REQ_CFG_REPLYTOSHUTDOWN;
+	req_lib_cfg_replytoshutdown.header.size = sizeof (struct req_lib_cfg_replytoshutdown);
+	req_lib_cfg_replytoshutdown.response = response;
+
+	iov.iov_base = &req_lib_cfg_replytoshutdown;
+	iov.iov_len = sizeof (struct req_lib_cfg_replytoshutdown);
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
+	error = saSendMsgRetry (cfg_instance->response_fd,
+				&iov, 1);
+
+	pthread_mutex_unlock (&cfg_instance->response_mutex);
+
+	return (error);
+}
+
+cs_error_t corosync_cfg_get_node_addrs (
+	corosync_cfg_handle_t cfg_handle,
+	int nodeid,
+	int max_addrs,
+	int *num_addrs,
+	corosync_cfg_node_address_t *addrs)
+{
+	cs_error_t error;
+	char buf[PIPE_BUF];
+	struct req_lib_cfg_get_node_addrs req_lib_cfg_get_node_addrs;
+	struct res_lib_cfg_get_node_addrs * res_lib_cfg_get_node_addrs = (struct res_lib_cfg_get_node_addrs *)buf;
+	struct cfg_instance *cfg_instance;
+	int addrlen;
+	int i;
+	struct iovec iov[2];
+
+	error = saHandleInstanceGet (&cfg_hdb, cfg_handle,
+		(void *)&cfg_instance);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&cfg_instance->response_mutex);
+
+	req_lib_cfg_get_node_addrs.header.size = sizeof (req_lib_cfg_get_node_addrs);
+	req_lib_cfg_get_node_addrs.header.id = MESSAGE_REQ_CFG_GET_NODE_ADDRS;
+	req_lib_cfg_get_node_addrs.nodeid = nodeid;
+
+	iov[0].iov_base = (char *)&req_lib_cfg_get_node_addrs;
+	iov[0].iov_len = sizeof (req_lib_cfg_get_node_addrs);
+
+	error = saSendMsgReceiveReply (cfg_instance->response_fd, iov, 1,
+				       res_lib_cfg_get_node_addrs, sizeof (mar_res_header_t));
+
+	if (error == CS_OK && res_lib_cfg_get_node_addrs->header.size > sizeof(mar_res_header_t)) {
+		error = saRecvRetry (cfg_instance->response_fd, (char *)res_lib_cfg_get_node_addrs + sizeof (mar_res_header_t),
+				     res_lib_cfg_get_node_addrs->header.size - sizeof (mar_res_header_t));
+	}
+	pthread_mutex_unlock (&cfg_instance->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	if (res_lib_cfg_get_node_addrs->family == AF_INET)
+		addrlen = sizeof(struct sockaddr_in);
+	if (res_lib_cfg_get_node_addrs->family == AF_INET6)
+		addrlen = sizeof(struct sockaddr_in6);
+
+	for (i=0; i<max_addrs && i<res_lib_cfg_get_node_addrs->num_addrs; i++) {
+		addrs[i].addressLength = addrlen;
+		struct sockaddr_in *in;
+		struct sockaddr_in6 *in6;
+
+		if (res_lib_cfg_get_node_addrs->family == AF_INET) {
+			in = (struct sockaddr_in *)addrs[i].address;
+			in->sin_family = AF_INET;
+			memcpy(&in->sin_addr, &res_lib_cfg_get_node_addrs->addrs[i][0], sizeof(struct in_addr));
+		}
+		if (res_lib_cfg_get_node_addrs->family == AF_INET6) {
+			in6 = (struct sockaddr_in6 *)addrs[i].address;
+			in6->sin6_family = AF_INET6;
+			memcpy(&in6->sin6_addr, &res_lib_cfg_get_node_addrs->addrs[i][0], sizeof(struct in6_addr));
+		}
+	}
+	*num_addrs = res_lib_cfg_get_node_addrs->num_addrs;
+	errno = error = res_lib_cfg_get_node_addrs->header.error;
+
+error_exit:
+
+	pthread_mutex_unlock (&cfg_instance->response_mutex);
+	return (error);
 }
diff -Naurd corosync-0.92/lib/confdb.c corosync-trunk/lib/confdb.c
--- corosync-0.92/lib/confdb.c	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/lib/confdb.c	2009-01-23 16:41:06.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Red Hat, Inc.
+ * Copyright (c) 2008-2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -42,7 +42,7 @@
 #include <sys/types.h>
 #include <errno.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/confdb.h>
 #include <corosync/ipc_confdb.h>
 #include <corosync/mar_gen.h>
@@ -86,7 +86,7 @@
 };
 
 
-static confdb_error_t do_find_destroy(struct confdb_inst *confdb_inst, unsigned int find_handle);
+static cs_error_t do_find_destroy(struct confdb_inst *confdb_inst, unsigned int find_handle);
 
 
 /* Safely tidy one iterator context list */
@@ -99,7 +99,7 @@
 	     iter != list; iter = tmp, tmp = iter->next) {
 
 		context = list_entry (iter, struct iter_context, list);
-		do_find_destroy(confdb_inst, context->find_handle);
+		(void)do_find_destroy(confdb_inst, context->find_handle);
 		free(context);
 	}
 }
@@ -137,20 +137,20 @@
  * @{
  */
 
-confdb_error_t confdb_initialize (
+cs_error_t confdb_initialize (
 	confdb_handle_t *handle,
 	confdb_callbacks_t *callbacks)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 
 	error = saHandleCreate (&confdb_handle_t_db, sizeof (struct confdb_inst), handle);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_no_destroy;
 	}
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, *handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_destroy;
 	}
 
@@ -163,7 +163,7 @@
 					  &confdb_inst->response_fd,
 					  CONFDB_SERVICE);
 	}
-	if (error != SA_AIS_OK)
+	if (error != CS_OK)
 		goto error_put_destroy;
 
 	memcpy (&confdb_inst->callbacks, callbacks, sizeof (confdb_callbacks_t));
@@ -175,26 +175,26 @@
 	list_init (&confdb_inst->object_iter_head);
 	list_init (&confdb_inst->key_iter_head);
 
-	saHandleInstancePut (&confdb_handle_t_db, *handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, *handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 
 error_put_destroy:
-	saHandleInstancePut (&confdb_handle_t_db, *handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, *handle);
 error_destroy:
-	saHandleDestroy (&confdb_handle_t_db, *handle);
+	(void)saHandleDestroy (&confdb_handle_t_db, *handle);
 error_no_destroy:
 	return (error);
 }
 
-confdb_error_t confdb_finalize (
+cs_error_t confdb_finalize (
 	confdb_handle_t handle)
 {
 	struct confdb_inst *confdb_inst;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -205,15 +205,15 @@
 	 */
 	if (confdb_inst->finalize) {
 		pthread_mutex_unlock (&confdb_inst->response_mutex);
-		saHandleInstancePut (&confdb_handle_t_db, handle);
-		return (CONFDB_ERR_BAD_HANDLE);
+		(void)saHandleInstancePut (&confdb_handle_t_db, handle);
+		return (CS_ERR_BAD_HANDLE);
 	}
 
 	confdb_inst->finalize = 1;
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
 
-	saHandleDestroy (&confdb_handle_t_db, handle);
+	(void)saHandleDestroy (&confdb_handle_t_db, handle);
 
 	/* Free saved context handles */
 	free_context_list(confdb_inst, &confdb_inst->object_find_head);
@@ -233,80 +233,80 @@
 			close(confdb_inst->dispatch_fd);
 		}
 	}
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
-	return (CONFDB_OK);
+	return (CS_OK);
 }
 
-confdb_error_t confdb_fd_get (
+cs_error_t confdb_fd_get (
 	confdb_handle_t handle,
 	int *fd)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	*fd = confdb_inst->dispatch_fd;
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
-confdb_error_t confdb_context_get (
+cs_error_t confdb_context_get (
 	confdb_handle_t handle,
 	void **context)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	*context = confdb_inst->context;
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
-confdb_error_t confdb_context_set (
+cs_error_t confdb_context_set (
 	confdb_handle_t handle,
 	void *context)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	confdb_inst->context = context;
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
-struct res_overlay {
+struct confdb_res_overlay {
 	mar_res_header_t header __attribute__((aligned(8)));
 	char data[512000];
 };
 
-confdb_error_t confdb_dispatch (
+cs_error_t confdb_dispatch (
 	confdb_handle_t handle,
-	confdb_dispatch_t dispatch_types)
+	cs_dispatch_flags_t dispatch_types)
 {
 	struct pollfd ufds;
 	int timeout = -1;
-	SaAisErrorT error;
+	cs_error_t error;
 	int cont = 1; /* always continue do loop except when set to 0 */
 	int dispatch_avail;
 	struct confdb_inst *confdb_inst;
@@ -314,16 +314,15 @@
 	struct res_lib_confdb_key_change_callback *res_key_changed_pt;
 	struct res_lib_confdb_object_create_callback *res_object_created_pt;
 	struct res_lib_confdb_object_destroy_callback *res_object_destroyed_pt;
-	struct res_overlay dispatch_data;
-	int ignore_dispatch = 0;
+	struct confdb_res_overlay dispatch_data;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = CONFDB_ERR_NOT_SUPPORTED;
+		error = CS_ERR_NOT_SUPPORTED;
 		goto error_unlock;
 	}
 
@@ -341,7 +340,7 @@
 		ufds.revents = 0;
 
 		error = saPollRetry (&ufds, 1, timeout);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
@@ -351,7 +350,7 @@
 		 * Regather poll data in case ufds has changed since taking lock
 		 */
 		error = saPollRetry (&ufds, 1, timeout);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
@@ -359,7 +358,7 @@
 		 * Handle has been finalized in another thread
 		 */
 		if (confdb_inst->finalize == 1) {
-			error = CONFDB_OK;
+			error = CS_OK;
 			pthread_mutex_unlock (&confdb_inst->dispatch_mutex);
 			goto error_unlock;
 		}
@@ -380,14 +379,14 @@
 			 */
 			error = saRecvRetry (confdb_inst->dispatch_fd, &dispatch_data.header,
 				sizeof (mar_res_header_t));
-			if (error != SA_AIS_OK) {
+			if (error != CS_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) {
+				if (error != CS_OK) {
 					goto error_unlock;
 				}
 			}
@@ -443,7 +442,7 @@
 				break;
 
 			default:
-				error = SA_AIS_ERR_LIBRARY;
+				error = CS_ERR_LIBRARY;
 				goto error_nounlock;
 				break;
 		}
@@ -453,16 +452,9 @@
 		 * */
 		switch (dispatch_types) {
 		case CONFDB_DISPATCH_ONE:
-			if (ignore_dispatch) {
-				ignore_dispatch = 0;
-			} else {
-				cont = 0;
-			}
+			cont = 0;
 			break;
 		case CONFDB_DISPATCH_ALL:
-			if (ignore_dispatch) {
-				ignore_dispatch = 0;
-			}
 			break;
 		case CONFDB_DISPATCH_BLOCKING:
 			break;
@@ -470,36 +462,36 @@
 	} while (cont);
 
 error_unlock:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 error_nounlock:
 	return (error);
 }
 
-confdb_error_t confdb_object_create (
+cs_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;
+	cs_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) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_object_create(parent_object_handle,
 					    object_name, object_name_len,
 					    object_handle))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -518,7 +510,7 @@
 		&res_lib_confdb_object_create, sizeof (struct res_lib_confdb_object_create));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -526,31 +518,31 @@
 	*object_handle = res_lib_confdb_object_create.object_handle;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_object_destroy (
+cs_error_t confdb_object_destroy (
 	confdb_handle_t handle,
 	unsigned int object_handle)
 {
-	confdb_error_t error;
+	cs_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) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_object_destroy(object_handle))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -567,39 +559,39 @@
 		&res, sizeof ( mar_res_header_t));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res.error;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_object_parent_get (
+cs_error_t confdb_object_parent_get (
 	confdb_handle_t handle,
 	unsigned int object_handle,
 	unsigned int *parent_object_handle)
 {
-	confdb_error_t error;
+	cs_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) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_object_parent_get(object_handle, parent_object_handle))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -616,7 +608,7 @@
 		&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) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -624,28 +616,28 @@
 	*parent_object_handle = res_lib_confdb_object_parent_get.parent_object_handle;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-static confdb_error_t do_find_destroy(
+static cs_error_t do_find_destroy(
 	struct confdb_inst *confdb_inst,
 	unsigned int find_handle)
 {
-	confdb_error_t error;
+	cs_error_t error;
 	struct iovec iov[2];
 	struct req_lib_confdb_object_find_destroy req_lib_confdb_object_find_destroy;
 	mar_res_header_t res;
 
 	if (!find_handle)
-		return SA_AIS_OK;
+		return CS_OK;
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_find_destroy(find_handle))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -662,7 +654,7 @@
 		&res, sizeof (mar_res_header_t));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -673,56 +665,56 @@
 	return (error);
 }
 
-confdb_error_t confdb_object_find_destroy(
+cs_error_t confdb_object_find_destroy(
 	confdb_handle_t handle,
 	unsigned int parent_object_handle)
 {
 	struct iter_context *context;
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	context = find_iter_context(&confdb_inst->object_find_head, parent_object_handle);
 	error = do_find_destroy(confdb_inst, context->find_handle);
-	if (error == SA_AIS_OK) {
+	if (error == CS_OK) {
 		list_del(&context->list);
 		free(context);
 	}
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 	return error;
 }
 
-confdb_error_t confdb_object_iter_destroy(
+cs_error_t confdb_object_iter_destroy(
 	confdb_handle_t handle,
 	unsigned int parent_object_handle)
 {
 	struct iter_context *context;
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	context = find_iter_context(&confdb_inst->object_iter_head, parent_object_handle);
 	error = do_find_destroy(confdb_inst, context->find_handle);
-	if (error == SA_AIS_OK) {
+	if (error == CS_OK) {
 		list_del(&context->list);
 		free(context);
 	}
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 	return error;
 }
 
 
-confdb_error_t confdb_key_create (
+cs_error_t confdb_key_create (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -730,24 +722,24 @@
 	void *value,
 	int value_len)
 {
-	confdb_error_t error;
+	cs_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) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_key_create(parent_object_handle,
 					 key_name, key_name_len,
 					 value, value_len))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -768,19 +760,19 @@
 		&res, sizeof (res));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res.error;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_key_delete (
+cs_error_t confdb_key_delete (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -788,24 +780,24 @@
 	void *value,
 	int value_len)
 {
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	struct req_lib_confdb_key_delete req_lib_confdb_key_delete;
 	mar_res_header_t res;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_key_delete(parent_object_handle,
 					 key_name, key_name_len,
 					 value, value_len))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -826,19 +818,19 @@
 		&res, sizeof (res));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res.error;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_key_get (
+cs_error_t confdb_key_get (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -846,24 +838,24 @@
 	void *value,
 	int *value_len)
 {
-	confdb_error_t error;
+	cs_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) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_key_get(parent_object_handle,
 				      key_name, key_name_len,
 				      value, value_len))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -882,47 +874,47 @@
 		&res_lib_confdb_key_get, sizeof (struct res_lib_confdb_key_get));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_confdb_key_get.header.error;
-	if (error == SA_AIS_OK) {
+	if (error == CS_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);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_key_increment (
+cs_error_t confdb_key_increment (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
 	int key_name_len,
 	unsigned int *value)
 {
-	confdb_error_t error;
+	cs_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_incdec res_lib_confdb_key_incdec;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_key_increment(parent_object_handle,
 					    key_name, key_name_len,
 					    value))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -941,46 +933,46 @@
 		&res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_confdb_key_incdec.header.error;
-	if (error == SA_AIS_OK) {
+	if (error == CS_OK) {
 		*value = res_lib_confdb_key_incdec.value;
 	}
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_key_decrement (
+cs_error_t confdb_key_decrement (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
 	int key_name_len,
 	unsigned int *value)
 {
-	confdb_error_t error;
+	cs_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_incdec res_lib_confdb_key_incdec;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_key_decrement(parent_object_handle,
 					    key_name, key_name_len,
 					    value))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -999,22 +991,22 @@
 		&res_lib_confdb_key_incdec, sizeof (struct res_lib_confdb_key_incdec));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_confdb_key_incdec.header.error;
-	if (error == SA_AIS_OK) {
+	if (error == CS_OK) {
 		*value = res_lib_confdb_key_incdec.value;
 	}
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_key_replace (
+cs_error_t confdb_key_replace (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -1024,25 +1016,25 @@
 	void *new_value,
 	int new_value_len)
 {
-	confdb_error_t error;
+	cs_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) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_key_replace(parent_object_handle,
 					  key_name, key_name_len,
 					  old_value, old_value_len,
 					  new_value, new_value_len))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 	req_lib_confdb_key_replace.header.size = sizeof (struct req_lib_confdb_key_replace);
@@ -1064,28 +1056,28 @@
 		&res, sizeof (res));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res.error;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_object_iter_start (
+cs_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;
+	cs_error_t error = CS_OK;
 	struct iter_context *context;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -1093,7 +1085,7 @@
 	if (!context) {
 		context = malloc(sizeof(struct iter_context));
 		if (!context) {
-			error = CONFDB_ERR_NO_MEMORY;
+			error = CS_ERR_NO_MEMORY;
 			goto ret;
 		}
 		context->parent_object_handle = object_handle;
@@ -1103,26 +1095,26 @@
 
 	/* Start a new find context */
 	if (context->find_handle) {
-		do_find_destroy(confdb_inst, context->find_handle);
+		(void)do_find_destroy(confdb_inst, context->find_handle);
 		context->find_handle = 0;
 	}
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 ret:
 	return error;
 }
 
-confdb_error_t confdb_key_iter_start (
+cs_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;
+	cs_error_t error = CS_OK;
 	struct iter_context *context;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -1130,7 +1122,7 @@
 	if (!context) {
 		context = malloc(sizeof(struct iter_context));
 		if (!context) {
-			error = CONFDB_ERR_NO_MEMORY;
+			error = CS_ERR_NO_MEMORY;
 			goto ret;
 		}
 		context->parent_object_handle = object_handle;
@@ -1140,22 +1132,22 @@
 	context->find_handle = 0;
 	context->next_entry = 0;
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 ret:
 	return error;
 }
 
-confdb_error_t confdb_object_find_start (
+cs_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;
+	cs_error_t error = CS_OK;
 	struct iter_context *context;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -1163,7 +1155,7 @@
 	if (!context) {
 		context = malloc(sizeof(struct iter_context));
 		if (!context) {
-			error = CONFDB_ERR_NO_MEMORY;
+			error = CS_ERR_NO_MEMORY;
 			goto ret;
 		}
 		context->find_handle = 0;
@@ -1172,24 +1164,24 @@
 	}
 	/* Start a new find context */
 	if (context->find_handle) {
-		do_find_destroy(confdb_inst, context->find_handle);
+		(void)do_find_destroy(confdb_inst, context->find_handle);
 		context->find_handle = 0;
 	}
 
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 ret:
 	return error;
 }
 
-confdb_error_t confdb_object_find (
+cs_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;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	struct iter_context *context;
@@ -1197,26 +1189,26 @@
 	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) {
+	if (error != CS_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;
+		error =	CS_ERR_CONTEXT_NOT_FOUND;
 		goto error_exit;
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_object_find(parent_object_handle,
 					  &context->find_handle,
 					  object_handle,
 					  object_name, &object_name_len,
 					  0))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -1236,7 +1228,7 @@
 		&res_lib_confdb_object_find, sizeof (struct res_lib_confdb_object_find));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -1245,20 +1237,20 @@
 	context->find_handle = res_lib_confdb_object_find.find_handle;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
 
-confdb_error_t confdb_object_iter (
+cs_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;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	struct iter_context *context;
@@ -1266,19 +1258,19 @@
 	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) {
+	if (error != CS_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;
+		error =	CS_ERR_CONTEXT_NOT_FOUND;
 		goto error_exit;
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		*object_name_len = 0;
 		if (confdb_sa_object_find(parent_object_handle,
@@ -1286,7 +1278,7 @@
 					  object_handle,
 					  object_name, object_name_len,
 					  1))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto sa_exit;
 	}
 
@@ -1304,12 +1296,12 @@
 		&res_lib_confdb_object_iter, sizeof (struct res_lib_confdb_object_iter));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_confdb_object_iter.header.error;
-	if (error == SA_AIS_OK) {
+	if (error == CS_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;
@@ -1318,12 +1310,12 @@
 sa_exit:
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_key_iter (
+cs_error_t confdb_key_iter (
 	confdb_handle_t handle,
 	unsigned int parent_object_handle,
 	void *key_name,
@@ -1331,7 +1323,7 @@
 	void *value,
 	int *value_len)
 {
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	struct iter_context *context;
@@ -1339,25 +1331,25 @@
 	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) {
+	if (error != CS_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;
+		error =	CS_ERR_CONTEXT_NOT_FOUND;
 		goto error_exit;
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_key_iter(parent_object_handle,
 				       context->next_entry,
 				       key_name, key_name_len,
 				       value, value_len))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto sa_exit;
 	}
 
@@ -1375,12 +1367,12 @@
 		&res_lib_confdb_key_iter, sizeof (struct res_lib_confdb_key_iter));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_confdb_key_iter.header.error;
-	if (error == SA_AIS_OK) {
+	if (error == CS_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;
@@ -1391,31 +1383,31 @@
 	context->next_entry++;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_write (
+cs_error_t confdb_write (
 	confdb_handle_t handle,
 	char *error_text)
 {
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	mar_req_header_t req;
 	struct res_lib_confdb_write res_lib_confdb_write;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_write(error_text))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -1431,7 +1423,7 @@
 				       &res_lib_confdb_write, sizeof ( struct res_lib_confdb_write));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -1440,32 +1432,32 @@
 		memcpy(error_text, res_lib_confdb_write.error.value, res_lib_confdb_write.error.length);
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_reload (
+cs_error_t confdb_reload (
 	confdb_handle_t handle,
 	int flush,
 	char *error_text)
 {
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	struct res_lib_confdb_reload res_lib_confdb_reload;
 	struct req_lib_confdb_reload req_lib_confdb_reload;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = SA_AIS_OK;
+		error = CS_OK;
 
 		if (confdb_sa_reload(flush, error_text))
-			error = SA_AIS_ERR_ACCESS;
+			error = CS_ERR_ACCESS;
 		goto error_exit;
 	}
 
@@ -1483,7 +1475,7 @@
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -1492,29 +1484,29 @@
 		memcpy(error_text, res_lib_confdb_reload.error.value, res_lib_confdb_reload.error.length);
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_track_changes (
+cs_error_t confdb_track_changes (
 	confdb_handle_t handle,
 	unsigned int object_handle,
 	unsigned int flags)
 {
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	struct req_lib_confdb_object_track_start req;
 	mar_res_header_t res;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = CONFDB_ERR_NOT_SUPPORTED;
+		error = CS_ERR_NOT_SUPPORTED;
 		goto error_exit;
 	}
 
@@ -1532,33 +1524,33 @@
 		&res, sizeof ( mar_res_header_t));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res.error;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
 
-confdb_error_t confdb_stop_track_changes (confdb_handle_t handle)
+cs_error_t confdb_stop_track_changes (confdb_handle_t handle)
 {
-	confdb_error_t error;
+	cs_error_t error;
 	struct confdb_inst *confdb_inst;
 	struct iovec iov[2];
 	mar_req_header_t req;
 	mar_res_header_t res;
 
 	error = saHandleInstanceGet (&confdb_handle_t_db, handle, (void *)&confdb_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	if (confdb_inst->standalone) {
-		error = CONFDB_ERR_NOT_SUPPORTED;
+		error = CS_ERR_NOT_SUPPORTED;
 		goto error_exit;
 	}
 
@@ -1574,14 +1566,14 @@
 		&res, sizeof ( mar_res_header_t));
 
 	pthread_mutex_unlock (&confdb_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res.error;
 
 error_exit:
-	saHandleInstancePut (&confdb_handle_t_db, handle);
+	(void)saHandleInstancePut (&confdb_handle_t_db, handle);
 
 	return (error);
 }
diff -Naurd corosync-0.92/lib/cpg.c corosync-trunk/lib/cpg.c
--- corosync-0.92/lib/cpg.c	2008-09-17 21:15:00.000000000 +0200
+++ corosync-trunk/lib/cpg.c	2009-01-08 07:29:16.000000000 +0100
@@ -45,7 +45,7 @@
 #include <sys/socket.h>
 #include <errno.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/cpg.h>
 #include <corosync/ipc_cpg.h>
 #include <corosync/mar_cpg.h>
@@ -90,27 +90,27 @@
  * @{
  */
 
-cpg_error_t cpg_initialize (
+cs_error_t cpg_initialize (
 	cpg_handle_t *handle,
 	cpg_callbacks_t *callbacks)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 
 	error = saHandleCreate (&cpg_handle_t_db, sizeof (struct cpg_inst), handle);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_no_destroy;
 	}
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, *handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_destroy;
 	}
 
 	error = saServiceConnect (&cpg_inst->dispatch_fd,
 				     &cpg_inst->response_fd,
 		CPG_SERVICE);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_put_destroy;
 	}
 
@@ -120,26 +120,26 @@
 
 	pthread_mutex_init (&cpg_inst->dispatch_mutex, NULL);
 
-	saHandleInstancePut (&cpg_handle_t_db, *handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, *handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 
 error_put_destroy:
-	saHandleInstancePut (&cpg_handle_t_db, *handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, *handle);
 error_destroy:
-	saHandleDestroy (&cpg_handle_t_db, *handle);
+	(void)saHandleDestroy (&cpg_handle_t_db, *handle);
 error_no_destroy:
 	return (error);
 }
 
-cpg_error_t cpg_finalize (
+cs_error_t cpg_finalize (
 	cpg_handle_t handle)
 {
 	struct cpg_inst *cpg_inst;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -150,15 +150,15 @@
 	 */
 	if (cpg_inst->finalize) {
 		pthread_mutex_unlock (&cpg_inst->response_mutex);
-		saHandleInstancePut (&cpg_handle_t_db, handle);
-		return (CPG_ERR_BAD_HANDLE);
+		(void)saHandleInstancePut (&cpg_handle_t_db, handle);
+		return (CS_ERR_BAD_HANDLE);
 	}
 
 	cpg_inst->finalize = 1;
 
 	pthread_mutex_unlock (&cpg_inst->response_mutex);
 
-	saHandleDestroy (&cpg_handle_t_db, handle);
+	(void)saHandleDestroy (&cpg_handle_t_db, handle);
 
 	/*
 	 * Disconnect from the server
@@ -171,80 +171,80 @@
 		shutdown(cpg_inst->dispatch_fd, 0);
 		close(cpg_inst->dispatch_fd);
 	}
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
-	return (CPG_OK);
+	return (CS_OK);
 }
 
-cpg_error_t cpg_fd_get (
+cs_error_t cpg_fd_get (
 	cpg_handle_t handle,
 	int *fd)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	*fd = cpg_inst->dispatch_fd;
 
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
-cpg_error_t cpg_context_get (
+cs_error_t cpg_context_get (
 	cpg_handle_t handle,
 	void **context)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	*context = cpg_inst->context;
 
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
-cpg_error_t cpg_context_set (
+cs_error_t cpg_context_set (
 	cpg_handle_t handle,
 	void *context)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	cpg_inst->context = context;
 
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
-struct res_overlay {
+struct cpg_res_overlay {
 	mar_res_header_t header __attribute__((aligned(8)));
 	char data[512000];
 };
 
-cpg_error_t cpg_dispatch (
+cs_error_t cpg_dispatch (
 	cpg_handle_t handle,
-	cpg_dispatch_t dispatch_types)
+	cs_dispatch_flags_t dispatch_types)
 {
 	struct pollfd ufds;
 	int timeout = -1;
-	SaAisErrorT error;
+	cs_error_t error;
 	int cont = 1; /* always continue do loop except when set to 0 */
 	int dispatch_avail;
 	struct cpg_inst *cpg_inst;
@@ -253,8 +253,7 @@
 	struct res_lib_cpg_deliver_callback *res_cpg_deliver_callback;
 	struct res_lib_cpg_groups_get_callback *res_lib_cpg_groups_get_callback;
 	cpg_callbacks_t callbacks;
-	struct res_overlay dispatch_data;
-	int ignore_dispatch = 0;
+	struct cpg_res_overlay dispatch_data;
 	struct cpg_address member_list[CPG_MEMBERS_MAX];
 	struct cpg_address left_list[CPG_MEMBERS_MAX];
 	struct cpg_address joined_list[CPG_MEMBERS_MAX];
@@ -264,7 +263,7 @@
 	unsigned int i;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -272,7 +271,7 @@
 	 * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and
 	 * wait indefinately for SA_DISPATCH_BLOCKING
 	 */
-	if (dispatch_types == CPG_DISPATCH_ALL) {
+	if (dispatch_types == CS_DISPATCH_ALL) {
 		timeout = 0;
 	}
 
@@ -282,7 +281,7 @@
 		ufds.revents = 0;
 
 		error = saPollRetry (&ufds, 1, timeout);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
@@ -292,7 +291,7 @@
 		 * Regather poll data in case ufds has changed since taking lock
 		 */
 		error = saPollRetry (&ufds, 1, timeout);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
@@ -300,13 +299,13 @@
 		 * Handle has been finalized in another thread
 		 */
 		if (cpg_inst->finalize == 1) {
-			error = CPG_OK;
+			error = CS_OK;
 			pthread_mutex_unlock (&cpg_inst->dispatch_mutex);
 			goto error_unlock;
 		}
 
 		dispatch_avail = ufds.revents & POLLIN;
-		if (dispatch_avail == 0 && dispatch_types == CPG_DISPATCH_ALL) {
+		if (dispatch_avail == 0 && dispatch_types == CS_DISPATCH_ALL) {
 			pthread_mutex_unlock (&cpg_inst->dispatch_mutex);
 			break; /* exit do while cont is 1 loop */
 		} else
@@ -321,14 +320,14 @@
 			 */
 			error = saRecvRetry (cpg_inst->dispatch_fd, &dispatch_data.header,
 				sizeof (mar_res_header_t));
-			if (error != SA_AIS_OK) {
+			if (error != CS_OK) {
 				goto error_unlock;
 			}
 			if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
 				error = saRecvRetry (cpg_inst->dispatch_fd, &dispatch_data.data,
 					dispatch_data.header.size - sizeof (mar_res_header_t));
 
-				if (error != SA_AIS_OK) {
+				if (error != CS_OK) {
 					goto error_unlock;
 				}
 			}
@@ -424,7 +423,7 @@
 			break;
 
 		default:
-			error = SA_AIS_ERR_LIBRARY;
+			error = CS_ERR_LIBRARY;
 			goto error_nounlock;
 			break;
 		}
@@ -433,34 +432,27 @@
 		 * Determine if more messages should be processed
 		 * */
 		switch (dispatch_types) {
-		case CPG_DISPATCH_ONE:
-			if (ignore_dispatch) {
-				ignore_dispatch = 0;
-			} else {
-				cont = 0;
-			}
+		case CS_DISPATCH_ONE:
+			cont = 0;
 			break;
-		case CPG_DISPATCH_ALL:
-			if (ignore_dispatch) {
-				ignore_dispatch = 0;
-			}
+		case CS_DISPATCH_ALL:
 			break;
-		case CPG_DISPATCH_BLOCKING:
+		case CS_DISPATCH_BLOCKING:
 			break;
 		}
 	} while (cont);
 
 error_unlock:
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 error_nounlock:
 	return (error);
 }
 
-cpg_error_t cpg_join (
+cs_error_t cpg_join (
     cpg_handle_t handle,
     struct cpg_name *group)
 {
-	cpg_error_t error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 	struct iovec iov[2];
 	struct req_lib_cpg_join req_lib_cpg_join;
@@ -469,7 +461,7 @@
 	struct res_lib_cpg_trackstart res_lib_cpg_trackstart;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -487,7 +479,7 @@
 	error = saSendMsgReceiveReply (cpg_inst->dispatch_fd, iov, 1,
 		&res_lib_cpg_trackstart, sizeof (struct res_lib_cpg_trackstart));
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		pthread_mutex_unlock (&cpg_inst->response_mutex);
 		goto error_exit;
 	}
@@ -507,30 +499,30 @@
 
 	pthread_mutex_unlock (&cpg_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_cpg_join.header.error;
 
 error_exit:
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
 	return (error);
 }
 
-cpg_error_t cpg_leave (
+cs_error_t cpg_leave (
     cpg_handle_t handle,
     struct cpg_name *group)
 {
-	cpg_error_t error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 	struct iovec iov[2];
 	struct req_lib_cpg_leave req_lib_cpg_leave;
 	struct res_lib_cpg_leave res_lib_cpg_leave;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -549,26 +541,26 @@
 		&res_lib_cpg_leave, sizeof (struct res_lib_cpg_leave));
 
 	pthread_mutex_unlock (&cpg_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_cpg_leave.header.error;
 
 error_exit:
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
 	return (error);
 }
 
-cpg_error_t cpg_mcast_joined (
+cs_error_t cpg_mcast_joined (
 	cpg_handle_t handle,
 	cpg_guarantee_t guarantee,
 	struct iovec *iovec,
 	int iov_len)
 {
 	int i;
-	cpg_error_t error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 	struct iovec iov[64];
 	struct req_lib_cpg_mcast req_lib_cpg_mcast;
@@ -576,7 +568,7 @@
 	int msg_len = 0;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -602,7 +594,7 @@
 
 	pthread_mutex_unlock (&cpg_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -612,85 +604,108 @@
  *	Also, don't set to ENABLED if the return value is TRY_AGAIN as this can lead
  *	to Flow Control State sync issues between AIS LIB and EXEC.
  */
-	if (res_lib_cpg_mcast.header.error == CPG_OK) {
+	if (res_lib_cpg_mcast.header.error == CS_OK) {
 		cpg_inst->flow_control_state = res_lib_cpg_mcast.flow_control_state;
 	}
 	error = res_lib_cpg_mcast.header.error;
 
 error_exit:
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
 	return (error);
 }
 
-cpg_error_t cpg_membership_get (
+cs_error_t cpg_membership_get (
 	cpg_handle_t handle,
 	struct cpg_name *group_name,
 	struct cpg_address *member_list,
 	int *member_list_entries)
 {
-	cpg_error_t error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 	struct iovec iov;
 	struct req_lib_cpg_membership req_lib_cpg_membership_get;
-	struct res_lib_cpg_confchg_callback res_lib_cpg_membership_get;
-	unsigned int i;
+	struct res_lib_cpg_confchg_callback *res_lib_cpg_membership_get;
+	mar_res_header_t header;
+	unsigned int i, bytesleft;
+	char *buffer = NULL;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
-	req_lib_cpg_membership_get.header.size = sizeof (mar_req_header_t);
+	req_lib_cpg_membership_get.header.size = sizeof (req_lib_cpg_membership_get);
 	req_lib_cpg_membership_get.header.id = MESSAGE_REQ_CPG_MEMBERSHIP;
-	marshall_to_mar_cpg_name_t (&req_lib_cpg_membership_get.group_name,
-		group_name);
 
 	iov.iov_base = (char *)&req_lib_cpg_membership_get;
-	iov.iov_len = sizeof (mar_req_header_t);
+	iov.iov_len = sizeof (req_lib_cpg_membership_get);
 
 	pthread_mutex_lock (&cpg_inst->response_mutex);
 
 	error = saSendMsgReceiveReply (cpg_inst->response_fd, &iov, 1,
-		&res_lib_cpg_membership_get, sizeof (mar_res_header_t));
+		&header, sizeof (header));
+	if (error != CS_OK) {
+		goto error_exit;
+	}
 
-	pthread_mutex_unlock (&cpg_inst->response_mutex);
+	buffer = malloc(header.size);
+	if (buffer == NULL) {
+		error = CS_ERR_NO_MEMORY;
+		goto error_exit;
+	}
 
-	if (error != SA_AIS_OK) {
+	memcpy (buffer, &header, sizeof (header));
+	bytesleft = header.size - sizeof (header);
+
+	error = saRecvRetry (cpg_inst->response_fd,
+		buffer + sizeof (header), bytesleft);
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
-	error = res_lib_cpg_membership_get.header.error;
+	error = header.error;
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	res_lib_cpg_membership_get = (struct res_lib_cpg_confchg_callback *) buffer;
 
 	/*
 	 * Copy results to caller
 	 */
-	*member_list_entries = res_lib_cpg_membership_get.member_list_entries;
+	*member_list_entries = res_lib_cpg_membership_get->member_list_entries;
 	if (member_list) {
-		for (i = 0; i < res_lib_cpg_membership_get.member_list_entries; i++) {
+		for (i = 0; i < res_lib_cpg_membership_get->member_list_entries; i++) {
 			marshall_from_mar_cpg_address_t (&member_list[i],
-				&res_lib_cpg_membership_get.member_list[i]);
+				&res_lib_cpg_membership_get->member_list[i]);
 		}
 	}
 
 error_exit:
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+
+	if (buffer != NULL)
+		free(buffer);
+
+	pthread_mutex_unlock (&cpg_inst->response_mutex);
+
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
 	return (error);
 }
 
-cpg_error_t cpg_local_get (
+cs_error_t cpg_local_get (
 	cpg_handle_t handle,
 	unsigned int *local_nodeid)
 {
-	cpg_error_t error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 	struct iovec iov;
 	struct req_lib_cpg_local_get req_lib_cpg_local_get;
 	struct res_lib_cpg_local_get res_lib_cpg_local_get;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -707,7 +722,7 @@
 
 	pthread_mutex_unlock (&cpg_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -716,23 +731,23 @@
 	*local_nodeid = res_lib_cpg_local_get.local_nodeid;
 
 error_exit:
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
 	return (error);
 }
 
-cpg_error_t cpg_groups_get (
+cs_error_t cpg_groups_get (
 	cpg_handle_t handle,
 	unsigned int *num_groups)
 {
-	cpg_error_t error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 	struct iovec iov;
 	struct req_lib_cpg_groups_get req_lib_cpg_groups_get;
 	struct res_lib_cpg_groups_get res_lib_cpg_groups_get;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -749,7 +764,7 @@
 
 	pthread_mutex_unlock (&cpg_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -758,26 +773,26 @@
 
 	/* Real output is delivered via a callback */
 error_exit:
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
 	return (error);
 }
 
-cpg_error_t cpg_flow_control_state_get (
+cs_error_t cpg_flow_control_state_get (
 	cpg_handle_t handle,
 	cpg_flow_control_state_t *flow_control_state)
 {
-	cpg_error_t error;
+	cs_error_t error;
 	struct cpg_inst *cpg_inst;
 
 	error = saHandleInstanceGet (&cpg_handle_t_db, handle, (void *)&cpg_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	*flow_control_state = cpg_inst->flow_control_state;
 
-	saHandleInstancePut (&cpg_handle_t_db, handle);
+	(void)saHandleInstancePut (&cpg_handle_t_db, handle);
 
 	return (error);
 }
diff -Naurd corosync-0.92/lib/evs.c corosync-trunk/lib/evs.c
--- corosync-0.92/lib/evs.c	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/lib/evs.c	2008-12-28 10:25:17.000000000 +0100
@@ -48,7 +48,7 @@
 
 #include <corosync/swab.h>
 #include <corosync/totem/totem.h>
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/evs.h>
 #include <corosync/ipc_evs.h>
 #include <corosync/ais_util.h>
@@ -62,7 +62,7 @@
 	pthread_mutex_t dispatch_mutex;
 };
 
-struct res_overlay {
+struct evs_res_overlay {
 	mar_res_header_t header __attribute__((aligned(8)));
 	char data[512000];
 };
@@ -98,29 +98,29 @@
  * test
  * @param handle The handle of evs initialize
  * @param callbacks The callbacks for evs_initialize
- * @returns EVS_OK
+ * @returns CS_OK
  */
-evs_error_t evs_initialize (
+cs_error_t evs_initialize (
 	evs_handle_t *handle,
 	evs_callbacks_t *callbacks)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct evs_inst *evs_inst;
 
 	error = saHandleCreate (&evs_handle_t_db, sizeof (struct evs_inst), handle);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_no_destroy;
 	}
 
 	error = saHandleInstanceGet (&evs_handle_t_db, *handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_destroy;
 	}
 
 	error = saServiceConnect (&evs_inst->response_fd,
 		&evs_inst->dispatch_fd,
 		EVS_SERVICE);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_put_destroy;
 	}
 
@@ -130,26 +130,26 @@
 
 	pthread_mutex_init (&evs_inst->dispatch_mutex, NULL);
 
-	saHandleInstancePut (&evs_handle_t_db, *handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, *handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 
 error_put_destroy:
-	saHandleInstancePut (&evs_handle_t_db, *handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, *handle);
 error_destroy:
-	saHandleDestroy (&evs_handle_t_db, *handle);
+	(void)saHandleDestroy (&evs_handle_t_db, *handle);
 error_no_destroy:
 	return (error);
 }
 
-evs_error_t evs_finalize (
+cs_error_t evs_finalize (
 	evs_handle_t handle)
 {
 	struct evs_inst *evs_inst;
-	SaAisErrorT error;
+	cs_error_t error;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 //	  TODO is the locking right here
@@ -160,15 +160,15 @@
 	 */
 	if (evs_inst->finalize) {
 		pthread_mutex_unlock (&evs_inst->response_mutex);
-		saHandleInstancePut (&evs_handle_t_db, handle);
-		return (EVS_ERR_BAD_HANDLE);
+		(void)saHandleInstancePut (&evs_handle_t_db, handle);
+		return (CS_ERR_BAD_HANDLE);
 	}
 
 	evs_inst->finalize = 1;
 
 	pthread_mutex_unlock (&evs_inst->response_mutex);
 
-	saHandleDestroy (&evs_handle_t_db, handle);
+	(void)saHandleDestroy (&evs_handle_t_db, handle);
     /*
      * Disconnect from the server
      */
@@ -180,49 +180,48 @@
         shutdown(evs_inst->dispatch_fd, 0);
         close(evs_inst->dispatch_fd);
     }
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 
 
-	return (EVS_OK);
+	return (CS_OK);
 }
 
-evs_error_t evs_fd_get (
+cs_error_t evs_fd_get (
 	evs_handle_t handle,
 	int *fd)
 {
-	SaAisErrorT error;
+	cs_error_t error;
 	struct evs_inst *evs_inst;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
 	*fd = evs_inst->dispatch_fd; 
 
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
-evs_error_t evs_dispatch (
+cs_error_t evs_dispatch (
 	evs_handle_t handle,
-	evs_dispatch_t dispatch_types)
+	cs_dispatch_flags_t dispatch_types)
 {
 	struct pollfd ufds;
 	int timeout = -1;
-	SaAisErrorT error;
+	cs_error_t error;
 	int cont = 1; /* always continue do loop except when set to 0 */
 	int dispatch_avail;
 	struct evs_inst *evs_inst;
 	struct res_evs_confchg_callback *res_evs_confchg_callback;
 	struct res_evs_deliver_callback *res_evs_deliver_callback;
 	evs_callbacks_t callbacks;
-	struct res_overlay dispatch_data;
-	int ignore_dispatch = 0;
+	struct evs_res_overlay dispatch_data;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -230,7 +229,7 @@
 	 * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and
 	 * wait indefinately for SA_DISPATCH_BLOCKING
 	 */
-	if (dispatch_types == EVS_DISPATCH_ALL) {
+	if (dispatch_types == CS_DISPATCH_ALL) {
 		timeout = 0;
 	}
 
@@ -240,7 +239,7 @@
 		ufds.revents = 0;
 
 		error = saPollRetry (&ufds, 1, timeout);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
@@ -250,7 +249,7 @@
 		 * Regather poll data in case ufds has changed since taking lock
 		 */
 		error = saPollRetry (&ufds, 1, 0);
-		if (error != SA_AIS_OK) {
+		if (error != CS_OK) {
 			goto error_nounlock;
 		}
 
@@ -258,13 +257,13 @@
 		 * Handle has been finalized in another thread
 		 */
 		if (evs_inst->finalize == 1) {
-			error = EVS_OK;
+			error = CS_OK;
 			pthread_mutex_unlock (&evs_inst->dispatch_mutex);
 			goto error_unlock;
 		}
 
 		dispatch_avail = ufds.revents & POLLIN;
-		if (dispatch_avail == 0 && dispatch_types == EVS_DISPATCH_ALL) {
+		if (dispatch_avail == 0 && dispatch_types == CS_DISPATCH_ALL) {
 			pthread_mutex_unlock (&evs_inst->dispatch_mutex);
 			break; /* exit do while cont is 1 loop */
 		} else 
@@ -279,14 +278,14 @@
 			 */
 			error = saRecvRetry (evs_inst->dispatch_fd, &dispatch_data.header,
 				sizeof (mar_res_header_t));
-			if (error != SA_AIS_OK) {
+			if (error != CS_OK) {
 				goto error_unlock;
 			}
 			if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
 				error = saRecvRetry (evs_inst->dispatch_fd, &dispatch_data.data,
 					dispatch_data.header.size - sizeof (mar_res_header_t));
 
-				if (error != SA_AIS_OK) {
+				if (error != CS_OK) {
 					goto error_unlock;
 				}
 			}
@@ -327,7 +326,7 @@
 			break;
 
 		default:
-			error = SA_AIS_ERR_LIBRARY;
+			error = CS_ERR_LIBRARY;
 			goto error_nounlock;
 			break;
 		}
@@ -336,42 +335,35 @@
 		 * Determine if more messages should be processed
 		 * */
 		switch (dispatch_types) {
-		case EVS_DISPATCH_ONE:
-			if (ignore_dispatch) {
-				ignore_dispatch = 0;
-			} else {
-				cont = 0;
-			}
+		case CS_DISPATCH_ONE:
+			cont = 0;
 			break;
-		case EVS_DISPATCH_ALL:
-			if (ignore_dispatch) {
-				ignore_dispatch = 0;
-			}
+		case CS_DISPATCH_ALL:
 			break;
-		case EVS_DISPATCH_BLOCKING:
+		case CS_DISPATCH_BLOCKING:
 			break;
 		}
 	} while (cont);
 
 error_unlock:
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 error_nounlock:
 	return (error);
 }
 
-evs_error_t evs_join (
+cs_error_t evs_join (
     evs_handle_t handle,
     struct evs_group *groups,
 	int group_entries)
 {
-	evs_error_t error;
+	cs_error_t error;
 	struct evs_inst *evs_inst;
 	struct iovec iov[2];
 	struct req_lib_evs_join req_lib_evs_join;
 	struct res_lib_evs_join res_lib_evs_join;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -392,31 +384,31 @@
 
 	pthread_mutex_unlock (&evs_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_evs_join.header.error;
 
 error_exit:
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 
 	return (error);
 }
 
-evs_error_t evs_leave (
+cs_error_t evs_leave (
     evs_handle_t handle,
     struct evs_group *groups,
 	int group_entries)
 {
-	evs_error_t error;
+	cs_error_t error;
 	struct evs_inst *evs_inst;
 	struct iovec iov[2];
 	struct req_lib_evs_leave req_lib_evs_leave;
 	struct res_lib_evs_leave res_lib_evs_leave;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -437,26 +429,26 @@
 
 	pthread_mutex_unlock (&evs_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_evs_leave.header.error;
 
 error_exit:
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 
 	return (error);
 }
 
-evs_error_t evs_mcast_joined (
+cs_error_t evs_mcast_joined (
 	evs_handle_t handle,
 	evs_guarantee_t guarantee,
 	struct iovec *iovec,
 	int iov_len)
 {
 	int i;
-	evs_error_t error;
+	cs_error_t error;
 	struct evs_inst *evs_inst;
 	struct iovec iov[64];
 	struct req_lib_evs_mcast_joined req_lib_evs_mcast_joined;
@@ -464,7 +456,7 @@
 	int msg_len = 0;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -490,19 +482,19 @@
 
 	pthread_mutex_unlock (&evs_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_evs_mcast_joined.header.error;
 
 error_exit:
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 
 	return (error);
 }
 
-evs_error_t evs_mcast_groups (
+cs_error_t evs_mcast_groups (
 	evs_handle_t handle,
 	evs_guarantee_t guarantee,
 	struct evs_group *groups,
@@ -511,7 +503,7 @@
 	int iov_len)
 {
 	int i;
-	evs_error_t error;
+	cs_error_t error;
 	struct evs_inst *evs_inst;
 	struct iovec iov[64];
 	struct req_lib_evs_mcast_groups req_lib_evs_mcast_groups;
@@ -519,7 +511,7 @@
 	int msg_len = 0;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 	for (i = 0; i < iov_len; i++) {
@@ -544,32 +536,32 @@
 		&res_lib_evs_mcast_groups, sizeof (struct res_lib_evs_mcast_groups));
 
 	pthread_mutex_unlock (&evs_inst->response_mutex);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	error = res_lib_evs_mcast_groups.header.error;
 
 error_exit:
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 
 	return (error);
 }
 
-evs_error_t evs_membership_get (
+cs_error_t evs_membership_get (
 	evs_handle_t handle,
 	unsigned int *local_nodeid,
 	unsigned int *member_list,
 	unsigned int *member_list_entries)
 {
-	evs_error_t error;
+	cs_error_t error;
 	struct evs_inst *evs_inst;
 	struct iovec iov;
 	struct req_lib_evs_membership_get req_lib_evs_membership_get;
 	struct res_lib_evs_membership_get res_lib_evs_membership_get;
 
 	error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		return (error);
 	}
 
@@ -586,7 +578,7 @@
 
 	pthread_mutex_unlock (&evs_inst->response_mutex);
 
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -606,7 +598,7 @@
 	}
 
 error_exit:
-	saHandleInstancePut (&evs_handle_t_db, handle);
+	(void)saHandleInstancePut (&evs_handle_t_db, handle);
 
 	return (error);
 }
diff -Naurd corosync-0.92/lib/libpload.versions corosync-trunk/lib/libpload.versions
--- corosync-0.92/lib/libpload.versions	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/lib/libpload.versions	2008-10-30 23:41:34.000000000 +0100
@@ -0,0 +1,21 @@
+# Version and symbol export for libSaClm.so
+
+COROSYNC_PLOAD_1.0 {
+	global:
+		pload_start;
+
+	local:
+		saHandleCreate;
+		saHandleDestroy;
+		saHandleInstanceGet;
+		saHandleInstancePut;
+		saRecvRetry;
+		saSelectRetry;
+		saSendMsgReceiveReply;
+		saSendMsgRetry;
+		saSendReceiveReply;
+		saSendRetry;
+		saServiceConnect;
+		saVersionVerify;
+		clustTimeNow;
+};
diff -Naurd corosync-0.92/lib/libquorum.versions corosync-trunk/lib/libquorum.versions
--- corosync-0.92/lib/libquorum.versions	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/lib/libquorum.versions	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,50 @@
+# Version and symbol export for libquorum.so
+
+OPENAIS_QUORUM_1.0 {
+	global:	   
+		quorum_initialize;
+		quorum_finalize;
+		quorum_getquorate;
+		quorum_initialize;
+		quorum_finalize;
+		quorum_dispatch;
+
+	local:
+		saHandleCreate;
+		saHandleDestroy;
+		saHandleInstanceGet;
+		saHandleInstancePut;
+		saRecvRetry;
+		saSelectRetry;
+		saSendMsgReceiveReply;
+		saSendMsgRetry;
+		saSendReceiveReply;
+		saSendRetry;
+		saServiceConnect;
+		saVersionVerify;
+		clustTimeNow;
+};
+# Version and symbol export for libquorum.so
+
+COROSYNC_QUORUM_1.0 {
+	global:
+		quorum_initialize;
+		quorum_finalize;
+		quorum_getquorate;
+		quorum_dispatch;
+
+	local:
+		saHandleCreate;
+		saHandleDestroy;
+		saHandleInstanceGet;
+		saHandleInstancePut;
+		saRecvRetry;
+		saSelectRetry;
+		saSendMsgReceiveReply;
+		saSendMsgRetry;
+		saSendReceiveReply;
+		saSendRetry;
+		saServiceConnect;
+		saVersionVerify;
+		clustTimeNow;
+};
diff -Naurd corosync-0.92/lib/libvotequorum.versions corosync-trunk/lib/libvotequorum.versions
--- corosync-0.92/lib/libvotequorum.versions	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/lib/libvotequorum.versions	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,71 @@
+# Version and symbol export for libvotequorum.so
+
+OPENAIS_VOTEQUORUM_1.0 {
+	global:	   
+		votequorum_initialize;
+		votequorum_finalize;
+		votequorum_getinfo;
+		votequorum_setexpected;
+		votequorum_setvotes;
+		votequorum_qdisk_register;
+		votequorum_qdisk_unregister;
+		votequorum_qdisk_poll;
+		votequorum_qdisk_getinfo;
+		votequorum_setstate;
+		votequorum_leaving;
+		votequorum_trackstart;
+		votequorum_trackstop;
+		votequorum_context_get;
+		votequorum_context_set;
+
+	local:
+		saHandleCreate;
+		saHandleDestroy;
+		saHandleInstanceGet;
+		saHandleInstancePut;
+		saRecvRetry;
+		saSelectRetry;
+		saSendMsgReceiveReply;
+		saSendMsgRetry;
+		saSendReceiveReply;
+		saSendRetry;
+		saServiceConnect;
+		saVersionVerify;
+		clustTimeNow;
+};
+# Version and symbol export for libvotequorum.so
+
+COROSYNC_VOTEQUORUM_1.0 {
+	global:
+		votequorum_initialize;
+		votequorum_finalize;
+		votequorum_getinfo;
+		votequorum_setexpected;
+		votequorum_setvotes;
+		votequorum_qdisk_register;
+		votequorum_qdisk_unregister;
+		votequorum_qdisk_poll;
+		votequorum_qdisk_getinfo;
+		votequorum_setdirty;
+		votequorum_killnode;
+		votequorum_leaving;
+		votequorum_trackstart;
+		votequorum_trackstop;
+		votequorum_context_get;
+		votequorum_context_set;
+
+	local:
+		saHandleCreate;
+		saHandleDestroy;
+		saHandleInstanceGet;
+		saHandleInstancePut;
+		saRecvRetry;
+		saSelectRetry;
+		saSendMsgReceiveReply;
+		saSendMsgRetry;
+		saSendReceiveReply;
+		saSendRetry;
+		saServiceConnect;
+		saVersionVerify;
+		clustTimeNow;
+};
diff -Naurd corosync-0.92/lib/Makefile corosync-trunk/lib/Makefile
--- corosync-0.92/lib/Makefile	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/lib/Makefile	2009-01-26 11:46:08.000000000 +0100
@@ -41,7 +41,10 @@
 	libconfdb.a libconfdb.so.2.0.0 \
 	libevs.a libevs.so.2.0.0 \
 	libcfg.a libcfg.so.2.0.0 \
-	libcoroutil.a libcoroutil.so.2.0.0
+	libquorum.a libquorum.so.2.0.0 \
+	libpload.a libpload.so.2.0.0 \
+	libcoroutil.a libcoroutil.so.2.0.0 \
+	libvotequorum.a libvotequorum.so.2.0.0
 
 libcoroutil.a: util.o
 	$(AR) -rc libcoroutil.a util.o
@@ -58,14 +61,20 @@
 libcpg.so.2.0.0: util.o cpg.o
 	$(CC) $(DARWIN_OPTS) util.o cpg.o -o $@
 
+libquorum.so.2.0.0: util.o quorum.o
+	$(CC) $(DARWIN_OPTS) util.o quorum.o -o $@
+
+libvotequorum.so.2.0.0: util.o votequorum.o
+	$(CC) $(DARWIN_OPTS) util.o votequorum.o -o $@
+
 libconfdb.so.2.0.0: util.o confdb.o sa-confdb.o 
 	$(CC) $(LDFLAGS) $(DARWIN_OPTS) util.o confdb.o sa-confdb.o ../lcr/lcr_ifact.o -o $@
 
 libcfg.so.2.0.0: util.o cfg.o
 	$(CC) $(DARWIN_OPTS) util.o cfg.o -o $@
 
-libcpg.so.2.0.0: util.o cpg.o
-	$(CC) $(DARWIN_OPTS) util.o cpg.o -o $@
+libpload.so.2.0.0: util.o pload.o
+	$(CC) $(DARWIN_OPTS) util.o pload.o -o $@
 
 else
 
@@ -78,12 +87,21 @@
 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 $@
 
+libquorum.so.2.0.0: util.o quorum.o
+	$(CC) -shared -Wl,-soname,libquorum.so.2,-version-script=$(srcdir)$(subdir)libquorum.versions util.o quorum.o -o $@
+
+libvotequorum.so.2.0.0: util.o votequorum.o
+	$(CC) -shared -Wl,-soname,libvotequorum.so.2,-version-script=$(srcdir)$(subdir)libvotequorum.versions util.o votequorum.o -o $@
+
 libconfdb.so.2.0.0: util.o confdb.o sa-confdb.o 
 	$(CC) $(LDFLAGS) -shared -Wl,-soname,libconfdb.so.2,-version-script=$(srcdir)$(subdir)libconfdb.versions util.o confdb.o sa-confdb.o ../lcr/lcr_ifact.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 $@
 
+libpload.so.2.0.0: util.o pload.o
+	$(CC) -shared -Wl,-soname,libpload.so.2,-version-script=$(srcdir)$(subdir)libpload.versions util.o cfg.o -o $@
+
 endif
 
 libevs.a: util.o evs.o
@@ -92,17 +110,27 @@
 libcpg.a: util.o cpg.o
 	$(AR) -rc libcpg.a util.o cpg.o
 
+libquorum.a: util.o quorum.o
+	$(AR) -rc libquorum.a util.o quorum.o
+
+libvotequorum.a: util.o votequorum.o
+	$(AR) -rc libvotequorum.a util.o votequorum.o
+
 libconfdb.a: util.o confdb.o sa-confdb.o
 	$(AR) -rc libconfdb.a util.o confdb.o sa-confdb.o ../lcr/lcr_ifact.o
 
 libcfg.a: util.o cfg.o
 	$(AR) -rc libcfg.a util.o cfg.o
 
+libpload.a: util.o pload.o
+	$(AR) -rc libpload.a util.o pload.o
+
 clean:
-	rm -f *.o libcfg.so* libcoroutil.so* libcoroutil.a \
-		libevs.so* libevs.a libcpg.so* libcpg.a libcfg.a libconfdb.so* \
-		libconfdb.a libconfdb.a \ *.da *.bb *.bbg
+	rm -f *.o *.a *.so* *.da *.bb *.bbg
  
+lint:
+	-splint $(LINT_FLAGS) $(CFLAGS) *.c
+
 # -fPIC rules required for all libraries
 %.o: %.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c -o $@ $<
diff -Naurd corosync-0.92/lib/pload.c corosync-trunk/lib/pload.c
--- corosync-0.92/lib/pload.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/lib/pload.c	2008-11-11 18:25:22.000000000 +0100
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#include <corosync/swab.h>
+#include <corosync/totem/totem.h>
+#include <corosync/corotypes.h>
+#include <corosync/ipc_pload.h>
+#include <corosync/pload.h>
+#include <corosync/ais_util.h>
+
+static void pload_instance_destructor (void *instance);
+
+struct pload_inst {
+	int dispatch_fd;
+	int response_fd;
+	pthread_mutex_t response_mutex;
+	pthread_mutex_t dispatch_mutex;
+	unsigned int finalize;
+};
+
+static struct saHandleDatabase pload_handle_t_db = {
+	.handleCount			= 0,
+	.handles			= 0,
+	.mutex				= PTHREAD_MUTEX_INITIALIZER,
+	.handleInstanceDestructor	= pload_instance_destructor
+};
+
+/*
+ * Clean up function for an evt instance (saEvtInitialize) handle
+ */
+static void pload_instance_destructor (void *instance)
+{
+	struct pload_inst *pload_inst = instance;
+
+	pthread_mutex_destroy (&pload_inst->response_mutex);
+	pthread_mutex_destroy (&pload_inst->dispatch_mutex);
+}
+
+
+/**
+ * @defgroup pload_corosync The extended virtual synchrony passthrough API
+ * @ingroup corosync
+ *
+ * @{
+ */
+/**
+ * test
+ * @param handle The handle of pload initialize
+ * @param callbacks The callbacks for pload_initialize
+ * @returns PLOAD_OK
+ */
+unsigned int pload_initialize (
+	pload_handle_t *handle,
+	pload_callbacks_t *callbacks)
+{
+	cs_error_t error;
+	struct pload_inst *pload_inst;
+
+	error = saHandleCreate (&pload_handle_t_db, sizeof (struct pload_inst), handle);
+	if (error != CS_OK) {
+		goto error_no_destroy;
+	}
+
+	error = saHandleInstanceGet (&pload_handle_t_db, *handle, (void *)&pload_inst);
+	if (error != CS_OK) {
+		goto error_destroy;
+	}
+
+	error = saServiceConnect (&pload_inst->response_fd,
+		&pload_inst->dispatch_fd,
+		PLOAD_SERVICE);
+	if (error != CS_OK) {
+		goto error_put_destroy;
+	}
+
+	pthread_mutex_init (&pload_inst->response_mutex, NULL);
+
+	pthread_mutex_init (&pload_inst->dispatch_mutex, NULL);
+
+	(void)saHandleInstancePut (&pload_handle_t_db, *handle);
+
+	return (CS_OK);
+
+error_put_destroy:
+	(void)saHandleInstancePut (&pload_handle_t_db, *handle);
+error_destroy:
+	(void)saHandleDestroy (&pload_handle_t_db, *handle);
+error_no_destroy:
+	return (error);
+}
+
+unsigned int pload_finalize (
+	pload_handle_t handle)
+{
+	struct pload_inst *pload_inst;
+	cs_error_t error;
+
+	error = saHandleInstanceGet (&pload_handle_t_db, handle, (void *)&pload_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+//	  TODO is the locking right here
+	pthread_mutex_lock (&pload_inst->response_mutex);
+
+	/*
+	 * Another thread has already started finalizing
+	 */
+	if (pload_inst->finalize) {
+		pthread_mutex_unlock (&pload_inst->response_mutex);
+		(void)saHandleInstancePut (&pload_handle_t_db, handle);
+		return (PLOAD_ERR_BAD_HANDLE);
+	}
+
+	pload_inst->finalize = 1;
+
+	pthread_mutex_unlock (&pload_inst->response_mutex);
+
+	(void)saHandleDestroy (&pload_handle_t_db, handle);
+    /*
+     * Disconnect from the server
+     */
+    if (pload_inst->response_fd != -1) {
+        shutdown(pload_inst->response_fd, 0);
+        close(pload_inst->response_fd);
+    }
+    if (pload_inst->dispatch_fd != -1) {
+        shutdown(pload_inst->dispatch_fd, 0);
+        close(pload_inst->dispatch_fd);
+    }
+	(void)saHandleInstancePut (&pload_handle_t_db, handle);
+
+
+	return (PLOAD_OK);
+}
+
+unsigned int pload_fd_get (
+	pload_handle_t handle,
+	int *fd)
+{
+	cs_error_t error;
+	struct pload_inst *pload_inst;
+
+	error = saHandleInstanceGet (&pload_handle_t_db, handle, (void *)&pload_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	*fd = pload_inst->dispatch_fd; 
+
+	(void)saHandleInstancePut (&pload_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+unsigned int pload_start (
+	pload_handle_t handle,
+	unsigned int code,
+	unsigned int msg_count,
+	unsigned int msg_size)
+{
+	unsigned int error;
+	struct pload_inst *pload_inst;
+	struct iovec iov;
+	struct req_lib_pload_start req_lib_pload_start;
+	struct res_lib_pload_start res_lib_pload_start;
+
+	error = saHandleInstanceGet (&pload_handle_t_db, handle, (void *)&pload_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	req_lib_pload_start.header.size = sizeof (struct req_lib_pload_start);
+	req_lib_pload_start.header.id = MESSAGE_REQ_PLOAD_START;
+	req_lib_pload_start.msg_code = code;
+	req_lib_pload_start.msg_count = msg_count;
+	req_lib_pload_start.msg_size = msg_size;
+
+	iov.iov_base = (char *)&req_lib_pload_start;
+	iov.iov_len = sizeof (struct req_lib_pload_start);
+	
+	pthread_mutex_lock (&pload_inst->response_mutex);
+
+	error = saSendMsgReceiveReply (pload_inst->response_fd, &iov, 1,
+		&res_lib_pload_start, sizeof (struct res_lib_pload_start));
+
+	pthread_mutex_unlock (&pload_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_pload_start.header.error;
+
+error_exit:
+	(void)saHandleInstancePut (&pload_handle_t_db, handle);
+
+	return (error);
+}
+
+/** @} */
diff -Naurd corosync-0.92/lib/quorum.c corosync-trunk/lib/quorum.c
--- corosync-0.92/lib/quorum.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/lib/quorum.c	2008-11-11 18:26:58.000000000 +0100
@@ -0,0 +1,493 @@
+/*
+ * 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 a quorum API using the corosync executive
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#include <corosync/corotypes.h>
+#include <corosync/mar_gen.h>
+#include <corosync/ipc_gen.h>
+#include <corosync/ais_util.h>
+#include "corosync/quorum.h"
+#include "corosync/ipc_quorum.h"
+
+struct quorum_inst {
+	int response_fd;
+	int dispatch_fd;
+	int finalize;
+	void *context;
+	quorum_callbacks_t callbacks;
+	pthread_mutex_t response_mutex;
+	pthread_mutex_t dispatch_mutex;
+};
+
+static void quorum_instance_destructor (void *instance);
+
+static struct saHandleDatabase quorum_handle_t_db = {
+	.handleCount		        = 0,
+	.handles			= 0,
+	.mutex				= PTHREAD_MUTEX_INITIALIZER,
+	.handleInstanceDestructor	= quorum_instance_destructor
+};
+
+/*
+ * Clean up function for a quorum instance (quorum_initialize) handle
+ */
+static void quorum_instance_destructor (void *instance)
+{
+	struct quorum_inst *quorum_inst = instance;
+
+	pthread_mutex_destroy (&quorum_inst->response_mutex);
+}
+
+cs_error_t quorum_initialize (
+	quorum_handle_t *handle,
+	quorum_callbacks_t *callbacks)
+{
+	cs_error_t error;
+	struct quorum_inst *quorum_inst;
+
+	error = saHandleCreate (&quorum_handle_t_db, sizeof (struct quorum_inst), handle);
+	if (error != CS_OK) {
+		goto error_no_destroy;
+	}
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, *handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		goto error_destroy;
+	}
+
+	error = saServiceConnect (&quorum_inst->dispatch_fd,
+				  &quorum_inst->response_fd,
+				  QUORUM_SERVICE);
+	if (error != CS_OK) {
+		goto error_put_destroy;
+	}
+
+	pthread_mutex_init (&quorum_inst->response_mutex, NULL);
+	pthread_mutex_init (&quorum_inst->dispatch_mutex, NULL);
+	if (callbacks)
+		memcpy(&quorum_inst->callbacks, callbacks, sizeof (callbacks));
+	else
+		memset(&quorum_inst->callbacks, 0, sizeof (callbacks));
+
+	(void)saHandleInstancePut (&quorum_handle_t_db, *handle);
+
+	return (CS_OK);
+
+error_put_destroy:
+	(void)saHandleInstancePut (&quorum_handle_t_db, *handle);
+error_destroy:
+	(void)saHandleDestroy (&quorum_handle_t_db, *handle);
+error_no_destroy:
+	return (error);
+}
+
+cs_error_t quorum_finalize (
+	quorum_handle_t handle)
+{
+	struct quorum_inst *quorum_inst;
+	cs_error_t error;
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&quorum_inst->response_mutex);
+
+	/*
+	 * Another thread has already started finalizing
+	 */
+	if (quorum_inst->finalize) {
+		pthread_mutex_unlock (&quorum_inst->response_mutex);
+		(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+		return (CS_ERR_BAD_HANDLE);
+	}
+
+	quorum_inst->finalize = 1;
+
+	pthread_mutex_unlock (&quorum_inst->response_mutex);
+
+	(void)saHandleDestroy (&quorum_handle_t_db, handle);
+
+	/*
+	 * Disconnect from the server
+	 */
+	if (quorum_inst->response_fd != -1) {
+		shutdown(quorum_inst->response_fd, 0);
+		close(quorum_inst->response_fd);
+	}
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+cs_error_t quorum_getquorate (
+	quorum_handle_t handle,
+	int *quorate)
+{
+	cs_error_t error;
+	struct quorum_inst *quorum_inst;
+	struct iovec iov[2];
+	mar_req_header_t req;
+	struct res_lib_quorum_getquorate res_lib_quorum_getquorate;
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&quorum_inst->response_mutex);
+
+	req.size = sizeof (req);
+	req.id = MESSAGE_REQ_QUORUM_GETQUORATE;
+
+	iov[0].iov_base = (char *)&req;
+	iov[0].iov_len = sizeof (req);
+
+	error = saSendMsgReceiveReply (quorum_inst->response_fd, iov, 1,
+		&res_lib_quorum_getquorate, sizeof (struct res_lib_quorum_getquorate));
+
+	pthread_mutex_unlock (&quorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_quorum_getquorate.header.error;
+
+	*quorate = res_lib_quorum_getquorate.quorate;
+
+error_exit:
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t quorum_fd_get (
+	quorum_handle_t handle,
+	int *fd)
+{
+	cs_error_t error;
+	struct quorum_inst *quorum_inst;
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	*fd = quorum_inst->dispatch_fd;
+
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+
+cs_error_t quorum_context_get (
+	quorum_handle_t handle,
+	void **context)
+{
+	cs_error_t error;
+	struct quorum_inst *quorum_inst;
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	*context = quorum_inst->context;
+
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+cs_error_t quorum_context_set (
+	quorum_handle_t handle,
+	void *context)
+{
+	cs_error_t error;
+	struct quorum_inst *quorum_inst;
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	quorum_inst->context = context;
+
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+
+cs_error_t quorum_trackstart (
+	quorum_handle_t handle,
+	unsigned int flags )
+{
+	cs_error_t error;
+	struct quorum_inst *quorum_inst;
+	struct iovec iov[2];
+	struct req_lib_quorum_trackstart req_lib_quorum_trackstart;
+	mar_res_header_t res;
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&quorum_inst->response_mutex);
+
+	req_lib_quorum_trackstart.header.size = sizeof (struct req_lib_quorum_trackstart);
+	req_lib_quorum_trackstart.header.id = MESSAGE_REQ_QUORUM_TRACKSTART;
+	req_lib_quorum_trackstart.track_flags = flags;
+
+	iov[0].iov_base = (char *)&req_lib_quorum_trackstart;
+	iov[0].iov_len = sizeof (struct req_lib_quorum_trackstart);
+
+	error = saSendMsgReceiveReply (quorum_inst->response_fd, iov, 1,
+		&res, sizeof (res));
+
+	pthread_mutex_unlock (&quorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res.error;
+
+error_exit:
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t quorum_trackstop (
+	quorum_handle_t handle)
+{
+	cs_error_t error;
+	struct quorum_inst *quorum_inst;
+	struct iovec iov[2];
+	mar_req_header_t req;
+	mar_res_header_t res;
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle, (void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&quorum_inst->response_mutex);
+
+	req.size = sizeof (req);
+	req.id = MESSAGE_REQ_QUORUM_TRACKSTOP;
+
+	iov[0].iov_base = (char *)&req;
+	iov[0].iov_len = sizeof (req);
+
+	error = saSendMsgReceiveReply (quorum_inst->response_fd, iov, 1,
+		&res, sizeof (res));
+
+	pthread_mutex_unlock (&quorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res.error;
+
+error_exit:
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+
+	return (error);
+}
+
+struct quorum_res_overlay {
+	mar_res_header_t header __attribute__((aligned(8)));
+	char data[512000];
+};
+
+cs_error_t quorum_dispatch (
+	quorum_handle_t handle,
+	cs_dispatch_flags_t dispatch_types)
+{
+	struct pollfd ufds;
+	int timeout = -1;
+	cs_error_t error;
+	int cont = 1; /* always continue do loop except when set to 0 */
+	int dispatch_avail;
+	struct quorum_inst *quorum_inst;
+	quorum_callbacks_t callbacks;
+	struct quorum_res_overlay dispatch_data;
+	struct res_lib_quorum_notification *res_lib_quorum_notification;
+
+	if (dispatch_types != CS_DISPATCH_ONE &&
+		dispatch_types != CS_DISPATCH_ALL &&
+		dispatch_types != CS_DISPATCH_BLOCKING) {
+
+		return (CS_ERR_INVALID_PARAM);
+	}
+
+	error = saHandleInstanceGet (&quorum_handle_t_db, handle,
+		(void *)&quorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	/*
+	 * Timeout instantly for CS_DISPATCH_ONE or SA_DISPATCH_ALL and
+	 * wait indefinately for CS_DISPATCH_BLOCKING
+	 */
+	if (dispatch_types == CS_DISPATCH_ALL) {
+		timeout = 0;
+	}
+
+	do {
+		ufds.fd = quorum_inst->dispatch_fd;
+		ufds.events = POLLIN;
+		ufds.revents = 0;
+
+		pthread_mutex_lock (&quorum_inst->dispatch_mutex);
+
+		error = saPollRetry (&ufds, 1, timeout);
+		if (error != CS_OK) {
+			goto error_unlock;
+		}
+
+		/*
+		 * Handle has been finalized in another thread
+		 */
+		if (quorum_inst->finalize == 1) {
+			error = CS_OK;
+			goto error_unlock;
+		}
+
+		if ((ufds.revents & (POLLERR|POLLHUP|POLLNVAL)) != 0) {
+			error = CS_ERR_BAD_HANDLE;
+			goto error_unlock;
+		}
+
+		dispatch_avail = ufds.revents & POLLIN;
+		if (dispatch_avail == 0 && dispatch_types == CS_DISPATCH_ALL) {
+			pthread_mutex_unlock (&quorum_inst->dispatch_mutex);
+			break; /* exit do while cont is 1 loop */
+		} else
+		if (dispatch_avail == 0) {
+			pthread_mutex_unlock (&quorum_inst->dispatch_mutex);
+			continue; /* next poll */
+		}
+
+		if (ufds.revents & POLLIN) {
+			error = saRecvRetry (quorum_inst->dispatch_fd, &dispatch_data.header,
+				sizeof (mar_res_header_t));
+			if (error != CS_OK) {
+				goto error_unlock;
+			}
+			if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
+				error = saRecvRetry (quorum_inst->dispatch_fd, &dispatch_data.data,
+					dispatch_data.header.size - sizeof (mar_res_header_t));
+				if (error != CS_OK) {
+					goto error_unlock;
+				}
+			}
+		} else {
+			pthread_mutex_unlock (&quorum_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 quorum_finalize has been called in another thread.
+		 */
+		memcpy (&callbacks, &quorum_inst->callbacks, sizeof (quorum_callbacks_t));
+		pthread_mutex_unlock (&quorum_inst->dispatch_mutex);
+
+		/*
+		 * Dispatch incoming message
+		 */
+		switch (dispatch_data.header.id) {
+
+		case MESSAGE_RES_QUORUM_NOTIFICATION:
+			if (callbacks.quorum_notify_fn == NULL) {
+				continue;
+			}
+			res_lib_quorum_notification = (struct res_lib_quorum_notification *)&dispatch_data;
+
+			callbacks.quorum_notify_fn ( handle,
+						     res_lib_quorum_notification->quorate,
+						     res_lib_quorum_notification->ring_seq,
+						     res_lib_quorum_notification->view_list_entries,
+						     res_lib_quorum_notification->view_list);
+			break;
+
+		default:
+			error = CS_ERR_LIBRARY;
+			goto error_put;
+			break;
+		}
+
+		/*
+		 * Determine if more messages should be processed
+		 * */
+		switch (dispatch_types) {
+		case CS_DISPATCH_ONE:
+			cont = 0;
+			break;
+		case CS_DISPATCH_ALL:
+			break;
+		case CS_DISPATCH_BLOCKING:
+			break;
+		}
+	} while (cont);
+
+	goto error_put;
+
+error_unlock:
+	pthread_mutex_unlock (&quorum_inst->dispatch_mutex);
+
+error_put:
+	(void)saHandleInstancePut (&quorum_handle_t_db, handle);
+	return (error);
+}
diff -Naurd corosync-0.92/lib/sa-confdb.c corosync-trunk/lib/sa-confdb.c
--- corosync-0.92/lib/sa-confdb.c	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/lib/sa-confdb.c	2008-11-12 18:39:37.000000000 +0100
@@ -43,7 +43,7 @@
 #include <sys/types.h>
 #include <errno.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/ais_util.h>
 #include <corosync/engine/objdb.h>
 #include <corosync/engine/config.h>
@@ -80,7 +80,7 @@
 	objdb = (struct objdb_iface_ver0 *)objdb_p;
 
 	objdb->objdb_init ();
-	return SA_AIS_OK;
+	return CS_OK;
 }
 
 static int load_config()
@@ -130,7 +130,7 @@
 	if (config_iface)
 		free(config_iface);
 
-	return SA_AIS_OK;
+	return CS_OK;
 }
 
 /* Needed by objdb when it writes back the configuration */
@@ -174,7 +174,7 @@
 	int res;
 
 	res = load_objdb();
-	if (res != SA_AIS_OK)
+	if (res != CS_OK)
 		return res;
 
 	res = load_config();
@@ -295,7 +295,6 @@
 }
 
 int confdb_sa_write (
-	unsigned int parent_object_handle,
 	char *error_text)
 {
 	char *errtext;
@@ -309,7 +308,6 @@
 }
 
 int confdb_sa_reload (
-	unsigned int parent_object_handle,
 	int flush,
 	char *error_text)
 {
diff -Naurd corosync-0.92/lib/sa-confdb.h corosync-trunk/lib/sa-confdb.h
--- corosync-0.92/lib/sa-confdb.h	2008-08-26 09:34:22.000000000 +0200
+++ corosync-trunk/lib/sa-confdb.h	2008-10-06 09:46:04.000000000 +0200
@@ -42,6 +42,8 @@
 extern int confdb_sa_key_replace(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);
 extern int confdb_sa_object_find(unsigned int parent_object_handle, unsigned int *find_handle, unsigned int *object_handle, void *object_name, int *object_name_len, int copy_name);
 extern int confdb_sa_key_iter(unsigned int parent_object_handle, unsigned int start_pos, void *key_name, int *key_name_len, void *value, int *value_len);
+extern int confdb_sa_key_increment(unsigned int parent_object_handle, void *key_name, int key_name_len, unsigned int *value);
+extern int confdb_sa_key_decrement(unsigned int parent_object_handle, void *key_name, int key_name_len, unsigned int *value);
 extern int confdb_sa_find_destroy(unsigned int find_handle);
 extern int confdb_sa_write(char *error_text);
 extern int confdb_sa_reload(int flush, char *error_text);
diff -Naurd corosync-0.92/lib/util.c corosync-trunk/lib/util.c
--- corosync-0.92/lib/util.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/lib/util.c	2008-11-11 19:13:47.000000000 +0100
@@ -53,7 +53,7 @@
 #include <netinet/in.h>
 #include <assert.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/ipc_gen.h>
 #include <corosync/ais_util.h>
 
@@ -96,7 +96,7 @@
 }
 #endif 
 
-SaAisErrorT
+cs_error_t
 saServiceConnect (
 	int *responseOut,
 	int *callbackOut,
@@ -110,7 +110,7 @@
 	mar_res_lib_response_init_t res_lib_response_init;
 	mar_req_lib_dispatch_init_t req_lib_dispatch_init;
 	mar_res_lib_dispatch_init_t res_lib_dispatch_init;
-	SaAisErrorT error;
+	cs_error_t error;
 	gid_t egid;
 
 	/*
@@ -131,7 +131,7 @@
 #endif
 	responseFD = socket (PF_UNIX, SOCK_STREAM, 0);
 	if (responseFD == -1) {
-		return (SA_AIS_ERR_NO_RESOURCES);
+		return (CS_ERR_NO_RESOURCES);
 	}
 
 	socket_nosigpipe (responseFD);
@@ -139,7 +139,7 @@
 	result = connect (responseFD, (struct sockaddr *)&address, AIS_SUN_LEN(&address));
 	if (result == -1) {
 		close (responseFD);
-		return (SA_AIS_ERR_TRY_AGAIN);
+		return (CS_ERR_TRY_AGAIN);
 	}
 
 	req_lib_response_init.resdis_header.size = sizeof (req_lib_response_init);
@@ -148,19 +148,19 @@
 
 	error = saSendRetry (responseFD, &req_lib_response_init,
 		sizeof (mar_req_lib_response_init_t));
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 	error = saRecvRetry (responseFD, &res_lib_response_init,
 		sizeof (mar_res_lib_response_init_t));
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
 	/*
 	 * Check for security errors
 	 */
-	if (res_lib_response_init.header.error != SA_AIS_OK) {
+	if (res_lib_response_init.header.error != CS_OK) {
 		error = res_lib_response_init.header.error;
 		goto error_exit;
 	}
@@ -171,7 +171,7 @@
 	callbackFD = socket (PF_UNIX, SOCK_STREAM, 0);
 	if (callbackFD == -1) {
 		close (responseFD);
-		return (SA_AIS_ERR_NO_RESOURCES);
+		return (CS_ERR_NO_RESOURCES);
 	}
 
 	socket_nosigpipe (callbackFD);
@@ -180,7 +180,7 @@
 	if (result == -1) {
 		close (callbackFD);
 		close (responseFD);
-		return (SA_AIS_ERR_TRY_AGAIN);
+		return (CS_ERR_TRY_AGAIN);
 	}
 
 	req_lib_dispatch_init.resdis_header.size = sizeof (req_lib_dispatch_init);
@@ -191,25 +191,25 @@
 
 	error = saSendRetry (callbackFD, &req_lib_dispatch_init,
 		sizeof (mar_req_lib_dispatch_init_t));
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit_two;
 	}
 	error = saRecvRetry (callbackFD, &res_lib_dispatch_init,
 		sizeof (mar_res_lib_dispatch_init_t));
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit_two;
 	}
 
 	/*
 	 * Check for security errors
 	 */
-	if (res_lib_dispatch_init.header.error != SA_AIS_OK) {
+	if (res_lib_dispatch_init.header.error != CS_OK) {
 		error = res_lib_dispatch_init.header.error;
 		goto error_exit;
 	}
 
 	*callbackOut = callbackFD;
-	return (SA_AIS_OK);
+	return (CS_OK);
 
 error_exit_two:
 	close (callbackFD);
@@ -218,14 +218,14 @@
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 saRecvRetry (
 	int s,
 	void *msg,
 	size_t len)
 {
-	SaAisErrorT error = SA_AIS_OK;
-	int result;
+	cs_error_t error = CS_OK;
+	ssize_t result;
 	struct msghdr msg_recv;
 	struct iovec iov_recv;
 	char *rbuf = (char *)msg;
@@ -260,12 +260,12 @@
 	 * EOF is detected when recvmsg return 0.
 	 */
 	if (result == 0) {
-		error = SA_AIS_ERR_LIBRARY;
+		error = CS_ERR_LIBRARY;
 		goto error_exit;
 	}
 #endif
 	if (result == -1 || result == 0) {
-		error = SA_AIS_ERR_LIBRARY;
+		error = CS_ERR_LIBRARY;
 		goto error_exit;
 	}
 	processed += result;
@@ -277,14 +277,14 @@
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 saSendRetry (
 	int s,
 	const void *msg,
 	size_t len)
 {
-	SaAisErrorT error = SA_AIS_OK;
-	int result;
+	cs_error_t error = CS_OK;
+	ssize_t result;
 	struct msghdr msg_send;
 	struct iovec iov_send;
 	char *rbuf = (char *)msg;
@@ -315,15 +315,15 @@
 	 */
 	if (result == -1 && processed == 0) {
 		if (errno == EINTR) {
-			error = SA_AIS_ERR_TRY_AGAIN;
+			error = CS_ERR_TRY_AGAIN;
 			goto error_exit;
 		}
 		if (errno == EAGAIN) {
-			error = SA_AIS_ERR_TRY_AGAIN;
+			error = CS_ERR_TRY_AGAIN;
 			goto error_exit;
 		}
 		if (errno == EFAULT) {
-			error = SA_AIS_ERR_INVALID_PARAM;
+			error = CS_ERR_INVALID_PARAM;
 			goto error_exit;
 		}
 	}
@@ -340,7 +340,7 @@
 			goto retry_send;
 		}
 		if (errno == EFAULT) {
-			error = SA_AIS_ERR_LIBRARY;
+			error = CS_ERR_LIBRARY;
 			goto error_exit;
 		}
 	}
@@ -349,7 +349,7 @@
 	 * return ERR_LIBRARY on any other syscall error
 	 */
 	if (result == -1) {
-		error = SA_AIS_ERR_LIBRARY;
+		error = CS_ERR_LIBRARY;
 		goto error_exit;
 	}
 
@@ -362,13 +362,13 @@
 	return (error);
 }
 
-SaAisErrorT saSendMsgRetry (
+cs_error_t saSendMsgRetry (
         int s,
         struct iovec *iov,
         int iov_len)
 {
-	SaAisErrorT error = SA_AIS_OK;
-	int result;
+	cs_error_t error = CS_OK;
+	ssize_t result;
 	int total_size = 0;
 	int i;
 	int csize;
@@ -404,15 +404,15 @@
 	 */
 	if (result == -1 && iovec_saved_position == -1) {
 		if (errno == EINTR) {
-			error = SA_AIS_ERR_TRY_AGAIN;
+			error = CS_ERR_TRY_AGAIN;
 			goto error_exit;
 		}
 		if (errno == EAGAIN) {
-			error = SA_AIS_ERR_TRY_AGAIN;
+			error = CS_ERR_TRY_AGAIN;
 			goto error_exit;
 		}
 		if (errno == EFAULT) {
-			error = SA_AIS_ERR_INVALID_PARAM;
+			error = CS_ERR_INVALID_PARAM;
 			goto error_exit;
 		}
 	}
@@ -428,7 +428,7 @@
 			goto retry_sendmsg;
 		}
 		if (errno == EFAULT) {
-			error = SA_AIS_ERR_LIBRARY;
+			error = CS_ERR_LIBRARY;
 			goto error_exit;
 		}
 	}
@@ -437,7 +437,7 @@
 	 * ERR_LIBRARY for any other syscall error
 	 */
 	if (result == -1) {
-		error = SA_AIS_ERR_LIBRARY;
+		error = CS_ERR_LIBRARY;
 		goto error_exit;
 	}
 
@@ -470,22 +470,22 @@
 	return (error);
 }
 
-SaAisErrorT saSendMsgReceiveReply (
+cs_error_t saSendMsgReceiveReply (
         int s,
         struct iovec *iov,
         int iov_len,
         void *responseMessage,
         int responseLen)
 {
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 
 	error = saSendMsgRetry (s, iov, iov_len);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 	
 	error = saRecvRetry (s, responseMessage, responseLen);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -493,22 +493,22 @@
 	return (error);
 }
 
-SaAisErrorT saSendReceiveReply (
+cs_error_t saSendReceiveReply (
         int s,
         void *requestMessage,
         int requestLen,
         void *responseMessage,
         int responseLen)
 {
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 
 	error = saSendRetry (s, requestMessage, requestLen);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 	
 	error = saRecvRetry (s, responseMessage, responseLen);
-	if (error != SA_AIS_OK) {
+	if (error != CS_OK) {
 		goto error_exit;
 	}
 
@@ -516,13 +516,13 @@
 	return (error);
 }
 
-SaAisErrorT
+cs_error_t
 saPollRetry (
         struct pollfd *ufds,
         unsigned int nfds,
         int timeout) 
 {
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 	int result;
 
 retry_poll:
@@ -531,18 +531,18 @@
 		goto retry_poll;
 	}
 	if (result == -1) {
-		error = SA_AIS_ERR_LIBRARY;
+		error = CS_ERR_LIBRARY;
 	}
 
 	return (error);
 }
 
 
-SaAisErrorT
+cs_error_t
 saHandleCreate (
 	struct saHandleDatabase *handleDatabase,
 	int instanceSize,
-	SaUint64T *handleOut)
+	uint64_t *handleOut)
 {
 	uint32_t handle;
 	uint32_t check;
@@ -566,7 +566,7 @@
 			sizeof (struct saHandle) * handleDatabase->handleCount);
 		if (newHandles == NULL) {
 			pthread_mutex_unlock (&handleDatabase->mutex);
-			return (SA_AIS_ERR_NO_MEMORY);
+			return (CS_ERR_NO_MEMORY);
 		}
 		handleDatabase->handles = newHandles;
 	}
@@ -575,7 +575,7 @@
 	if (instance == 0) {
 		free (newHandles);
 		pthread_mutex_unlock (&handleDatabase->mutex);
-		return (SA_AIS_ERR_NO_MEMORY);
+		return (CS_ERR_NO_MEMORY);
 	}
 
 
@@ -601,20 +601,20 @@
 
 	handleDatabase->handles[handle].check = check;
 
-	*handleOut = (SaUint64T)((uint64_t)check << 32 | handle);
+	*handleOut = (uint64_t)((uint64_t)check << 32 | handle);
 
 	pthread_mutex_unlock (&handleDatabase->mutex);
 
-	return (SA_AIS_OK);
+	return (CS_OK);
 }
 
 
-SaAisErrorT
+cs_error_t
 saHandleDestroy (
 	struct saHandleDatabase *handleDatabase,
-	SaUint64T inHandle)
+	uint64_t inHandle)
 {
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 	uint32_t check = inHandle >> 32;
 	uint32_t handle = inHandle & 0xffffffff;
 
@@ -622,7 +622,7 @@
 
 	if (check != handleDatabase->handles[handle].check) {
 		pthread_mutex_unlock (&handleDatabase->mutex);
-		error = SA_AIS_ERR_BAD_HANDLE;
+		error = CS_ERR_BAD_HANDLE;
 		return (error);
 	}
 
@@ -630,34 +630,34 @@
 
 	pthread_mutex_unlock (&handleDatabase->mutex);
 
-	saHandleInstancePut (handleDatabase, inHandle);
+	(void)saHandleInstancePut (handleDatabase, inHandle);
 
 	return (error);
 }
 
 
-SaAisErrorT
+cs_error_t
 saHandleInstanceGet (
 	struct saHandleDatabase *handleDatabase,
-	SaUint64T inHandle,
+	uint64_t inHandle,
 	void **instance)
 { 
 	uint32_t check = inHandle >> 32;
 	uint32_t handle = inHandle & 0xffffffff;
 
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 	pthread_mutex_lock (&handleDatabase->mutex);
 
-	if (handle >= (SaUint64T)handleDatabase->handleCount) {
-		error = SA_AIS_ERR_BAD_HANDLE;
+	if (handle >= (uint64_t)handleDatabase->handleCount) {
+		error = CS_ERR_BAD_HANDLE;
 		goto error_exit;
 	}
 	if (handleDatabase->handles[handle].state != SA_HANDLE_STATE_ACTIVE) {
-		error = SA_AIS_ERR_BAD_HANDLE;
+		error = CS_ERR_BAD_HANDLE;
 		goto error_exit;
 	}
 	if (check != handleDatabase->handles[handle].check) {
-		error = SA_AIS_ERR_BAD_HANDLE;
+		error = CS_ERR_BAD_HANDLE;
 		goto error_exit;
 	}
 
@@ -673,20 +673,20 @@
 }
 
 
-SaAisErrorT
+cs_error_t
 saHandleInstancePut (
 	struct saHandleDatabase *handleDatabase,
-	SaUint64T inHandle)
+	uint64_t inHandle)
 {
 	void *instance;
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 	uint32_t check = inHandle >> 32;
 	uint32_t handle = inHandle & 0xffffffff;
 
 	pthread_mutex_lock (&handleDatabase->mutex);
 
 	if (check != handleDatabase->handles[handle].check) {
-		error = SA_AIS_ERR_BAD_HANDLE;
+		error = CS_ERR_BAD_HANDLE;
 		goto error_exit;
 	}
 
@@ -707,16 +707,16 @@
 }
 
 
-SaAisErrorT
+cs_error_t
 saVersionVerify (
     struct saVersionDatabase *versionDatabase,
-	SaVersionT *version)
+	cs_version_t *version)
 {
 	int i;
-	SaAisErrorT error = SA_AIS_ERR_VERSION;
+	cs_error_t error = CS_ERR_VERSION;
 
 	if (version == 0) {
-		return (SA_AIS_ERR_INVALID_PARAM);
+		return (CS_ERR_INVALID_PARAM);
 	}
 
 	/*
@@ -742,7 +742,7 @@
 			 * Check if we can support the major version requested.
 			 */
 			if (versionDatabase->versionsSupported[i].majorVersion >= version->majorVersion) {
-				error = SA_AIS_OK;
+				error = CS_OK;
 				break;
 			} 
 
@@ -771,17 +771,17 @@
 /*
  * Get the time of day and convert to nanoseconds
  */
-SaTimeT clustTimeNow(void)
+cs_time_t clustTimeNow(void)
 {
 	struct timeval tv;
-	SaTimeT time_now;
+	cs_time_t time_now;
 
 	if (gettimeofday(&tv, 0)) {
 		return 0ULL;
 	}
 
-	time_now = (SaTimeT)(tv.tv_sec) * 1000000000ULL;
-	time_now += (SaTimeT)(tv.tv_usec) * 1000ULL;
+	time_now = (cs_time_t)(tv.tv_sec) * 1000000000ULL;
+	time_now += (cs_time_t)(tv.tv_usec) * 1000ULL;
 
 	return time_now;
 }
diff -Naurd corosync-0.92/lib/util.h corosync-trunk/lib/util.h
--- corosync-0.92/lib/util.h	2008-05-12 15:48:06.000000000 +0200
+++ corosync-trunk/lib/util.h	2008-11-06 22:49:07.000000000 +0100
@@ -72,72 +72,72 @@
 	SaVersionT *versionsSupported;
 };
 
-SaAisErrorT
+cs_error_t
 saServiceConnect (
         int *responseOut,
         int *callbackOut,
         enum service_types service);
 
-SaAisErrorT
+cs_error_t
 saRecvRetry (
 	int s,
 	void *msg,
 	size_t len);
 
-SaAisErrorT
+cs_error_t
 saSendRetry (
 	int s,
 	const void *msg,
 	size_t len);
 
-SaAisErrorT saSendMsgRetry (
+cs_error_t saSendMsgRetry (
 	int s,
 	struct iovec *iov,
 	int iov_len);
 
-SaAisErrorT saSendMsgReceiveReply (
+cs_error_t saSendMsgReceiveReply (
 	int s,
 	struct iovec *iov,
 	int iov_len,
 	void *responseMessage,
 	int responseLen);
 
-SaAisErrorT saSendReceiveReply (
+cs_error_t saSendReceiveReply (
 	int s,
 	void *requestMessage,
 	int requestLen,
 	void *responseMessage,
 	int responseLen);
 
-SaAisErrorT
+cs_error_t
 saPollRetry (
 	struct pollfd *ufds,
 	unsigned int nfds,
 	int timeout);
 
-SaAisErrorT
+cs_error_t
 saHandleCreate (
 	struct saHandleDatabase *handleDatabase,
 	int instanceSize,
 	SaUint64T *handleOut);
 
-SaAisErrorT
+cs_error_t
 saHandleDestroy (
 	struct saHandleDatabase *handleDatabase,
 	SaUint64T handle);
 
-SaAisErrorT
+cs_error_t
 saHandleInstanceGet (
 	struct saHandleDatabase *handleDatabase,
 	SaUint64T handle,
 	void **instance);
 
-SaAisErrorT
+cs_error_t
 saHandleInstancePut (
 	struct saHandleDatabase *handleDatabase,
 	SaUint64T handle);
 
-SaAisErrorT
+cs_error_t
 saVersionVerify (
 	struct saVersionDatabase *versionDatabase,
 	SaVersionT *version);
diff -Naurd corosync-0.92/lib/votequorum.c corosync-trunk/lib/votequorum.c
--- corosync-0.92/lib/votequorum.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/lib/votequorum.c	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,821 @@
+/*
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Provides a quorum API using the corosync executive
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#include <corosync/mar_gen.h>
+#include <corosync/ipc_gen.h>
+#include <corosync/ais_util.h>
+#include "corosync/votequorum.h"
+#include "corosync/ipc_votequorum.h"
+
+struct votequorum_inst {
+	int response_fd;
+	int dispatch_fd;
+	int finalize;
+	void *context;
+	votequorum_callbacks_t callbacks;
+	pthread_mutex_t response_mutex;
+	pthread_mutex_t dispatch_mutex;
+};
+
+static void votequorum_instance_destructor (void *instance);
+
+static struct saHandleDatabase votequorum_handle_t_db = {
+	.handleCount		        = 0,
+	.handles			= 0,
+	.mutex				= PTHREAD_MUTEX_INITIALIZER,
+	.handleInstanceDestructor	= votequorum_instance_destructor
+};
+
+/*
+ * Clean up function for a quorum instance (votequorum_initialize) handle
+ */
+static void votequorum_instance_destructor (void *instance)
+{
+	struct votequorum_inst *votequorum_inst = instance;
+
+	pthread_mutex_destroy (&votequorum_inst->response_mutex);
+}
+
+cs_error_t votequorum_initialize (
+	votequorum_handle_t *handle,
+	votequorum_callbacks_t *callbacks)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+
+	error = saHandleCreate (&votequorum_handle_t_db, sizeof (struct votequorum_inst), handle);
+	if (error != CS_OK) {
+		goto error_no_destroy;
+	}
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, *handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		goto error_destroy;
+	}
+
+	error = saServiceConnect (&votequorum_inst->dispatch_fd,
+				  &votequorum_inst->response_fd,
+				  VOTEQUORUM_SERVICE);
+	if (error != CS_OK) {
+		goto error_put_destroy;
+	}
+
+	pthread_mutex_init (&votequorum_inst->response_mutex, NULL);
+	pthread_mutex_init (&votequorum_inst->dispatch_mutex, NULL);
+	if (callbacks)
+		memcpy(&votequorum_inst->callbacks, callbacks, sizeof (callbacks));
+	else
+		memset(&votequorum_inst->callbacks, 0, sizeof (callbacks));
+
+	saHandleInstancePut (&votequorum_handle_t_db, *handle);
+
+	return (CS_OK);
+
+error_put_destroy:
+	saHandleInstancePut (&votequorum_handle_t_db, *handle);
+error_destroy:
+	saHandleDestroy (&votequorum_handle_t_db, *handle);
+error_no_destroy:
+	return (error);
+}
+
+cs_error_t votequorum_finalize (
+	votequorum_handle_t handle)
+{
+	struct votequorum_inst *votequorum_inst;
+	cs_error_t error;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	/*
+	 * Another thread has already started finalizing
+	 */
+	if (votequorum_inst->finalize) {
+		pthread_mutex_unlock (&votequorum_inst->response_mutex);
+		saHandleInstancePut (&votequorum_handle_t_db, handle);
+		return (CS_ERR_BAD_HANDLE);
+	}
+
+	votequorum_inst->finalize = 1;
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	saHandleDestroy (&votequorum_handle_t_db, handle);
+
+	/*
+	 * Disconnect from the server
+	 */
+	if (votequorum_inst->response_fd != -1) {
+		shutdown(votequorum_inst->response_fd, 0);
+		close(votequorum_inst->response_fd);
+	}
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+
+cs_error_t votequorum_getinfo (
+	votequorum_handle_t handle,
+	unsigned int nodeid,
+	struct votequorum_info *info)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_getinfo req_lib_votequorum_getinfo;
+	struct res_lib_votequorum_getinfo res_lib_votequorum_getinfo;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_getinfo.header.size = sizeof (struct req_lib_votequorum_getinfo);
+	req_lib_votequorum_getinfo.header.id = MESSAGE_REQ_VOTEQUORUM_GETINFO;
+	req_lib_votequorum_getinfo.nodeid = nodeid;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_getinfo;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_getinfo);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_getinfo, sizeof (struct res_lib_votequorum_getinfo));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_getinfo.header.error;
+
+	info->node_id = res_lib_votequorum_getinfo.nodeid;
+	info->node_votes = res_lib_votequorum_getinfo.votes;
+	info->node_expected_votes = res_lib_votequorum_getinfo.expected_votes;
+	info->highest_expected = res_lib_votequorum_getinfo.highest_expected;
+	info->total_votes = res_lib_votequorum_getinfo.total_votes;
+	info->quorum = res_lib_votequorum_getinfo.quorum;
+	info->flags = res_lib_votequorum_getinfo.flags;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_setexpected (
+	votequorum_handle_t handle,
+	unsigned int expected_votes)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_setexpected req_lib_votequorum_setexpected;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_setexpected.header.size = sizeof (struct req_lib_votequorum_setexpected);
+	req_lib_votequorum_setexpected.header.id = MESSAGE_REQ_VOTEQUORUM_SETEXPECTED;
+	req_lib_votequorum_setexpected.expected_votes = expected_votes;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_setexpected;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_setexpected);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_setvotes (
+	votequorum_handle_t handle,
+	unsigned int nodeid,
+	unsigned int votes)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_setvotes req_lib_votequorum_setvotes;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_setvotes.header.size = sizeof (struct req_lib_votequorum_setvotes);
+	req_lib_votequorum_setvotes.header.id = MESSAGE_REQ_VOTEQUORUM_SETVOTES;
+	req_lib_votequorum_setvotes.nodeid = nodeid;
+	req_lib_votequorum_setvotes.votes = votes;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_setvotes;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_setvotes);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_qdisk_register (
+	votequorum_handle_t handle,
+	char *name,
+	unsigned int votes)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_qdisk_register req_lib_votequorum_qdisk_register;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	if (strlen(name) > VOTEQUORUM_MAX_QDISK_NAME_LEN)
+		return CS_ERR_INVALID_PARAM;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_qdisk_register.header.size = sizeof (struct req_lib_votequorum_qdisk_register);
+	req_lib_votequorum_qdisk_register.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_REGISTER;
+	strcpy(req_lib_votequorum_qdisk_register.name, name);
+	req_lib_votequorum_qdisk_register.votes = votes;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_qdisk_register;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_qdisk_register);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_qdisk_poll (
+	votequorum_handle_t handle,
+	unsigned int state)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_qdisk_poll req_lib_votequorum_qdisk_poll;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_qdisk_poll.header.size = sizeof (struct req_lib_votequorum_qdisk_poll);
+	req_lib_votequorum_qdisk_poll.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_POLL;
+	req_lib_votequorum_qdisk_poll.state = state;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_qdisk_poll;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_qdisk_poll);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_qdisk_unregister (
+	votequorum_handle_t handle)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_general req_lib_votequorum_general;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general);
+	req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_UNREGISTER;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_general;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_general);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+
+
+cs_error_t votequorum_qdisk_getinfo (
+	votequorum_handle_t handle,
+	struct votequorum_qdisk_info *qinfo)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_general req_lib_votequorum_general;
+	struct res_lib_votequorum_qdisk_getinfo res_lib_votequorum_qdisk_getinfo;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general);
+	req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_QDISK_GETINFO;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_general;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_general);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_qdisk_getinfo, sizeof (struct res_lib_votequorum_qdisk_getinfo));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_qdisk_getinfo.header.error;
+
+	qinfo->votes = res_lib_votequorum_qdisk_getinfo.votes;
+	qinfo->state = res_lib_votequorum_qdisk_getinfo.state;
+	strcpy(qinfo->name, res_lib_votequorum_qdisk_getinfo.name);
+
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_setstate (
+	votequorum_handle_t handle)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_general req_lib_votequorum_general;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general);
+	req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_SETSTATE;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_general;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_general);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_leaving (
+	votequorum_handle_t handle)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_general req_lib_votequorum_general;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general);
+	req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_LEAVING;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_general;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_general);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_trackstart (
+	votequorum_handle_t handle,
+	uint64_t context,
+	unsigned int flags )
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_trackstart req_lib_votequorum_trackstart;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_trackstart.header.size = sizeof (struct req_lib_votequorum_trackstart);
+	req_lib_votequorum_trackstart.header.id = MESSAGE_REQ_VOTEQUORUM_TRACKSTART;
+	req_lib_votequorum_trackstart.track_flags = flags;
+	req_lib_votequorum_trackstart.context = context;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_trackstart;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_trackstart);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+cs_error_t votequorum_trackstop (
+	votequorum_handle_t handle)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+	struct iovec iov[2];
+	struct req_lib_votequorum_general req_lib_votequorum_general;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	pthread_mutex_lock (&votequorum_inst->response_mutex);
+
+	req_lib_votequorum_general.header.size = sizeof (struct req_lib_votequorum_general);
+	req_lib_votequorum_general.header.id = MESSAGE_REQ_VOTEQUORUM_TRACKSTOP;
+
+	iov[0].iov_base = (char *)&req_lib_votequorum_general;
+	iov[0].iov_len = sizeof (struct req_lib_votequorum_general);
+
+	error = saSendMsgReceiveReply (votequorum_inst->response_fd, iov, 1,
+		&res_lib_votequorum_status, sizeof (struct res_lib_votequorum_status));
+
+	pthread_mutex_unlock (&votequorum_inst->response_mutex);
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_votequorum_status.header.error;
+
+error_exit:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (error);
+}
+
+
+cs_error_t votequorum_context_get (
+	votequorum_handle_t handle,
+	void **context)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	*context = votequorum_inst->context;
+
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+cs_error_t votequorum_context_set (
+	votequorum_handle_t handle,
+	void *context)
+{
+	cs_error_t error;
+	struct votequorum_inst *votequorum_inst;
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle, (void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	votequorum_inst->context = context;
+
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+
+	return (CS_OK);
+}
+
+
+struct res_overlay {
+	mar_res_header_t header __attribute__((aligned(8)));
+	char data[512000];
+};
+
+cs_error_t votequorum_dispatch (
+	votequorum_handle_t handle,
+	cs_dispatch_flags_t dispatch_types)
+{
+	struct pollfd ufds;
+	int timeout = -1;
+	cs_error_t error;
+	int cont = 1; /* always continue do loop except when set to 0 */
+	int dispatch_avail;
+	struct votequorum_inst *votequorum_inst;
+	votequorum_callbacks_t callbacks;
+	struct res_overlay dispatch_data;
+	struct res_lib_votequorum_notification *res_lib_votequorum_notification;
+
+	if (dispatch_types != CS_DISPATCH_ONE &&
+		dispatch_types != CS_DISPATCH_ALL &&
+		dispatch_types != CS_DISPATCH_BLOCKING) {
+
+		return (CS_ERR_INVALID_PARAM);
+	}
+
+	error = saHandleInstanceGet (&votequorum_handle_t_db, handle,
+		(void *)&votequorum_inst);
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	/*
+	 * Timeout instantly for CS_DISPATCH_ONE or CS_DISPATCH_ALL and
+	 * wait indefinately for CS_DISPATCH_BLOCKING
+	 */
+	if (dispatch_types == CS_DISPATCH_ALL) {
+		timeout = 0;
+	}
+
+	do {
+		ufds.fd = votequorum_inst->dispatch_fd;
+		ufds.events = POLLIN;
+		ufds.revents = 0;
+
+		pthread_mutex_lock (&votequorum_inst->dispatch_mutex);
+
+		error = saPollRetry (&ufds, 1, timeout);
+		if (error != CS_OK) {
+			goto error_unlock;
+		}
+
+		/*
+		 * Handle has been finalized in another thread
+		 */
+		if (votequorum_inst->finalize == 1) {
+			error = CS_OK;
+			goto error_unlock;
+		}
+
+		if ((ufds.revents & (POLLERR|POLLHUP|POLLNVAL)) != 0) {
+			error = CS_ERR_BAD_HANDLE;
+			goto error_unlock;
+		}
+
+		dispatch_avail = ufds.revents & POLLIN;
+		if (dispatch_avail == 0 && dispatch_types == CS_DISPATCH_ALL) {
+			pthread_mutex_unlock (&votequorum_inst->dispatch_mutex);
+			break; /* exit do while cont is 1 loop */
+		} else
+		if (dispatch_avail == 0) {
+			pthread_mutex_unlock (&votequorum_inst->dispatch_mutex);
+			continue; /* next poll */
+		}
+
+		if (ufds.revents & POLLIN) {
+			error = saRecvRetry (votequorum_inst->dispatch_fd, &dispatch_data.header,
+				sizeof (mar_res_header_t));
+			if (error != CS_OK) {
+				goto error_unlock;
+			}
+			if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
+				error = saRecvRetry (votequorum_inst->dispatch_fd, &dispatch_data.data,
+					dispatch_data.header.size - sizeof (mar_res_header_t));
+				if (error != CS_OK) {
+					goto error_unlock;
+				}
+			}
+		} else {
+			pthread_mutex_unlock (&votequorum_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 votequorum_finalize has been called in another thread.
+		 */
+		memcpy (&callbacks, &votequorum_inst->callbacks, sizeof (votequorum_callbacks_t));
+		pthread_mutex_unlock (&votequorum_inst->dispatch_mutex);
+
+		/*
+		 * Dispatch incoming message
+		 */
+		switch (dispatch_data.header.id) {
+
+		case MESSAGE_RES_VOTEQUORUM_NOTIFICATION:
+			if (callbacks.votequorum_notify_fn == NULL) {
+				continue;
+			}
+			res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)&dispatch_data;
+
+			callbacks.votequorum_notify_fn ( handle,
+							 res_lib_votequorum_notification->context,
+							 res_lib_votequorum_notification->quorate,
+							 res_lib_votequorum_notification->node_list_entries,
+							 (votequorum_node_t *)res_lib_votequorum_notification->node_list );
+				;
+			break;
+
+		default:
+			error = CS_ERR_LIBRARY;
+			goto error_put;
+			break;
+		}
+
+		/*
+		 * Determine if more messages should be processed
+		 * */
+		switch (dispatch_types) {
+		case CS_DISPATCH_ONE:
+			cont = 0;
+			break;
+		case CS_DISPATCH_ALL:
+			break;
+		case CS_DISPATCH_BLOCKING:
+			break;
+		}
+	} while (cont);
+
+	goto error_put;
+
+error_unlock:
+	pthread_mutex_unlock (&votequorum_inst->dispatch_mutex);
+
+error_put:
+	saHandleInstancePut (&votequorum_handle_t_db, handle);
+	return (error);
+}
diff -Naurd corosync-0.92/Makefile corosync-trunk/Makefile
--- corosync-0.92/Makefile	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/Makefile	2009-01-26 11:46:08.000000000 +0100
@@ -115,10 +115,17 @@
 	(cd $(builddir)test; echo ==== `pwd` ===; $(call sub_make,test,clean));
 	rm -rf $(builddir)doc/api
 
-COROSYNC_LIBS	= evs cpg cfg coroutil confdb
+lint:
+	(cd $(builddir)exec; echo ==== `pwd` ===; $(call sub_make,exec,lint));
+	(cd $(builddir)services; echo ==== `pwd` ===; $(call sub_make,services,lint));
+	(cd $(builddir)lcr; echo ==== `pwd` ===; $(call sub_make,lcr,lint));
+	(cd $(builddir)lib; echo ==== `pwd` ===; $(call sub_make,lib,lint));
+	(cd $(builddir)tools; echo ==== `pwd` ===; $(call sub_make,tools,lint));
+
+COROSYNC_LIBS	= evs cpg cfg coroutil confdb quorum votequorum
 
 COROSYNC_HEADERS	= cpg.h cfg.h evs.h ipc_gen.h mar_gen.h swab.h \
-		  ais_util.h confdb.h list.h saAis.h
+		  ais_util.h confdb.h quorum.h list.h corotypes.h votequorum.h
 
 EXEC_LIBS	= totem_pg logsys
 
@@ -145,7 +152,7 @@
 	    install -m 755 exec/lib$$eLib.so.2.* $(DESTDIR)$(LIBDIR);	\
 	    if [ "xYES" = "x$(STATICLIBS)" ]; then			\
 		install -m 755 exec/lib$$eLib.a $(DESTDIR)$(LIBDIR);	\
-		if [ ${OPENCOROSYNC_COMPAT} = "DARWIN" ]; then		\
+		if [ ${COROSYNC_COMPAT} = "DARWIN" ]; then		\
 		    ranlib $(DESTDIR)$(LIBDIR)/lib$$eLib.a;		\
 		fi							\
 	    fi								\
@@ -161,7 +168,7 @@
 	    install -m 755 lib/lib$$aLib.so.2.* $(DESTDIR)$(LIBDIR);	\
 	    if [ "xYES" = "x$(STATICLIBS)" ]; then			\
 	        install -m 755 lib/lib$$aLib.a $(DESTDIR)$(LIBDIR);	\
-		if [ ${OPENCOROSYNC_COMPAT} = "DARWIN" ]; then		\
+		if [ ${COROSYNC_COMPAT} = "DARWIN" ]; then		\
 		    ranlib $(DESTDIR)$(LIBDIR)/lib$$aLib.a;		\
 	        fi							\
 	    fi								\
@@ -177,7 +184,7 @@
 	install -m 755 $(builddir)tools/corosync-cfgtool $(DESTDIR)$(SBINDIR)
 	install -m 755 $(builddir)tools/corosync-keygen $(DESTDIR)$(SBINDIR)
 
-	if [ ! -f $(DESTDIR)$(ETCDIR)/penais.conf ] ; then 	   \
+	if [ ! -f $(DESTDIR)$(ETCDIR)/corosync.conf ] ; then 	   \
 		install -m 644 $(srcdir)conf/corosync.conf $(DESTDIR)$(ETCDIR) ; \
 	fi
 
@@ -196,6 +203,7 @@
 	install -m 644 $(srcdir)include/corosync/engine/coroapi.h $(DESTDIR)$(INCLUDEDIR_ENGINE)
 	install -m 644 $(srcdir)include/corosync/engine/objdb.h $(DESTDIR)$(INCLUDEDIR_ENGINE)
 	install -m 644 $(srcdir)include/corosync/engine/logsys.h $(DESTDIR)$(INCLUDEDIR_ENGINE)
+	install -m 644 $(srcdir)include/corosync/engine/quorum.h $(DESTDIR)$(INCLUDEDIR_ENGINE)
 	install -m 644 $(srcdir)include/corosync/engine/config.h $(DESTDIR)$(INCLUDEDIR_ENGINE)
 	install -m 644 $(srcdir)man/*.3 $(DESTDIR)$(MANDIR)/man3
 	install -m 644 $(srcdir)man/*.5 $(DESTDIR)$(MANDIR)/man5
diff -Naurd corosync-0.92/Makefile.inc corosync-trunk/Makefile.inc
--- corosync-0.92/Makefile.inc	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/Makefile.inc	2008-12-09 14:48:47.000000000 +0100
@@ -38,16 +38,15 @@
 # COROSYNC_BUILD can be defined as RELEASE or DEBUG
 #
 ifndef COROSYNC_BUILD
-	COROSYNC_BUILD=DEBUG
+	COROSYNC_BUILD=RELEASE
 endif
 
-# COROSYNC_PROFILE
-
 # default CFLAGS, LDFLAGS
 #
 CFLAGS =
 LDFLAGS =
 DYFLAGS =
+LINT_FLAGS = -weak -unrecog +posixlib +ignoresigns -fcnuse -badflag -D__gnuc_va_list=va_list -D__attribute\(x\)= 
 
 override CFLAGS += -DLCRSODIR='"$(LCRSODIR)"'
 
@@ -58,35 +57,26 @@
 # build CFLAGS, LDFLAGS
 #
 ifeq (${COROSYNC_BUILD}, RELEASE) 
-	CFLAGS += -O3 -Wall
-# -Wstrict-aliasing=2 TODO sameday fix all of these
-ifndef COROSYNC_PROFILE
-	CFLAGS += -fomit-frame-pointer
-endif
-	LDFLAGS += 
+	override CFLAGS += -O3 -Wall
+	override LDFLAGS += 
 endif
 ifeq (${COROSYNC_BUILD}, DEBUG) 
-	CFLAGS += -O0 -g -Wall -DDEBUG --time
-	LDFLAGS += -g
+	override CFLAGS += -O0 -g -Wall
+	override LDFLAGS += -g
 	ifeq (${COROSYNC_COMPAT}, SOLARIS)
 		CFLAGS += -Werror -DTS_CLASS
 	endif
 endif
 ifeq (${COROSYNC_BUILD}, COVERAGE)
-	CFLAGS += -O0 -g -ftest-coverage -fprofile-arcs
-	LDFLAGS += -g -ftest-coverage -fprofile-arcs
+	override CFLAGS += -O0 -g -ftest-coverage -fprofile-arcs
+	override LDFLAGS += -g -ftest-coverage -fprofile-arcs
 	BUILD_DYNAMIC=0
 endif
 
-ifdef COROSYNC_PROFILE
-	CFLAGS += -pg
-	LDFLAGS += -pg
-endif
-
 # platform specific CFLAGS, LDFLAGS
 #
 ifeq (${COROSYNC_COMPAT}, LINUX) 
-	override CFLAGS += -DCOROSYNC_LINUX
+	override CFLAGS += -DCOROSYNC_LINUX -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
 	override LDFLAGS += -ldl -lpthread
 	override DYFLAGS += -rdynamic
 endif
diff -Naurd corosync-0.92/man/confdb_overview.8 corosync-trunk/man/confdb_overview.8
--- corosync-0.92/man/confdb_overview.8	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/man/confdb_overview.8	2009-01-26 11:46:08.000000000 +0100
@@ -34,16 +34,24 @@
 .TH CONFDB_OVERVIEW 8 2006-03-06 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
 .SH OVERVIEW
 The CONFDB library is delivered with the corosync project.  This library is used
-to examine manipulate the configuratin databser used by corosync.
+to examine manipulate the configuration database used by corosync.
 .PP
 The library provides a mechanism to:
+.PP
 * Create new objects
+.PP
 * Create new key/value pairs within those objects
+.PP
 * Remove existing keys
+.PP
 * Remove an existing object and all it sub-objects and keys
+.PP
 * Read keys and values
+.PP
 * Iterate keys within an object
+.PP
 * Iterate subobjects within a parent object
+.PP
 * Find a named object
 .PP
 .SH BUGS
diff -Naurd corosync-0.92/man/corosync.conf.5 corosync-trunk/man/corosync.conf.5
--- corosync-0.92/man/corosync.conf.5	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/man/corosync.conf.5	2008-10-21 00:05:51.000000000 +0200
@@ -435,20 +435,6 @@
 No default.
 
 .TP
-debug
-This specifies whether debug output is logged for all services.  This is
-generally a bad idea, unless there is some specific bug or problem that must be
-found in the executive. Set the value to 
-.B on
-to debug, 
-.B off
-to turn off debugging. If enabled, individual loggers can be disabled using a
-.B logger_subsys
-directive.
-
-The default is off.
-
-.TP
 timestamp
 This specifies that a timestamp is placed on all log messages.
 
diff -Naurd corosync-0.92/man/index.html corosync-trunk/man/index.html
--- corosync-0.92/man/index.html	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/man/index.html	2009-01-26 11:46:08.000000000 +0100
@@ -85,5 +85,30 @@
 <BR>
 <A HREF="confdb_object_parent_get.html">confdb_object_parent_get(3)</A>: Description of the confdb_object_parent_get interface.
 
+<BR>
+<A HREF="votequorum_overview.html">votequorum_overview(8)</A>: An overview of the vote-based quorum service
+<BR>
+<A HREF="votequorum_initialize.html">votequorum_initialize(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_finalize.html">votequorum_finalize(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_fd_get.html">votequorum_fd_get(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_getinfo.html">votequorum_getinfo(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_leaving.html">votequorum_leaving(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_setexpected.html">votequorum_setexpected(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_setvotes.html">votequorum_setvotes(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_qdisk_register.html">votequorum_qdisk_register(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_qdisk_unregister.html">votequorum_qdisk_unregister(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_qdisk_poll.html">votequorum_qdisk_poll(3)</A>: Description of the votequorum interface.
+<BR>
+<A HREF="votequorum_qdisk_getinfo.html">votequorum_qdisk_getinfo(3)</A>: Description of the votequorum interface.
+<BR>
 
 </body>
diff -Naurd corosync-0.92/man/Makefile corosync-trunk/man/Makefile
--- corosync-0.92/man/Makefile	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/man/Makefile	2009-01-26 11:46:08.000000000 +0100
@@ -74,6 +74,19 @@
 	groff -mandoc -Thtml confdb_object_parent_get.3 > html/confdb_object_parent_get.html
 	groff -mandoc -Thtml confdb_overview.8 > html/confdb_overview.html
 
+	groff -mandoc -Thtml votequorum_overview.8 > html/votequorum_overview.html
+	groff -mandoc -Thtml votequorum_initialize.3 > html/votequorum_initialize.html
+	groff -mandoc -Thtml votequorum_finalize.3 > html/votequorum_finalize.html
+	groff -mandoc -Thtml votequorum_fd_get.3 > html/votequorum_fd_get.html
+	groff -mandoc -Thtml votequorum_dispatch.3 > html/votequorum_dispatch.html
+	groff -mandoc -Thtml votequorum_getinfo.3 > html/votequorum_getinfo.html
+	groff -mandoc -Thtml votequorum_leaving.3 > html/votequorum_leaving.html
+	groff -mandoc -Thtml votequorum_setexpected.3 > html/votequorum_setexpected.html
+	groff -mandoc -Thtml votequorum_setvotes.3 > html/votequorum_setvotes.html
+	groff -mandoc -Thtml votequorum_qdisk_register.3 > html/votequorum_qdisk_register.html
+	groff -mandoc -Thtml votequorum_qdisk_unregister.3 > html/votequorum_qdisk_unregister.html
+	groff -mandoc -Thtml votequorum_qdisk_poll.3 > html/votequorum_poll.html
+	groff -mandoc -Thtml votequorum_qdisk_getinfo.3 > html/votequorum_qdisk_getinfo.html
 	cp index.html html
 
 clean:
diff -Naurd corosync-0.92/man/votequorum_dispatch.3 corosync-trunk/man/votequorum_dispatch.3
--- corosync-0.92/man/votequorum_dispatch.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_dispatch.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,96 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_DISPATCH 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_dispatch \- Dispatches callbacks from the votequorum service
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_dispatch(votequorum_handle_t " handle ", votequorum_dispatch_t *" dispatch_types ");"
+.SH DESCRIPTION
+The
+.B votequorum_dispatch
+function is used to dispatch configuration changes.
+.PP
+Each application may have several connections to the votequorum API.  Each  application
+uses the 
+.I handle
+argument to uniquely identify the connection.
+.PP
+The
+.I dispatch_types
+argument is used to identify the type of dispatch to execute.  The possible types are
+defined by the structure:
+
+.IP
+.RS
+.ne 18
+.nf
+.ta 4n 30n 33n
+typedef enum {
+        CS_DISPATCH_ONE,
+        CS_DISPATCH_ALL,
+        CS_DISPATCH_BLOCKING
+} votequorum_dispatch_t;
+.ta
+.fi
+.RE
+.IP
+.PP
+.PP
+The dispatch values have the following meanings:
+.TP
+.B CS_DISPATCH_ONE
+Dispatch at least one callback, blocking until the callback is dispatched.
+.TP
+.B CS_DISPATCH_ALL
+Dispatch all waiting callbacks without blocking to wait for any callbacks.
+.TP
+.B CS_DISPATCH_BLOCKING
+Dispatch all callbacks blocking indefinitely.  This is used in a threaded
+program where a thread is created, and then votequorum_dispatch() is called immediately
+from the created thread to execute callbacks.
+
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_fd_get (3),
+
+.PP
diff -Naurd corosync-0.92/man/votequorum_fd_get.3 corosync-trunk/man/votequorum_fd_get.3
--- corosync-0.92/man/votequorum_fd_get.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_fd_get.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,64 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_FD_GET 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_fd_get \- Dispatches callbacks from the votequorum service
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_fd_get(votequorum_handle_t " handle ", int *" fd ");"
+.SH DESCRIPTION
+The
+.B votequorum_fd_get
+function is used to retrieve the file descriptor that may be used with the poll
+system call to determine when
+.B votequorum_dispatch(3)
+won't block.  The
+.I handle
+argument may not be used directly with
+.B poll
+because it is not the file descriptor, but instead an internal identifier used
+by the votequorum library.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_finalize.3 corosync-trunk/man/votequorum_finalize.3
--- corosync-0.92/man/votequorum_finalize.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_finalize.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,61 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_FINALIZE 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_finalize \- Terminate a connection to the votequorum service
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_finalize(votequorum_handle_t " handle ");"
+.SH DESCRIPTION
+The
+.B votequorum_finalize
+function is used to close a connection to the configuration dabatase API.
+Once the connection is finalized, the handle may not be used again by applications.
+No more callbacks will be dispatched from the
+.B votequorum_dispatch function.
+.PP
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+
+.PP
diff -Naurd corosync-0.92/man/votequorum_getinfo.3 corosync-trunk/man/votequorum_getinfo.3
--- corosync-0.92/man/votequorum_getinfo.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_getinfo.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,91 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_GETINFO 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_getinfo \- Get information about the VoteQuorum service
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_getinfo(votequorum_handle_t *" handle ", unsigned int " nodeid ", struct votequorum_info *" info ");
+.SH DESCRIPTION
+The
+.B votequorum_getinfo
+function is used to get information about the voteing system and its nodes. 
+
+The votequorum_info structure is defined as follows:
+.PP
+.PP
+.IP
+.RS
+.ne 18
+.nf
+.ta 4n 20n 32n
+
+struct votequorum_info {
+	unsigned int node_id;
+	unsigned int node_votes;
+	unsigned int node_expected_votes;
+	unsigned int highest_expected;
+	unsigned int total_votes;
+	unsigned int quorum;
+	unsigned int flags;
+};
+
+#define VOTEQUORUM_INFO_FLAG_DIRTY      1
+#define VOTEQUORUM_INFO_FLAG_DISALLOWED 2
+#define VOTEQUORUM_INFO_FLAG_TWONODE    4
+#define VOTEQUORUM_INFO_FLAG_QUORATE    8
+
+.ta
+.fi
+.RE
+.IP
+.PP
+.PP
+The members starting node_ hold information specific to the requested nodeid, the other are
+general to the voting system.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH BUGS
+Callbacks are not support at the moment.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_finalize (3),
+.BR votequorum_fd_get (3),
+.BR votequorum_dispatch (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_initialize.3 corosync-trunk/man/votequorum_initialize.3
--- corosync-0.92/man/votequorum_initialize.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_initialize.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,106 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_INITIALIZE 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_initialize \- Create a new connection to the VoteQuorum service
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_initialize(votequorum_handle_t *" handle ", votequorum_callbacks_t *" callbacks ");
+.SH DESCRIPTION
+The
+.B votequorum_initialize
+function is used to initialize a connection to the vote-based quorum database API.
+.PP
+Each application may have several connections to the votequorum API.  Each application
+uses the 
+.I handle
+argument to uniquely identify the connection.  The
+.I handle
+argument is then used in other function calls to identify the connection to be used
+for communication with the votequorum service.
+.PP
+Every time the voting configuraton changes (eg a node joins or leave the cluster), the callback is called.
+The callback function is described by the following type definitions:
+
+typedef void (*votequorum_notification_fn_t) (
+	votequorum_handle_t handle,
+	uint64_t context,
+	uint32_t quorate,
+	uint32_t node_list_entries,
+	votequorum_node_t node_list[]
+	);
+
+.ta
+.fi
+.RE
+.IP
+.PP
+.PP
+The
+.I callbacks
+argument is of the type:
+.IP
+.RS
+.ne 18
+.nf
+.PP
+typedef struct {
+	votequorum_notification_fn_t votequorum_notify_fn;
+} votequorum_callbacks_t;
+
+.ta
+.fi
+.RE
+.IP
+.PP
+When a configuration change occurs, the callback
+is called from the
+.B votequorum_dispatch()
+function. 
+.PP
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH BUGS
+Callbacks are not support at the moment.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_finalize (3),
+.BR votequorum_fd_get (3),
+.BR votequorum_dispatch (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_leaving.3 corosync-trunk/man/votequorum_leaving.3
--- corosync-0.92/man/votequorum_leaving.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_leaving.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,67 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_LEAVING 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_leaving \- Tell other nodes that we are leaving the cluster
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_leaving(votequorum_handle_t " handle ");"
+.SH DESCRIPTION
+The
+.B votequorum_leaving
+function is used to tell the other nodes in the cluster that this node is leaving. They
+will (when the node actually leaves) reduce quorum to keep the cluster running without
+this node.
+.PP
+This function should only be called if it is known that the node is being shut down for
+a known reason and could be out of the cluster for an extended period of time. 
+.PP
+Normal behaviour is for the cluster to reduce the total number of votes, but NOT expected_votes
+when a node leave the cluster, so the cluster could become inquorate. This is correct behaviour
+and is ther eto prevent split-brain.
+.PP
+Do NOT call this function unless you know what you are doing.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_overview.8 corosync-trunk/man/votequorum_overview.8
--- corosync-0.92/man/votequorum_overview.8	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_overview.8	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,82 @@
+.\"/*
+.\" * 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.
+.\" */
+.TH VOTEQUORUM_OVERVIEW 8 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH OVERVIEW
+The votequuorum library is delivered with the corosync project. It is the external interface to 
+the vote-based quorum service. This service is optionally loaded into all ndes in a corosync cluster
+to avoid split-brain situations. It does this by having a number of votes assigned to each system
+in the cluster and ensuring that only when a majority of the votes are present, cluster operations are
+allowed to proceed.
+.PP
+The library provides a mechanism to:
+* Query the quorum status
+.PP
+* Get a list of nodes known to the quorum service
+.PP
+* Receive notifications of quorum state changes
+.PP
+* Change the number of votes assigned to a node
+.PP
+* Change the number of expected votes for a cluster to be quorate
+.PP
+* Connect an additional quorum device to allow small clusters to remain quorate during node outages.
+.PP
+.B votequorum 
+reads its configuration from the objdb. The following keys are read when it starts up:
+.PP
+* quorum.expected_votes
+.br
+* quorum.votes
+.br
+* quorum.quorumdev_poll
+.br
+* quorum.disallowed
+.br
+* quorum.two_node
+.PP
+Most of those values can be changed while corosync is running with the following exceptions:
+.B quorum.disallowed 
+cannot be changed, and
+.B two_node
+cannot be set on-the-fly, though it can be cleared. ie you can start with two nodes in the cluster
+and add a third without rebooting all the nodes.
+.PP
+.SH BUGS
+This software is not yet production, so there may still be some bugs.
+.SH "SEE ALSO"
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_fd_get (3),
+.BR votequorum_dispatch (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_qdisk_getinfo.3 corosync-trunk/man/votequorum_qdisk_getinfo.3
--- corosync-0.92/man/votequorum_qdisk_getinfo.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_qdisk_getinfo.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,80 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_QDISK_GETINFO 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_qdisk_getinfo \- Get details of the quorum device
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_qdisk_getinfo(votequorum_handle_t " handle ", struct votequorum_qdisk_info " *info ");"
+.SH DESCRIPTION
+The
+.B votequorum_qdisk_getinfo
+Returns information about the quorum device in the following structure:
+.PP
+.PP
+.IP
+.RS
+.ne 18
+.nf
+.ta 4n 20n 32n
+
+struct votequorum_qdisk_info {
+	unsigned int votes;
+	unsigned int state;
+	char name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
+};
+
+.ta
+.fi
+.RE
+.IP
+.PP
+.PP
+
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.BR votequorum_qdisk_poll (3),
+.BR votequorum_qdisk_unregister (3),
+.BR votequorum_qdisk_getinfo (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_qdisk_poll.3 corosync-trunk/man/votequorum_qdisk_poll.3
--- corosync-0.92/man/votequorum_qdisk_poll.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_qdisk_poll.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,69 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_QDISK_POLL 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_qdisk_poll \- Tells votequorum the result of the quorum device poll
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_qdisk_poll(votequorum_handle_t " handle ", unsigned int " state ");"
+.SH DESCRIPTION
+The
+.B votequorum_qdisk_poll
+is called by the quorum device subsyetem (not provided as part of votequorum) to tell
+the voting system if the qurum device is present/active or not. If 
+.B state
+is 1 then the votes for the device are included in the quorum calculation, otherwise not.
+This routine should be called at regular intervals to ensure that the device status
+is always known to votequorum. If 
+.B votequorum_qdisk_poll
+is not called after (default) 10 seconds then the device will be deeded to be dead and 
+its votes removed from the cluster. This does not unregister the device.
+The default poll time can be changed by setting the object database variable
+quorum.quorumdev_poll.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.BR votequorum_qdisk_poll (3),
+.BR votequorum_qdisk_unregister (3),
+.BR votequorum_qdisk_getinfo (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_qdisk_register.3 corosync-trunk/man/votequorum_qdisk_register.3
--- corosync-0.92/man/votequorum_qdisk_register.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_qdisk_register.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,68 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_QDISK_REGISTER 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_qdisk_register \- Registers a new quorum device
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_qdisk_register(votequorum_handle_t " handle ", char * " name ", unsigned int " votes ");"
+.SH DESCRIPTION
+The
+.B votequorum_qdisk_register
+is used to register a new quorum device. A quorum device is an external way of adding votes to a small 
+cluster. The quorum device is, in effect, a pseudo node in the cluster that provide votes based on some
+external device, usually a shared disk partition or perhaps a network router.
+.br
+This call creates the device but does not mark it active.
+.B votequorum_qdisk_poll
+must be called for the votes to be included in the quorum calculation.
+.br
+Note that it is the responsibility of the quorum device subsystem (not provided as part of votequorum)
+to keep all nodes informed of the quorum device status.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.BR votequorum_qdisk_poll (3),
+.BR votequorum_qdisk_unregister (3),
+.BR votequorum_qdisk_getinfo (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_qdisk_unregister.3 corosync-trunk/man/votequorum_qdisk_unregister.3
--- corosync-0.92/man/votequorum_qdisk_unregister.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_qdisk_unregister.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,60 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_QDISK_UNREGISTER 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_qdisk_unregister \- Unregisters a new quorum device
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_qdisk_unregister(votequorum_handle_t " handle ");"
+.SH DESCRIPTION
+The
+.B votequorum_qdisk_unregister
+unregisters a quorum device. Any votes it had will be removed from the cluster. Not that this could
+make the cluster inquorate.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.BR votequorum_qdisk_poll (3),
+.BR votequorum_qdisk_unregister (3),
+.BR votequorum_qdisk_getinfo (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_setexpected.3 corosync-trunk/man/votequorum_setexpected.3
--- corosync-0.92/man/votequorum_setexpected.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_setexpected.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,60 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_SETEXPECTED 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_setexpected \- Sets the expected votes for the cluster
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_setexpected(votequorum_handle_t " handle ", int " expected_votes ");"
+.SH DESCRIPTION
+The
+.B votequorum_setexpected
+function is used to change the expected votes in the cluster. Expected votes is used to calculate
+quorum and should normally be the total number of votes that will exist when all the expected nodes
+are joined. Quorum will usually be half of this (rounded up).
+.br
+It is not possible to set expected votes up so that it makes the cluster inquorate using this command.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.PP
diff -Naurd corosync-0.92/man/votequorum_setvotes.3 corosync-trunk/man/votequorum_setvotes.3
--- corosync-0.92/man/votequorum_setvotes.3	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/man/votequorum_setvotes.3	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,57 @@
+.\"/*
+.\" * Copyright (c) 2009 Red Hat, Inc.
+.\" *
+.\" * All rights reserved.
+.\" *
+.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
+.\" *
+.\" * This software licensed under BSD license, the text of which follows:
+.\" * 
+.\" * Redistribution and use in source and binary forms, with or without
+.\" * modification, are permitted provided that the following conditions are met:
+.\" *
+.\" * - Redistributions of source code must retain the above copyright notice,
+.\" *   this list of conditions and the following disclaimer.
+.\" * - Redistributions in binary form must reproduce the above copyright notice,
+.\" *   this list of conditions and the following disclaimer in the documentation
+.\" *   and/or other materials provided with the distribution.
+.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
+.\" *   contributors may be used to endorse or promote products derived from this
+.\" *   software without specific prior written permission.
+.\" *
+.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" * THE POSSIBILITY OF SUCH DAMAGE.
+.\" */
+.TH VOTEQUORUM_VOTES 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.SH NAME
+votequorum_setvotes \- Sets the number of votes for a node
+.SH SYNOPSIS
+.B #include <corosync/votequorum.h>
+.sp
+.BI "int votequorum_setexpected(votequorum_handle_t " handle ", unsigned int " nodeid ", int " votes ");"
+.SH DESCRIPTION
+The
+.B votequorum_setvotes
+is used to change the number of votes that a node has. Note that it is not possible, using this function, 
+to change the number of node votes such that the cluster goes inquorate.
+.SH RETURN VALUE
+This call returns the CS_OK value if successful, otherwise an error is returned.
+.PP
+.SH ERRORS
+The errors are undocumented.
+.SH "SEE ALSO"
+.BR votequorum_overview (8),
+.BR votequorum_initialize (3),
+.BR votequorum_finalize (3),
+.BR votequorum_dispatch (3),
+.BR votequorum_fd_get (3),
+.PP
diff -Naurd corosync-0.92/services/cfg.c corosync-trunk/services/cfg.c
--- corosync-0.92/services/cfg.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/services/cfg.c	2009-01-19 09:31:21.000000000 +0100
@@ -1,13 +1,13 @@
 /*
  * Copyright (c) 2005-2006 MontaVista Software, Inc.
- * Copyright (c) 2006-2008 Red Hat, Inc.
+ * Copyright (c) 2006-2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
  * Author: Steven Dake (sdake@redhat.com)
  *
  * This software licensed under BSD license, the text of which follows:
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  *
@@ -42,16 +42,18 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <limits.h>
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/cfg.h>
 #include <corosync/list.h>
 #include <corosync/queue.h>
 #include <corosync/mar_gen.h>
 #include <corosync/ipc_gen.h>
+#include <corosync/totem/totemip.h>
 #include <corosync/ipc_cfg.h>
 #include <corosync/lcr/lcr_comp.h>
 #include <corosync/engine/logsys.h>
@@ -60,7 +62,31 @@
 LOGSYS_DECLARE_SUBSYS ("CFG", LOG_INFO);
 
 enum cfg_message_req_types {
-        MESSAGE_REQ_EXEC_CFG_RINGREENABLE = 0
+        MESSAGE_REQ_EXEC_CFG_RINGREENABLE = 0,
+	MESSAGE_REQ_EXEC_CFG_KILLNODE = 1,
+	MESSAGE_REQ_EXEC_CFG_SHUTDOWN = 2
+};
+
+#define DEFAULT_SHUTDOWN_TIMEOUT 5
+
+static struct list_head trackers_list;
+
+/*
+ * Variables controlling a requested shutdown
+ */
+static corosync_timer_handle_t shutdown_timer;
+static struct cfg_info *shutdown_con;
+static uint32_t shutdown_flags;
+static int shutdown_yes;
+static int shutdown_no;
+static int shutdown_expected;
+
+struct cfg_info
+{
+	struct list_head list;
+	void *conn;
+	void *tracker_conn;
+	enum {SHUTDOWN_REPLY_UNKNOWN, SHUTDOWN_REPLY_YES, SHUTDOWN_REPLY_NO} shutdown_reply;
 };
 
 static void cfg_confchg_fn (
@@ -82,6 +108,16 @@
         void *message,
         unsigned int nodeid);
 
+static void message_handler_req_exec_cfg_killnode (
+        void *message,
+        unsigned int nodeid);
+
+static void message_handler_req_exec_cfg_shutdown (
+        void *message,
+        unsigned int nodeid);
+
+static void exec_cfg_killnode_endian_convert (void *msg);
+
 static void message_handler_req_lib_cfg_ringstatusget (
 	void *conn,
 	void *msg);
@@ -114,6 +150,22 @@
 	void *conn,
 	void *msg);
 
+static void message_handler_req_lib_cfg_killnode (
+	void *conn,
+	void *msg);
+
+static void message_handler_req_lib_cfg_tryshutdown (
+	void *conn,
+	void *msg);
+
+static void message_handler_req_lib_cfg_replytoshutdown (
+	void *conn,
+	void *msg);
+
+static void message_handler_req_lib_cfg_get_node_addrs (
+	void *conn,
+	void *msg);
+
 /*
  * Service Handler Definition
  */
@@ -123,56 +175,87 @@
 		.lib_handler_fn		= message_handler_req_lib_cfg_ringstatusget,
 		.response_size		= sizeof (struct res_lib_cfg_ringstatusget),
 		.response_id		= MESSAGE_RES_CFG_RINGSTATUSGET,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 1 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_ringreenable,
 		.response_size		= sizeof (struct res_lib_cfg_ringreenable),
 		.response_id		= MESSAGE_RES_CFG_RINGREENABLE,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 2 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_statetrack,
 		.response_size		= sizeof (struct res_lib_cfg_statetrack),
 		.response_id		= MESSAGE_RES_CFG_STATETRACKSTART,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 3 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_statetrackstop,
 		.response_size		= sizeof (struct res_lib_cfg_statetrackstop),
 		.response_id		= MESSAGE_RES_CFG_STATETRACKSTOP,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 4 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_administrativestateset,
 		.response_size		= sizeof (struct res_lib_cfg_administrativestateset),
 		.response_id		= MESSAGE_RES_CFG_ADMINISTRATIVESTATESET,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 5 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_administrativestateget,
 		.response_size		= sizeof (struct res_lib_cfg_administrativestateget),
 		.response_id		= MESSAGE_RES_CFG_ADMINISTRATIVESTATEGET,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 6 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_serviceload,
 		.response_size		= sizeof (struct res_lib_cfg_serviceload),
 		.response_id		= MESSAGE_RES_CFG_SERVICELOAD,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 7 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_serviceunload,
 		.response_size		= sizeof (struct res_lib_cfg_serviceunload),
 		.response_id		= MESSAGE_RES_CFG_SERVICEUNLOAD,
-		.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 8 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_killnode,
+		.response_size		= sizeof (struct res_lib_cfg_killnode),
+		.response_id		= MESSAGE_RES_CFG_KILLNODE,
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 9 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_tryshutdown,
+		.response_size		= sizeof (struct res_lib_cfg_tryshutdown),
+		.response_id		= MESSAGE_RES_CFG_TRYSHUTDOWN,
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 10 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_replytoshutdown,
+		.response_size		= 0,
+		.response_id		= 0,
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 11 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_get_node_addrs,
+		.response_size		= sizeof (struct res_lib_cfg_get_node_addrs),
+		.response_id		= MESSAGE_RES_CFG_GET_NODE_ADDRS,
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	}
 };
 
 static struct corosync_exec_handler cfg_exec_engine[] =
 {
-	{
-		message_handler_req_exec_cfg_ringreenable
+	{ /* 0 */
+		.exec_handler_fn = message_handler_req_exec_cfg_ringreenable,
+	},
+	{ /* 1 */
+		.exec_handler_fn = message_handler_req_exec_cfg_killnode,
+		.exec_endian_convert_fn	= exec_cfg_killnode_endian_convert
+	},
+	{ /* 2 */
+		.exec_handler_fn = message_handler_req_exec_cfg_shutdown,
 	}
 };
 
@@ -182,8 +265,9 @@
 struct corosync_service_engine cfg_service_engine = {
 	.name					= "corosync configuration service",
 	.id					= CFG_SERVICE,
-	.private_data_size			= 0,
-	.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, 
+	.private_data_size			= sizeof(struct cfg_info),
+	.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
+	.allow_inquorate			= CS_LIB_ALLOW_INQUORATE,
 	.lib_init_fn				= cfg_lib_init_fn,
 	.lib_exit_fn				= cfg_lib_exit_fn,
 	.lib_engine				= cfg_lib_engine,
@@ -238,12 +322,24 @@
         mar_message_source_t source __attribute__((aligned(8)));
 };
 
+struct req_exec_cfg_killnode {
+	mar_req_header_t header __attribute__((aligned(8)));
+        mar_uint32_t nodeid __attribute__((aligned(8)));
+	mar_name_t reason __attribute__((aligned(8)));
+};
+
+struct req_exec_cfg_shutdown {
+	mar_req_header_t header __attribute__((aligned(8)));
+};
+
 /* IMPL */
 
 static int cfg_exec_init_fn (
 	struct corosync_api_v1 *corosync_api_v1)
 {
 	api = corosync_api_v1;
+
+	list_init(&trackers_list);
 	return (0);
 }
 
@@ -256,16 +352,193 @@
 {
 }
 
+/*
+ * Tell other nodes we are shutting down
+ */
+static int send_shutdown()
+{
+	struct req_exec_cfg_shutdown req_exec_cfg_shutdown;
+	struct iovec iovec;
+
+	ENTER();
+	req_exec_cfg_shutdown.header.size =
+		sizeof (struct req_exec_cfg_shutdown);
+	req_exec_cfg_shutdown.header.id = SERVICE_ID_MAKE (CFG_SERVICE,
+		MESSAGE_REQ_EXEC_CFG_SHUTDOWN);
+
+	iovec.iov_base = (char *)&req_exec_cfg_shutdown;
+	iovec.iov_len = sizeof (struct req_exec_cfg_shutdown);
+
+	assert (api->totem_mcast (&iovec, 1, TOTEM_SAFE) == 0);
+
+	LEAVE();
+	return 0;
+}
+
+static void send_test_shutdown(void * conn, int status)
+{
+	struct res_lib_cfg_testshutdown res_lib_cfg_testshutdown;
+	struct list_head *iter;
+
+	ENTER();
+	res_lib_cfg_testshutdown.header.size = sizeof(struct res_lib_cfg_testshutdown);
+	res_lib_cfg_testshutdown.header.id = MESSAGE_RES_CFG_TESTSHUTDOWN;
+	res_lib_cfg_testshutdown.header.error = status;
+	res_lib_cfg_testshutdown.flags = shutdown_flags;
+
+	if (conn) {
+		TRACE1("sending testshutdown to %p", conn);
+		api->ipc_conn_send_response(conn, &res_lib_cfg_testshutdown,
+					    sizeof(res_lib_cfg_testshutdown));
+	} else {
+		for (iter = trackers_list.next; iter != &trackers_list; iter = iter->next) {
+			struct cfg_info *ci = list_entry(iter, struct cfg_info, list);
+
+			TRACE1("sending testshutdown to %p", ci->tracker_conn);
+			api->ipc_conn_send_response(ci->tracker_conn, &res_lib_cfg_testshutdown,
+						    sizeof(res_lib_cfg_testshutdown));
+		}
+	}
+	LEAVE();
+}
+
+static void check_shutdown_status()
+{
+	ENTER();
+
+	/*
+	 * Shutdown client might have gone away
+	 */
+	if (!shutdown_con) {
+		LEAVE();
+		return;
+	}
+
+	/*
+	 * All replies safely gathered in ?
+	 */
+	if (shutdown_yes + shutdown_no >= shutdown_expected) {
+		struct res_lib_cfg_tryshutdown res_lib_cfg_tryshutdown;
+
+		api->timer_delete(shutdown_timer);
+
+		if (shutdown_yes >= shutdown_expected ||
+		    shutdown_flags == CFG_SHUTDOWN_FLAG_REGARDLESS) {
+			TRACE1("shutdown confirmed");
+
+			/*
+			 * Tell other nodes we are going down
+			 */
+			send_shutdown();
+
+			res_lib_cfg_tryshutdown.header.size = sizeof(struct res_lib_cfg_tryshutdown);
+			res_lib_cfg_tryshutdown.header.id = MESSAGE_RES_CFG_TRYSHUTDOWN;
+			res_lib_cfg_tryshutdown.header.error = CS_OK;
+
+			/*
+			 * Tell originator that shutdown was confirmed
+			 */
+			api->ipc_conn_send_response(shutdown_con->conn, &res_lib_cfg_tryshutdown,
+						    sizeof(res_lib_cfg_tryshutdown));
+			shutdown_con = NULL;
+		}
+		else {
+
+			TRACE1("shutdown cancelled");
+			res_lib_cfg_tryshutdown.header.size = sizeof(struct res_lib_cfg_tryshutdown);
+			res_lib_cfg_tryshutdown.header.id = MESSAGE_RES_CFG_TRYSHUTDOWN;
+			res_lib_cfg_tryshutdown.header.error = CS_ERR_BUSY;
+
+			/*
+			 * Tell originator that shutdown was cancelled
+			 */
+			api->ipc_conn_send_response(shutdown_con->conn, &res_lib_cfg_tryshutdown,
+						    sizeof(res_lib_cfg_tryshutdown));
+			shutdown_con = NULL;
+		}
+
+		log_printf(LOG_DEBUG, "shutdown decision is: (yes count: %d, no count: %d) flags=%x\n", shutdown_yes, shutdown_no, shutdown_flags);
+	}
+	LEAVE();
+}
+
+
+/*
+ * Not all nodes responded to the shutdown (in time)
+ */
+static void shutdown_timer_fn(void *arg)
+{
+	ENTER();
+
+	/*
+	 * Mark undecideds as "NO"
+	 */
+	shutdown_no = shutdown_expected;
+	check_shutdown_status();
+
+	send_test_shutdown(NULL, CS_ERR_TIMEOUT);
+	LEAVE();
+}
+
+static void remove_ci_from_shutdown(struct cfg_info *ci)
+{
+	ENTER();
+
+	/*
+	 * If the controlling shutdown process has quit, then cancel the
+	 * shutdown session
+	 */
+	if (ci == shutdown_con) {
+		shutdown_con = NULL;
+		api->timer_delete(shutdown_timer);
+	}
+
+	if (!list_empty(&ci->list)) {
+		list_del(&ci->list);
+		list_init(&ci->list);
+
+		/*
+		 * Remove our option
+		 */
+		if (shutdown_con) {
+			if (ci->shutdown_reply == SHUTDOWN_REPLY_YES)
+				shutdown_yes--;
+			if (ci->shutdown_reply == SHUTDOWN_REPLY_NO)
+				shutdown_no--;
+		}
+
+		/*
+		 * If we are leaving, then that's an implicit YES to shutdown
+		 */
+		ci->shutdown_reply = SHUTDOWN_REPLY_YES;
+		shutdown_yes++;
+
+		check_shutdown_status();
+	}
+	LEAVE();
+}
+
+
 int cfg_lib_exit_fn (void *conn)
 {
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+
+	ENTER();
+	if (!list_empty(&ci->list)) {
+		list_del(&ci->list);
+		remove_ci_from_shutdown(ci);
+	}
+	LEAVE();
 	return (0);
 }
 
 static int cfg_lib_init_fn (void *conn)
 {
-	
-	ENTER("");
-	LEAVE("");
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+
+	ENTER();
+	list_init(&ci->list);
+	LEAVE();
 
         return (0);
 }
@@ -281,18 +554,64 @@
 		(struct req_exec_cfg_ringreenable *)message;
 	struct res_lib_cfg_ringreenable res_lib_cfg_ringreenable;
 
-	ENTER("");
+	ENTER();
 	api->totem_ring_reenable ();
         if (api->ipc_source_is_local(&req_exec_cfg_ringreenable->source)) {
 		res_lib_cfg_ringreenable.header.id = MESSAGE_RES_CFG_RINGREENABLE;
 		res_lib_cfg_ringreenable.header.size = sizeof (struct res_lib_cfg_ringreenable);
-		res_lib_cfg_ringreenable.header.error = SA_AIS_OK;
+		res_lib_cfg_ringreenable.header.error = CS_OK;
 		api->ipc_conn_send_response (
 			req_exec_cfg_ringreenable->source.conn,
 			&res_lib_cfg_ringreenable,
 			sizeof (struct res_lib_cfg_ringreenable));
 	}
-	LEAVE("");
+	LEAVE();
+}
+
+static void exec_cfg_killnode_endian_convert (void *msg)
+{
+	struct req_exec_cfg_killnode *req_exec_cfg_killnode =
+		(struct req_exec_cfg_killnode *)msg;
+	ENTER();
+
+	swab_mar_name_t(&req_exec_cfg_killnode->reason);
+	LEAVE();
+}
+
+
+static void message_handler_req_exec_cfg_killnode (
+        void *message,
+        unsigned int nodeid)
+{
+	struct req_exec_cfg_killnode *req_exec_cfg_killnode =
+		(struct req_exec_cfg_killnode *)message;
+	cs_name_t reason;
+
+	ENTER();
+	log_printf(LOG_DEBUG, "request to kill node %d(us=%d): %s\n",  req_exec_cfg_killnode->nodeid, api->totem_nodeid_get(), reason.value);
+        if (req_exec_cfg_killnode->nodeid == api->totem_nodeid_get()) {
+		marshall_from_mar_name_t(&reason, &req_exec_cfg_killnode->reason);
+		log_printf(LOG_NOTICE, "Killed by node %d: %s\n",
+			   nodeid, reason.value);
+		corosync_fatal_error(COROSYNC_FATAL_ERROR_EXIT);
+	}
+	LEAVE();
+}
+
+/*
+ * Self shutdown
+ */
+static void message_handler_req_exec_cfg_shutdown (
+        void *message,
+        unsigned int nodeid)
+{
+	ENTER();
+
+	log_printf(LOG_NOTICE, "Node %d was shut down by sysadmin\n", nodeid);
+	if (nodeid == api->totem_nodeid_get()) {
+		corosync_fatal_error(COROSYNC_FATAL_ERROR_EXIT);
+	}
+	LEAVE();
 }
 
 
@@ -310,11 +629,11 @@
 	char *totem_ip_string;
 	unsigned int i;
 
-	ENTER("");
+	ENTER();
 
 	res_lib_cfg_ringstatusget.header.id = MESSAGE_RES_CFG_RINGSTATUSGET;
 	res_lib_cfg_ringstatusget.header.size = sizeof (struct res_lib_cfg_ringstatusget);
-	res_lib_cfg_ringstatusget.header.error = SA_AIS_OK;
+	res_lib_cfg_ringstatusget.header.error = CS_OK;
 
 	api->totem_ifaces_get (
 		api->totem_nodeid_get(),
@@ -336,7 +655,7 @@
 		&res_lib_cfg_ringstatusget,
 		sizeof (struct res_lib_cfg_ringstatusget));
 
-	LEAVE("");
+	LEAVE();
 }
 
 static void message_handler_req_lib_cfg_ringreenable (
@@ -346,7 +665,7 @@
 	struct req_exec_cfg_ringreenable req_exec_cfg_ringreenable;
 	struct iovec iovec;
 
-	ENTER("");
+	ENTER();
 	req_exec_cfg_ringreenable.header.size =
 		sizeof (struct req_exec_cfg_ringreenable);
 	req_exec_cfg_ringreenable.header.id = SERVICE_ID_MAKE (CFG_SERVICE,
@@ -358,27 +677,56 @@
 
 	assert (api->totem_mcast (&iovec, 1, TOTEM_SAFE) == 0);
 
-	LEAVE("");
+	LEAVE();
 }
 
 static void message_handler_req_lib_cfg_statetrack (
 	void *conn,
 	void *msg)
 {
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
 //	struct req_lib_cfg_statetrack *req_lib_cfg_statetrack = (struct req_lib_cfg_statetrack *)message;
+	struct res_lib_cfg_statetrack res_lib_cfg_statetrack;
 
-	ENTER("");
-	LEAVE("");
+	ENTER();
+
+	/*
+	 * We only do shutdown tracking at the moment
+	 */
+	if (list_empty(&ci->list)) {
+		list_add(&ci->list, &trackers_list);
+		ci->tracker_conn = api->ipc_conn_partner_get (conn);
+
+		if (shutdown_con) {
+			/*
+			 * Shutdown already in progress, ask the newcomer's opinion
+			 */
+			ci->shutdown_reply = SHUTDOWN_REPLY_UNKNOWN;
+			shutdown_expected++;
+			send_test_shutdown(ci->tracker_conn, CS_OK);
+		}
+	}
+
+	res_lib_cfg_statetrack.header.size = sizeof(struct res_lib_cfg_statetrack);
+	res_lib_cfg_statetrack.header.id = MESSAGE_RES_CFG_STATETRACKSTART;
+	res_lib_cfg_statetrack.header.error = CS_OK;
+
+	api->ipc_conn_send_response(conn, &res_lib_cfg_statetrack,
+				    sizeof(res_lib_cfg_statetrack));
+
+	LEAVE();
 }
 
 static void message_handler_req_lib_cfg_statetrackstop (
 	void *conn,
 	void *msg)
 {
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
 //	struct req_lib_cfg_statetrackstop *req_lib_cfg_statetrackstop = (struct req_lib_cfg_statetrackstop *)message;
 
-	ENTER("");
-	LEAVE("");
+	ENTER();
+	remove_ci_from_shutdown(ci);
+	LEAVE();
 }
 
 static void message_handler_req_lib_cfg_administrativestateset (
@@ -386,16 +734,17 @@
 	void *msg)
 {
 //	struct req_lib_cfg_administrativestateset *req_lib_cfg_administrativestateset = (struct req_lib_cfg_administrativestateset *)message;
-	ENTER("");
-	LEAVE("");
+
+	ENTER();
+	LEAVE();
 }
 static void message_handler_req_lib_cfg_administrativestateget (
 	void *conn,
 	void *msg)
 {
 //	struct req_lib_cfg_administrativestateget *req_lib_cfg_administrativestateget = (struct req_lib_cfg_administrativestateget *)message;
-	ENTER("");
-	LEAVE("");
+	ENTER();
+	LEAVE();
 }
 
 static void message_handler_req_lib_cfg_serviceload (
@@ -406,7 +755,7 @@
 		(struct req_lib_cfg_serviceload *)msg;
 	struct res_lib_cfg_serviceload res_lib_cfg_serviceload;
 
-	ENTER("");
+	ENTER();
 	api->service_link_and_init (
 		api,
 		(char *)req_lib_cfg_serviceload->service_name,
@@ -414,12 +763,12 @@
 
 	res_lib_cfg_serviceload.header.id = MESSAGE_RES_CFG_SERVICEUNLOAD;
 	res_lib_cfg_serviceload.header.size = sizeof (struct res_lib_cfg_serviceload);
-	res_lib_cfg_serviceload.header.error = SA_AIS_OK;
+	res_lib_cfg_serviceload.header.error = CS_OK;
 	api->ipc_conn_send_response (
 		conn,
 		&res_lib_cfg_serviceload,
 		sizeof (struct res_lib_cfg_serviceload));
-	LEAVE("");
+	LEAVE();
 }
 
 static void message_handler_req_lib_cfg_serviceunload (
@@ -430,17 +779,225 @@
 		(struct req_lib_cfg_serviceunload *)msg;
 	struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload;
 
-	ENTER("");
+	ENTER();
 	api->service_unlink_and_exit (
 		api,
 		(char *)req_lib_cfg_serviceunload->service_name,
 		req_lib_cfg_serviceunload->service_ver);
 	res_lib_cfg_serviceunload.header.id = MESSAGE_RES_CFG_SERVICEUNLOAD;
 	res_lib_cfg_serviceunload.header.size = sizeof (struct res_lib_cfg_serviceunload);
-	res_lib_cfg_serviceunload.header.error = SA_AIS_OK;
+	res_lib_cfg_serviceunload.header.error = CS_OK;
 	api->ipc_conn_send_response (
 		conn,
 		&res_lib_cfg_serviceunload,
 		sizeof (struct res_lib_cfg_serviceunload));
-	LEAVE("");
+	LEAVE();
+}
+
+
+static void message_handler_req_lib_cfg_killnode (
+	void *conn,
+	void *msg)
+{
+	struct req_lib_cfg_killnode *req_lib_cfg_killnode = (struct req_lib_cfg_killnode *)msg;
+	struct res_lib_cfg_killnode res_lib_cfg_killnode;
+	struct req_exec_cfg_killnode req_exec_cfg_killnode;
+	struct iovec iovec;
+	int res;
+
+	ENTER();
+	req_exec_cfg_killnode.header.size =
+		sizeof (struct req_exec_cfg_killnode);
+	req_exec_cfg_killnode.header.id = SERVICE_ID_MAKE (CFG_SERVICE,
+		MESSAGE_REQ_EXEC_CFG_KILLNODE);
+	req_exec_cfg_killnode.nodeid = req_lib_cfg_killnode->nodeid;
+	marshall_to_mar_name_t(&req_exec_cfg_killnode.reason, &req_lib_cfg_killnode->reason);
+
+	iovec.iov_base = (char *)&req_exec_cfg_killnode;
+	iovec.iov_len = sizeof (struct req_exec_cfg_killnode);
+
+	res = api->totem_mcast (&iovec, 1, TOTEM_SAFE);
+
+	res_lib_cfg_killnode.header.size = sizeof(struct res_lib_cfg_killnode);
+	res_lib_cfg_killnode.header.id = MESSAGE_RES_CFG_KILLNODE;
+	res_lib_cfg_killnode.header.error = CS_OK;
+
+	api->ipc_conn_send_response(conn, &res_lib_cfg_killnode,
+				    sizeof(res_lib_cfg_killnode));
+
+	LEAVE();
+}
+
+
+static void message_handler_req_lib_cfg_tryshutdown (
+	void *conn,
+	void *msg)
+{
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+	struct req_lib_cfg_tryshutdown *req_lib_cfg_tryshutdown = (struct req_lib_cfg_tryshutdown *)msg;
+	struct res_lib_cfg_tryshutdown res_lib_cfg_tryshutdown;
+	struct list_head *iter;
+
+	ENTER();
+
+	if (req_lib_cfg_tryshutdown->flags == CFG_SHUTDOWN_FLAG_IMMEDIATE) {
+
+		/*
+		 * Tell other nodes
+		 */
+		send_shutdown();
+
+		res_lib_cfg_tryshutdown.header.size = sizeof(struct res_lib_cfg_tryshutdown);
+		res_lib_cfg_tryshutdown.header.id = MESSAGE_RES_CFG_TRYSHUTDOWN;
+		res_lib_cfg_tryshutdown.header.error = CS_OK;
+		api->ipc_conn_send_response(conn, &res_lib_cfg_tryshutdown,
+					    sizeof(res_lib_cfg_tryshutdown));
+
+		LEAVE();
+		return;
+	}
+
+	/*
+	 * Shutdown in progress, return an error
+	 */
+	if (shutdown_con) {
+		struct res_lib_cfg_tryshutdown res_lib_cfg_tryshutdown;
+
+		res_lib_cfg_tryshutdown.header.size = sizeof(struct res_lib_cfg_tryshutdown);
+		res_lib_cfg_tryshutdown.header.id = MESSAGE_RES_CFG_TRYSHUTDOWN;
+		res_lib_cfg_tryshutdown.header.error = CS_ERR_EXIST;
+
+		api->ipc_conn_send_response(conn, &res_lib_cfg_tryshutdown,
+					    sizeof(res_lib_cfg_tryshutdown));
+
+
+		LEAVE();
+
+		return;
+	}
+
+	ci->conn = conn;
+	shutdown_con = (struct cfg_info *)api->ipc_private_data_get (conn);
+	shutdown_flags = req_lib_cfg_tryshutdown->flags;
+	shutdown_yes = 0;
+	shutdown_no = 0;
+
+	/*
+	 * Count the number of listeners
+	 */
+	shutdown_expected = 0;
+
+	for (iter = trackers_list.next; iter != &trackers_list; iter = iter->next) {
+		struct cfg_info *ci = list_entry(iter, struct cfg_info, list);
+		ci->shutdown_reply = SHUTDOWN_REPLY_UNKNOWN;
+		shutdown_expected++;
+	}
+
+	/*
+	 * If no-one is listening for events then we can just go down now
+	 */
+	if (shutdown_expected == 0) {
+		send_shutdown();
+		LEAVE();
+		return;
+	}
+	else {
+		unsigned int cfg_handle;
+		unsigned int find_handle;
+		char *timeout_str;
+		unsigned int shutdown_timeout = DEFAULT_SHUTDOWN_TIMEOUT;
+
+		/*
+		 * Look for a shutdown timeout in objdb
+		 */
+		api->object_find_create(OBJECT_PARENT_HANDLE, "cfg", strlen("cfg"), &find_handle);
+		api->object_find_next(find_handle, &cfg_handle);
+		api->object_find_destroy(find_handle);
+
+		if (cfg_handle) {
+			if ( !api->object_key_get(cfg_handle,
+						  "shutdown_timeout",
+						  strlen("shutdown_timeout"),
+						  (void *)&timeout_str,
+						  NULL)) {
+				shutdown_timeout = atoi(timeout_str);
+			}
+		}
+
+		/*
+		 * Start the timer. If we don't get a full set of replies before this goes
+		 * off we'll cancel the shutdown
+		 */
+		api->timer_add_duration((unsigned long long)shutdown_timeout*1000000000, NULL,
+					shutdown_timer_fn, &shutdown_timer);
+
+		/*
+		 * Tell the users we would like to shut down
+		 */
+		send_test_shutdown(NULL, CS_OK);
+	}
+
+	/*
+	 * We don't sent a reply to the caller here.
+	 * We send it when we know if we can shut down or not
+	 */
+
+	LEAVE();
+}
+
+static void message_handler_req_lib_cfg_replytoshutdown (
+	void *conn,
+	void *msg)
+{
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+	struct req_lib_cfg_replytoshutdown *req_lib_cfg_replytoshutdown = (struct req_lib_cfg_replytoshutdown *)msg;
+
+	ENTER();
+	if (!shutdown_con) {
+		LEAVE();
+		return;
+	}
+
+	if (req_lib_cfg_replytoshutdown->response) {
+		shutdown_yes++;
+		ci->shutdown_reply = SHUTDOWN_REPLY_YES;
+	}
+	else {
+		shutdown_no++;
+		ci->shutdown_reply = SHUTDOWN_REPLY_NO;
+	}
+	check_shutdown_status();
+	LEAVE();
+}
+
+static void message_handler_req_lib_cfg_get_node_addrs (void *conn, void *msg)
+{
+	struct totem_ip_address node_ifs[INTERFACE_MAX];
+	char buf[PIPE_BUF];
+	char **status;
+	unsigned int num_interfaces = 0;
+	int ret = 0;
+	int i;
+	struct req_lib_cfg_get_node_addrs *req_lib_cfg_get_node_addrs = (struct req_lib_cfg_get_node_addrs *)msg;
+	struct res_lib_cfg_get_node_addrs *res_lib_cfg_get_node_addrs = (struct res_lib_cfg_get_node_addrs *)buf;
+
+	if (req_lib_cfg_get_node_addrs->nodeid == 0)
+		req_lib_cfg_get_node_addrs->nodeid = api->totem_nodeid_get();
+
+	api->totem_ifaces_get(req_lib_cfg_get_node_addrs->nodeid, node_ifs, &status, &num_interfaces);
+
+	res_lib_cfg_get_node_addrs->header.size = sizeof(struct res_lib_cfg_get_node_addrs) + (num_interfaces * TOTEMIP_ADDRLEN);
+	res_lib_cfg_get_node_addrs->header.id = MESSAGE_RES_CFG_GET_NODE_ADDRS;
+	res_lib_cfg_get_node_addrs->header.error = ret;
+	res_lib_cfg_get_node_addrs->num_addrs = num_interfaces;
+	if (num_interfaces) {
+		res_lib_cfg_get_node_addrs->family = node_ifs[0].family;
+		for (i = 0; i<num_interfaces; i++) {
+			memcpy(&res_lib_cfg_get_node_addrs->addrs[i][0], node_ifs[i].addr, TOTEMIP_ADDRLEN);
+		}
+	}
+	else {
+		res_lib_cfg_get_node_addrs->header.error = CS_ERR_NOT_EXIST;
+	}
+	api->ipc_conn_send_response(conn, res_lib_cfg_get_node_addrs, res_lib_cfg_get_node_addrs->header.size);
 }
diff -Naurd corosync-0.92/services/confdb.c corosync-trunk/services/confdb.c
--- corosync-0.92/services/confdb.c	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/services/confdb.c	2009-01-23 16:41:06.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Red Hat, Inc.
+ * Copyright (c) 2008-2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -38,7 +38,7 @@
 #include <errno.h>
 #include <unistd.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/cfg.h>
 #include <corosync/list.h>
 #include <corosync/queue.h>
@@ -106,103 +106,103 @@
 		.lib_handler_fn				= message_handler_req_lib_confdb_object_create,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_OBJECT_CREATE,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 1 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_object_destroy,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_OBJECT_DESTROY,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 2 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_object_find,
 		.response_size				= sizeof (struct res_lib_confdb_object_find),
 		.response_id				= MESSAGE_RES_CONFDB_OBJECT_FIND,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 3 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_key_create,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_KEY_CREATE,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 4 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_key_get,
 		.response_size				= sizeof (struct res_lib_confdb_key_get),
 		.response_id				= MESSAGE_RES_CONFDB_KEY_GET,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 5 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_key_replace,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_KEY_REPLACE,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 6 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_key_delete,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_KEY_DELETE,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 7 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_object_iter,
 		.response_size				= sizeof (struct res_lib_confdb_object_iter),
 		.response_id				= MESSAGE_RES_CONFDB_OBJECT_ITER,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 8 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_object_parent_get,
 		.response_size				= sizeof (struct res_lib_confdb_object_parent_get),
 		.response_id				= MESSAGE_RES_CONFDB_OBJECT_PARENT_GET,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 9 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_key_iter,
 		.response_size				= sizeof (struct res_lib_confdb_key_iter),
 		.response_id				= MESSAGE_RES_CONFDB_KEY_ITER,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 10 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_track_start,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_TRACK_START,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 11 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_track_stop,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_TRACK_STOP,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 12 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_write,
 		.response_size				= sizeof (struct res_lib_confdb_write),
 		.response_id				= MESSAGE_RES_CONFDB_WRITE,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 13 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_reload,
 		.response_size				= sizeof (struct res_lib_confdb_reload),
 		.response_id				= MESSAGE_RES_CONFDB_RELOAD,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 14 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_object_find_destroy,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 15 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_key_increment,
 		.response_size				= sizeof (struct res_lib_confdb_key_incdec),
 		.response_id				= MESSAGE_RES_CONFDB_KEY_INCREMENT,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 16 */
 		.lib_handler_fn				= message_handler_req_lib_confdb_key_decrement,
 		.response_size				= sizeof (struct res_lib_confdb_key_incdec),
 		.response_id				= MESSAGE_RES_CONFDB_KEY_DECREMENT,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 };
 
@@ -211,7 +211,8 @@
 	.name				        = "corosync cluster config database access v1.01",
 	.id					= CONFDB_SERVICE,
 	.private_data_size			= 0,
-	.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
+	.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
+	.allow_inquorate			= CS_LIB_ALLOW_INQUORATE,
 	.lib_init_fn				= confdb_lib_init_fn,
 	.lib_exit_fn				= confdb_lib_exit_fn,
 	.lib_engine				= confdb_lib_engine,
@@ -279,6 +280,7 @@
 	api->object_track_stop(confdb_notify_lib_of_key_change,
 						   confdb_notify_lib_of_new_object,
 						   confdb_notify_lib_of_destroyed_object,
+						   NULL,
 						   api->ipc_conn_partner_get (conn));
 	return (0);
 }
@@ -288,13 +290,13 @@
 	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;
+	int ret = CS_OK;
 
 	if (api->object_create(req_lib_confdb_object_create->parent_object_handle,
 					&object_handle,
 					req_lib_confdb_object_create->object_name.value,
 					req_lib_confdb_object_create->object_name.length))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res_lib_confdb_object_create.object_handle = object_handle;
 	res_lib_confdb_object_create.header.size = sizeof(res_lib_confdb_object_create);
@@ -307,10 +309,10 @@
 {
 	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;
+	int ret = CS_OK;
 
 	if (api->object_destroy(req_lib_confdb_object_destroy->object_handle))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY;
@@ -322,12 +324,10 @@
 {
 	struct req_lib_confdb_object_find_destroy *req_lib_confdb_object_find_destroy = (struct req_lib_confdb_object_find_destroy *)message;
 	mar_res_header_t res;
-	int ret = SA_AIS_OK;
-
-	log_printf(LOG_LEVEL_DEBUG, "object_find_destroy for conn=%p, %d\n", conn, req_lib_confdb_object_find_destroy->find_handle);
+	int ret = CS_OK;
 
 	if (api->object_find_destroy(req_lib_confdb_object_find_destroy->find_handle))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_CONFDB_OBJECT_FIND_DESTROY;
@@ -340,14 +340,14 @@
 {
 	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;
+	int ret = CS_OK;
 
 	if (api->object_key_create(req_lib_confdb_key_create->object_handle,
 					    req_lib_confdb_key_create->key_name.value,
 					    req_lib_confdb_key_create->key_name.length,
 					    req_lib_confdb_key_create->value.value,
 					    req_lib_confdb_key_create->value.length))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_CONFDB_KEY_CREATE;
@@ -361,14 +361,14 @@
 	struct res_lib_confdb_key_get res_lib_confdb_key_get;
 	int value_len;
 	void *value;
-	int ret = SA_AIS_OK;
+	int ret = CS_OK;
 
 	if (api->object_key_get(req_lib_confdb_key_get->parent_object_handle,
 					 req_lib_confdb_key_get->key_name.value,
 					 req_lib_confdb_key_get->key_name.length,
 					 &value,
 					 &value_len))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 	else {
 		memcpy(res_lib_confdb_key_get.value.value, value, value_len);
 		res_lib_confdb_key_get.value.length = value_len;
@@ -384,15 +384,13 @@
 {
 	struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message;
 	struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
-	int value_len;
-	void *value;
-	int ret = SA_AIS_OK;
+	int ret = CS_OK;
 
 	if (api->object_key_increment(req_lib_confdb_key_get->parent_object_handle,
 				      req_lib_confdb_key_get->key_name.value,
 				      req_lib_confdb_key_get->key_name.length,
 				      &res_lib_confdb_key_incdec.value))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec);
 	res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_INCREMENT;
@@ -404,15 +402,13 @@
 {
 	struct req_lib_confdb_key_get *req_lib_confdb_key_get = (struct req_lib_confdb_key_get *)message;
 	struct res_lib_confdb_key_incdec res_lib_confdb_key_incdec;
-	int value_len;
-	void *value;
-	int ret = SA_AIS_OK;
+	int ret = CS_OK;
 
 	if (api->object_key_decrement(req_lib_confdb_key_get->parent_object_handle,
 				      req_lib_confdb_key_get->key_name.value,
 				      req_lib_confdb_key_get->key_name.length,
 				      &res_lib_confdb_key_incdec.value))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res_lib_confdb_key_incdec.header.size = sizeof(res_lib_confdb_key_incdec);
 	res_lib_confdb_key_incdec.header.id = MESSAGE_RES_CONFDB_KEY_DECREMENT;
@@ -424,7 +420,7 @@
 {
 	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;
+	int ret = CS_OK;
 
 	if (api->object_key_replace(req_lib_confdb_key_replace->object_handle,
 					     req_lib_confdb_key_replace->key_name.value,
@@ -433,7 +429,7 @@
 					     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;
+		ret = CS_ERR_ACCESS;
 
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_CONFDB_KEY_REPLACE;
@@ -445,14 +441,14 @@
 {
 	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;
+	int ret = CS_OK;
 
 	if (api->object_key_delete(req_lib_confdb_key_delete->object_handle,
 					    req_lib_confdb_key_delete->key_name.value,
 					    req_lib_confdb_key_delete->key_name.length,
 					    req_lib_confdb_key_delete->value.value,
 					    req_lib_confdb_key_delete->value.length))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_CONFDB_KEY_DELETE;
@@ -465,11 +461,11 @@
 	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;
+	int ret = CS_OK;
 
 	if (api->object_parent_get(req_lib_confdb_object_parent_get->object_handle,
 					    &object_handle))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res_lib_confdb_object_parent_get.parent_object_handle = object_handle;
 	res_lib_confdb_object_parent_get.header.size = sizeof(res_lib_confdb_object_parent_get);
@@ -487,7 +483,7 @@
 	int key_name_len;
 	void *value;
 	int value_len;
-	int ret = SA_AIS_OK;
+	int ret = CS_OK;
 
 	if (api->object_key_iter_from(req_lib_confdb_key_iter->parent_object_handle,
 					       req_lib_confdb_key_iter->next_entry,
@@ -495,7 +491,7 @@
 					       &key_name_len,
 					       &value,
 					       &value_len))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 	else {
 		memcpy(res_lib_confdb_key_iter.key_name.value, key_name, key_name_len);
 		memcpy(res_lib_confdb_key_iter.value.value, value, value_len);
@@ -514,7 +510,7 @@
 	struct req_lib_confdb_object_iter *req_lib_confdb_object_iter = (struct req_lib_confdb_object_iter *)message;
 	struct res_lib_confdb_object_iter res_lib_confdb_object_iter;
 	int object_name_len;
-	int ret = SA_AIS_OK;
+	int ret = CS_OK;
 
 	if (!req_lib_confdb_object_iter->find_handle) {
 		api->object_find_create(req_lib_confdb_object_iter->parent_object_handle,
@@ -525,8 +521,10 @@
 		res_lib_confdb_object_iter.find_handle = req_lib_confdb_object_iter->find_handle;
 
 	if (api->object_find_next(res_lib_confdb_object_iter.find_handle,
-				  &res_lib_confdb_object_iter.object_handle))
-		ret = SA_AIS_ERR_ACCESS;
+				  &res_lib_confdb_object_iter.object_handle)) {
+		ret = CS_ERR_ACCESS;
+		api->object_find_destroy(res_lib_confdb_object_iter.find_handle);
+	}
 	else {
 		api->object_name_get(res_lib_confdb_object_iter.object_handle,
 				     (char *)res_lib_confdb_object_iter.object_name.value,
@@ -545,7 +543,7 @@
 {
 	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;
+	int ret = CS_OK;
 
 	if (!req_lib_confdb_object_find->find_handle) {
 		api->object_find_create(req_lib_confdb_object_find->parent_object_handle,
@@ -557,8 +555,10 @@
 		res_lib_confdb_object_find.find_handle = req_lib_confdb_object_find->find_handle;
 
 	if (api->object_find_next(res_lib_confdb_object_find.find_handle,
-				  &res_lib_confdb_object_find.object_handle))
-		ret = SA_AIS_ERR_ACCESS;
+				  &res_lib_confdb_object_find.object_handle)) {
+		ret = CS_ERR_ACCESS;
+		api->object_find_destroy(res_lib_confdb_object_find.find_handle);
+	}
 
 	res_lib_confdb_object_find.header.size = sizeof(res_lib_confdb_object_find);
 	res_lib_confdb_object_find.header.id = MESSAGE_RES_CONFDB_OBJECT_FIND;
@@ -571,11 +571,11 @@
 static void message_handler_req_lib_confdb_write (void *conn, void *message)
 {
 	struct res_lib_confdb_write res_lib_confdb_write;
-	int ret = SA_AIS_OK;
+	int ret = CS_OK;
 	char *error_string = NULL;
 
 	if (api->object_write_config(&error_string))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res_lib_confdb_write.header.size = sizeof(res_lib_confdb_write);
 	res_lib_confdb_write.header.id = MESSAGE_RES_CONFDB_WRITE;
@@ -593,11 +593,11 @@
 {
 	struct req_lib_confdb_reload *req_lib_confdb_reload = (struct req_lib_confdb_reload *)message;
 	struct res_lib_confdb_reload res_lib_confdb_reload;
-	int ret = SA_AIS_OK;
+	int ret = CS_OK;
 	char *error_string = NULL;
 
 	if (api->object_reload_config(req_lib_confdb_reload->flush, &error_string))
-		ret = SA_AIS_ERR_ACCESS;
+		ret = CS_ERR_ACCESS;
 
 	res_lib_confdb_reload.header.size = sizeof(res_lib_confdb_reload);
 	res_lib_confdb_reload.header.id = MESSAGE_RES_CONFDB_RELOAD;
@@ -624,7 +624,7 @@
 
 	res.header.size = sizeof(res);
 	res.header.id = MESSAGE_RES_CONFDB_KEY_CHANGE_CALLBACK;
-	res.header.error = SA_AIS_OK;
+	res.header.error = CS_OK;
 // handle & type
 	res.change_type = change_type;
 	res.parent_object_handle = parent_object_handle;
@@ -651,7 +651,7 @@
 
 	res.header.size = sizeof(res);
 	res.header.id = MESSAGE_RES_CONFDB_OBJECT_CREATE_CALLBACK;
-	res.header.error = SA_AIS_OK;
+	res.header.error = CS_OK;
 	res.parent_object_handle = parent_object_handle;
 	res.object_handle = object_handle;
 	memcpy(res.name.value, name_pt, name_len);
@@ -668,7 +668,7 @@
 
 	res.header.size = sizeof(res);
 	res.header.id = MESSAGE_RES_CONFDB_OBJECT_DESTROY_CALLBACK;
-	res.header.error = SA_AIS_OK;
+	res.header.error = CS_OK;
 	res.parent_object_handle = parent_object_handle;
 	memcpy(res.name.value, name_pt, name_len);
 	res.name.length = name_len;
@@ -686,10 +686,11 @@
 							confdb_notify_lib_of_key_change,
 							confdb_notify_lib_of_new_object,
 							confdb_notify_lib_of_destroyed_object,
+							NULL,
 							api->ipc_conn_partner_get (conn));
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_CONFDB_TRACK_START;
-	res.error = SA_AIS_OK;
+	res.error = CS_OK;
 	api->ipc_conn_send_response(conn, &res, sizeof(res));
 }
 
@@ -700,11 +701,12 @@
 	api->object_track_stop(confdb_notify_lib_of_key_change,
 						   confdb_notify_lib_of_new_object,
 						   confdb_notify_lib_of_destroyed_object,
+						   NULL,
 						   api->ipc_conn_partner_get (conn));
 
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_CONFDB_TRACK_STOP;
-	res.error = SA_AIS_OK;
+	res.error = CS_OK;
 	api->ipc_conn_send_response(conn, &res, sizeof(res));
 }
 
diff -Naurd corosync-0.92/services/cpg.c corosync-trunk/services/cpg.c
--- corosync-0.92/services/cpg.c	2008-09-17 21:15:00.000000000 +0200
+++ corosync-trunk/services/cpg.c	2009-01-08 07:29:16.000000000 +0100
@@ -51,7 +51,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/cfg.h>
 #include <corosync/list.h>
 #include <corosync/queue.h>
@@ -99,7 +99,7 @@
 	void *conn;
 	void *trackerconn;
 	struct group_info *group;
-	enum corosync_flow_control_state flow_control_state;
+	enum cs_flow_control_state flow_control_state;
 	struct list_head list; /* on the group_info members list */
 };
 
@@ -189,49 +189,49 @@
 		.lib_handler_fn				= message_handler_req_lib_cpg_join,
 		.response_size				= sizeof (struct res_lib_cpg_join),
 		.response_id				= MESSAGE_RES_CPG_JOIN,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 1 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_leave,
 		.response_size				= sizeof (struct res_lib_cpg_leave),
 		.response_id				= MESSAGE_RES_CPG_LEAVE,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 2 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_mcast,
 		.response_size				= sizeof (struct res_lib_cpg_mcast),
 		.response_id				= MESSAGE_RES_CPG_MCAST,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 3 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_membership,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CPG_MEMBERSHIP,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 4 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_trackstart,
 		.response_size				= sizeof (struct res_lib_cpg_trackstart),
 		.response_id				= MESSAGE_RES_CPG_TRACKSTART,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 5 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_trackstop,
 		.response_size				= sizeof (struct res_lib_cpg_trackstart),
 		.response_id				= MESSAGE_RES_CPG_TRACKSTOP,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 6 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_local_get,
 		.response_size				= sizeof (struct res_lib_cpg_local_get),
 		.response_id				= MESSAGE_RES_CPG_LOCAL_GET,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 7 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_groups_get,
 		.response_size				= sizeof (struct res_lib_cpg_groups_get),
 		.response_id				= MESSAGE_RES_CPG_GROUPS_GET,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	}
 };
 
@@ -263,7 +263,7 @@
 	.name				        = "corosync cluster closed process group service v1.01",
 	.id					= CPG_SERVICE,
 	.private_data_size			= sizeof (struct process_info),
-	.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED,
+	.flow_control				= CS_LIB_FLOW_CONTROL_REQUIRED,
 	.lib_init_fn				= cpg_lib_init_fn,
 	.lib_exit_fn				= cpg_lib_exit_fn,
 	.lib_engine				= cpg_lib_engine,
@@ -395,7 +395,7 @@
 		sizeof(mar_cpg_address_t) * (count + left_list_entries + joined_list_entries);
 	buf = alloca(size);
 	if (!buf)
-		return SA_AIS_ERR_NO_SPACE;
+		return CS_ERR_NO_SPACE;
 
 	res = (struct res_lib_cpg_confchg_callback *)buf;
 	res->joined_list_entries = joined_list_entries;
@@ -404,6 +404,7 @@
 
 	res->header.size = size;
 	res->header.id = id;
+	res->header.error = CS_OK;
 	memcpy(&res->group_name, &gi->group_name, sizeof(mar_cpg_name_t));
 
 	/* Build up the message */
@@ -453,7 +454,7 @@
 		}
 	}
 
-	return SA_AIS_OK;
+	return CS_OK;
 }
 
 static void remove_group(struct group_info *gi)
@@ -571,6 +572,8 @@
 					return;
 				}
 			}
+			if (!buf)
+				continue;
 
 			res = (struct res_lib_cpg_groups_get_callback *)buf;
 			retgi = res->member_list;
@@ -694,7 +697,7 @@
 	struct memb_ring_id *ring_id)
 {
 	int i;
-	uint32_t lowest_nodeid = 0xffffff;
+	uint32_t lowest_nodeid = 0xffffffff;
 	struct iovec req_exec_cpg_iovec;
 
 	/* We don't send the library joinlist in here because it can end up
@@ -736,7 +739,7 @@
 
 static void cpg_flow_control_state_set_fn (
 	void *context,
-	enum corosync_flow_control_state flow_control_state)
+	enum cs_flow_control_state flow_control_state)
 {
 	struct res_lib_cpg_flowcontrol_callback res_lib_cpg_flowcontrol_callback;
 	struct process_info *process_info = (struct process_info *)context;
@@ -1105,19 +1108,19 @@
 	struct process_info *pi = (struct process_info *)api->ipc_private_data_get (conn);
 	struct res_lib_cpg_join res_lib_cpg_join;
 	struct group_info *gi;
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 
 	log_printf(LOG_LEVEL_DEBUG, "got join request on %p, pi=%p, pi->pid=%d\n", conn, pi, pi->pid);
 
 	/* Already joined on this conn */
 	if (pi->pid) {
-		error = SA_AIS_ERR_INVALID_PARAM;
+		error = CS_ERR_INVALID_PARAM;
 		goto join_err;
 	}
 
 	gi = get_group(&req_lib_cpg_join->group_name);
 	if (!gi) {
-		error = SA_AIS_ERR_NO_SPACE;
+		error = CS_ERR_NO_SPACE;
 		goto join_err;
 	}
 
@@ -1151,12 +1154,12 @@
 	struct process_info *pi = (struct process_info *)api->ipc_private_data_get (conn);
 	struct res_lib_cpg_leave res_lib_cpg_leave;
 	struct group_info *gi;
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 
 	log_printf(LOG_LEVEL_DEBUG, "got leave request on %p\n", conn);
 
 	if (!pi || !pi->pid || !pi->group) {
-		error = SA_AIS_ERR_INVALID_PARAM;
+		error = CS_ERR_INVALID_PARAM;
 		goto leave_ret;
 	}
 	gi = pi->group;
@@ -1198,7 +1201,7 @@
 	if (!gi) {
 		res_lib_cpg_mcast.header.size = sizeof(res_lib_cpg_mcast);
 		res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_MCAST;
-		res_lib_cpg_mcast.header.error = SA_AIS_ERR_ACCESS; /* TODO Better error code ?? */
+		res_lib_cpg_mcast.header.error = CS_ERR_ACCESS; /* TODO Better error code ?? */
 		res_lib_cpg_mcast.flow_control_state = CPG_FLOW_CONTROL_DISABLED;
 		api->ipc_conn_send_response(conn, &res_lib_cpg_mcast,
 			sizeof(res_lib_cpg_mcast));
@@ -1225,7 +1228,7 @@
 
 	res_lib_cpg_mcast.header.size = sizeof(res_lib_cpg_mcast);
 	res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_MCAST;
-	res_lib_cpg_mcast.header.error = SA_AIS_OK;
+	res_lib_cpg_mcast.header.error = CS_OK;
 	res_lib_cpg_mcast.flow_control_state = pi->flow_control_state;
 	api->ipc_conn_send_response(conn, &res_lib_cpg_mcast,
 		sizeof(res_lib_cpg_mcast));
@@ -1240,7 +1243,7 @@
 		mar_res_header_t res;
 		res.size = sizeof(res);
 		res.id = MESSAGE_RES_CPG_MEMBERSHIP;
-		res.error = SA_AIS_ERR_ACCESS; /* TODO Better error code */
+		res.error = CS_ERR_ACCESS; /* TODO Better error code */
 		api->ipc_conn_send_response(conn, &res, sizeof(res));
 		return;
 	}
@@ -1256,13 +1259,13 @@
 	struct group_info *gi;
 	struct process_info *otherpi;
 	void *otherconn;
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 
 	log_printf(LOG_LEVEL_DEBUG, "got trackstart request on %p\n", conn);
 
 	gi = get_group(&req_lib_cpg_trackstart->group_name);
 	if (!gi) {
-		error = SA_AIS_ERR_NO_SPACE;
+		error = CS_ERR_NO_SPACE;
 		goto tstart_ret;
 	}
 
@@ -1274,7 +1277,7 @@
 tstart_ret:
 	res_lib_cpg_trackstart.header.size = sizeof(res_lib_cpg_trackstart);
 	res_lib_cpg_trackstart.header.id = MESSAGE_RES_CPG_TRACKSTART;
-	res_lib_cpg_trackstart.header.error = SA_AIS_OK;
+	res_lib_cpg_trackstart.header.error = CS_OK;
 	api->ipc_conn_send_response(conn, &res_lib_cpg_trackstart, sizeof(res_lib_cpg_trackstart));
 }
 
@@ -1285,13 +1288,13 @@
 	struct process_info *otherpi;
 	void *otherconn;
 	struct group_info *gi;
-	SaAisErrorT error = SA_AIS_OK;
+	cs_error_t error = CS_OK;
 
 	log_printf(LOG_LEVEL_DEBUG, "got trackstop request on %p\n", conn);
 
 	gi = get_group(&req_lib_cpg_trackstop->group_name);
 	if (!gi) {
-		error = SA_AIS_ERR_NO_SPACE;
+		error = CS_ERR_NO_SPACE;
 		goto tstop_ret;
 	}
 
@@ -1303,7 +1306,7 @@
 tstop_ret:
 	res_lib_cpg_trackstop.header.size = sizeof(res_lib_cpg_trackstop);
 	res_lib_cpg_trackstop.header.id = MESSAGE_RES_CPG_TRACKSTOP;
-	res_lib_cpg_trackstop.header.error = SA_AIS_OK;
+	res_lib_cpg_trackstop.header.error = CS_OK;
 	api->ipc_conn_send_response(conn, &res_lib_cpg_trackstop.header, sizeof(res_lib_cpg_trackstop));
 }
 
@@ -1313,7 +1316,7 @@
 
 	res_lib_cpg_local_get.header.size = sizeof(res_lib_cpg_local_get);
 	res_lib_cpg_local_get.header.id = MESSAGE_RES_CPG_LOCAL_GET;
-	res_lib_cpg_local_get.header.error = SA_AIS_OK;
+	res_lib_cpg_local_get.header.error = CS_OK;
 	res_lib_cpg_local_get.local_nodeid = api->totem_nodeid_get ();
 
 	api->ipc_conn_send_response(conn, &res_lib_cpg_local_get,
@@ -1326,7 +1329,7 @@
 
 	res_lib_cpg_groups_get.header.size = sizeof(res_lib_cpg_groups_get);
 	res_lib_cpg_groups_get.header.id = MESSAGE_RES_CPG_GROUPS_GET;
-	res_lib_cpg_groups_get.header.error = SA_AIS_OK;
+	res_lib_cpg_groups_get.header.error = CS_OK;
 	res_lib_cpg_groups_get.num_groups = count_groups();
 
 	api->ipc_conn_send_response(conn, &res_lib_cpg_groups_get,
diff -Naurd corosync-0.92/services/evs.c corosync-trunk/services/evs.c
--- corosync-0.92/services/evs.c	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/services/evs.c	2008-11-06 22:49:07.000000000 +0100
@@ -49,7 +49,7 @@
 #include <arpa/inet.h>
 
 #include <corosync/swab.h>
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/ipc_gen.h>
 #include <corosync/lcr/lcr_comp.h>
 #include <corosync/engine/coroapi.h>
@@ -104,31 +104,31 @@
 		.lib_handler_fn				= message_handler_req_evs_join,
 		.response_size				= sizeof (struct res_lib_evs_join),
 		.response_id				= MESSAGE_RES_EVS_JOIN,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 1 */
 		.lib_handler_fn				= message_handler_req_evs_leave,
 		.response_size				= sizeof (struct res_lib_evs_leave),
 		.response_id				= MESSAGE_RES_EVS_LEAVE,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	},
 	{ /* 2 */
 		.lib_handler_fn				= message_handler_req_evs_mcast_joined,
 		.response_size				= sizeof (struct res_lib_evs_mcast_joined),
 		.response_id				= MESSAGE_RES_EVS_MCAST_JOINED,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 3 */
 		.lib_handler_fn				= message_handler_req_evs_mcast_groups,
 		.response_size				= sizeof (struct res_lib_evs_mcast_groups),
 		.response_id				= MESSAGE_RES_EVS_MCAST_GROUPS,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_REQUIRED
 	},
 	{ /* 4 */
 		.lib_handler_fn				= message_handler_req_evs_membership_get,
 		.response_size				= sizeof (struct res_lib_evs_membership_get),
 		.response_id				= MESSAGE_RES_EVS_MEMBERSHIP_GET,
-		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	}
 };
 
@@ -144,7 +144,7 @@
 	.name			= "corosync extended virtual synchrony service",
 	.id			= EVS_SERVICE,
 	.private_data_size	= sizeof (struct evs_pd),
-	.flow_control		= COROSYNC_LIB_FLOW_CONTROL_REQUIRED, 
+	.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED, 
 	.lib_init_fn		= evs_lib_init_fn,
 	.lib_exit_fn		= evs_lib_exit_fn,
 	.lib_engine		= evs_lib_engine,
@@ -223,7 +223,7 @@
 	 */
 	res_evs_confchg_callback.header.size = sizeof (struct res_evs_confchg_callback);
 	res_evs_confchg_callback.header.id = MESSAGE_RES_EVS_CONFCHG_CALLBACK;
-	res_evs_confchg_callback.header.error = SA_AIS_OK;
+	res_evs_confchg_callback.header.error = CS_OK;
 
 	memcpy (res_evs_confchg_callback.member_list,
 		member_list, member_list_entries * sizeof(*member_list));
@@ -276,21 +276,21 @@
 
 static void message_handler_req_evs_join (void *conn, void *msg)
 {
-	evs_error_t error = EVS_OK;
+	cs_error_t error = CS_OK;
 	struct req_lib_evs_join *req_lib_evs_join = (struct req_lib_evs_join *)msg;
 	struct res_lib_evs_join res_lib_evs_join;
 	void *addr;
 	struct evs_pd *evs_pd = (struct evs_pd *)api->ipc_private_data_get (conn);
 
 	if (req_lib_evs_join->group_entries > 50) {
-		error = EVS_ERR_TOO_MANY_GROUPS;
+		error = CS_ERR_TOO_MANY_GROUPS;
 		goto exit_error;
 	}
 
 	addr = realloc (evs_pd->groups, sizeof (struct evs_group) * 
 		(evs_pd->group_entries + req_lib_evs_join->group_entries));
 	if (addr == NULL) {
-		error = SA_AIS_ERR_NO_MEMORY;
+		error = CS_ERR_NO_MEMORY;
 		goto exit_error;
 	}
 	evs_pd->groups = addr;
@@ -314,7 +314,7 @@
 {
 	struct req_lib_evs_leave *req_lib_evs_leave = (struct req_lib_evs_leave *)msg;
 	struct res_lib_evs_leave res_lib_evs_leave;
-	evs_error_t error = EVS_OK;
+	cs_error_t error = CS_OK;
 	int error_index;
 	int i, j;
 	int found;
@@ -342,7 +342,7 @@
 			}
 		}
 		if (found == 0) {
-			error = EVS_ERR_NOT_EXIST;
+			error = CS_ERR_NOT_EXIST;
 			error_index = i;
 			break;
 		}
@@ -358,7 +358,7 @@
 
 static void message_handler_req_evs_mcast_joined (void *conn, void *msg)
 {
-	evs_error_t error = EVS_ERR_TRY_AGAIN;
+	cs_error_t error = CS_ERR_TRY_AGAIN;
 	struct req_lib_evs_mcast_joined *req_lib_evs_mcast_joined = (struct req_lib_evs_mcast_joined *)msg;
 	struct res_lib_evs_mcast_joined res_lib_evs_mcast_joined;
 	struct iovec req_exec_evs_mcast_iovec[3];
@@ -388,7 +388,7 @@
 	res = api->totem_mcast (req_exec_evs_mcast_iovec, 3, TOTEM_AGREED);
 		// TODO
 	if (res == 0) {
-		error = EVS_OK;
+		error = CS_OK;
 	}
 
 	res_lib_evs_mcast_joined.header.size = sizeof (struct res_lib_evs_mcast_joined);
@@ -401,7 +401,7 @@
 
 static void message_handler_req_evs_mcast_groups (void *conn, void *msg)
 {
-	evs_error_t error = EVS_ERR_TRY_AGAIN;
+	cs_error_t error = CS_ERR_TRY_AGAIN;
 	struct req_lib_evs_mcast_groups *req_lib_evs_mcast_groups = (struct req_lib_evs_mcast_groups *)msg;
 	struct res_lib_evs_mcast_groups res_lib_evs_mcast_groups;
 	struct iovec req_exec_evs_mcast_iovec[3];
@@ -434,7 +434,7 @@
 	send_ok = api->totem_send_ok (req_exec_evs_mcast_iovec, 3);
 	res = api->totem_mcast (req_exec_evs_mcast_iovec, 3, TOTEM_AGREED);
 	if (res == 0) {
-		error = EVS_OK;
+		error = CS_OK;
 	}
 
 	res_lib_evs_mcast_groups.header.size = sizeof (struct res_lib_evs_mcast_groups);
@@ -451,7 +451,7 @@
 
 	res_lib_evs_membership_get.header.size = sizeof (struct res_lib_evs_membership_get);
 	res_lib_evs_membership_get.header.id = MESSAGE_RES_EVS_MEMBERSHIP_GET;
-	res_lib_evs_membership_get.header.error = EVS_OK;
+	res_lib_evs_membership_get.header.error = CS_OK;
 	res_lib_evs_membership_get.local_nodeid = api->totem_nodeid_get ();
 	memcpy (&res_lib_evs_membership_get.member_list,
 		&res_evs_confchg_callback.member_list,
@@ -488,7 +488,7 @@
 	res_evs_deliver_callback.header.size = sizeof (struct res_evs_deliver_callback) +
 		req_exec_evs_mcast->msg_len;
 	res_evs_deliver_callback.header.id = MESSAGE_RES_EVS_DELIVER_CALLBACK;
-	res_evs_deliver_callback.header.error = SA_AIS_OK;
+	res_evs_deliver_callback.header.error = CS_OK;
 	res_evs_deliver_callback.msglen = req_exec_evs_mcast->msg_len;
 
 	msg_addr = (char *)req_exec_evs_mcast + sizeof (struct req_exec_evs_mcast) + 
diff -Naurd corosync-0.92/services/Makefile corosync-trunk/services/Makefile
--- corosync-0.92/services/Makefile	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/services/Makefile	2009-01-26 11:46:08.000000000 +0100
@@ -50,12 +50,12 @@
 endif
 
 # LCR objects
-LCR_SRC = evs.c cfg.c cpg.c confdb.c
-LCR_OBJS = evs.o cfg.o cpg.o confdb.o $(AMF_OBJS)
+LCR_SRC = evs.c cfg.c cpg.c confdb.c pload.c
+LCR_OBJS = evs.o cfg.o cpg.o confdb.o $(AMF_OBJS) pload.o
 
 override CFLAGS += -fPIC
 
-all: service_evs.lcrso service_cfg.lcrso service_cpg.lcrso service_confdb.lcrso
+all: service_evs.lcrso service_cfg.lcrso service_cpg.lcrso service_confdb.lcrso service_pload.lcrso testquorum.lcrso service_votequorum.lcrso
 
 ifeq (${COROSYNC_COMPAT}, DARWIN)
 
@@ -71,6 +71,15 @@
 service_cpg.lcrso: cpg.o
 	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load cpg.o -o $@
 
+service_pload.lcrso: pload.o
+	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load pload.o -o $@
+
+service_votequorum.lcrso: votequorum.o
+	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load votequorum.o -o $@
+
+testquorum.lcrso: testquorum.o
+	$(CC) $(LDFLAGS) -bundle $(LDFLAGS) -bundle_loader ../exec/corosync -bind_at_load testquorum.o -o $@
+
 else
 
 service_evs.lcrso: evs.o
@@ -85,11 +94,23 @@
 service_cpg.lcrso: cpg.o
 	$(CC) -shared -Wl,-soname,service_cpg.lcrso cpg.o -o $@
 
+service_pload.lcrso: pload.o
+	$(CC) -shared -Wl,-soname,service_pload.lcrso pload.o -o $@
+
+service_votequorum.lcrso: votequorum.o
+	$(CC) -shared -Wl,-soname,service_votequorum.lcrso votequorum.o -o $@
+
+testquorum.lcrso: testquorum.o
+	$(CC) -shared -Wl,-soname,testquorum.lcrso testquorum.o -o $@
+
 endif
 
 clean:
 	rm -f *.o *.lcrso 
 
+lint:
+	-splint $(LINT_FLAGS) $(CFLAGS) *.c
+
 depend:
 	makedepend -Y -- $(CFLAGS) $(CPPFLAGS) $(EXEC_SRC) $(TOTEM_SRC) $(LOGSYS_SRC) $(LCR_SRC) > /dev/null 2>&1
 
@@ -104,3 +125,6 @@
 
 cpg.o: cpg.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+testquorum.o: testquorum.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
diff -Naurd corosync-0.92/services/pload.c corosync-trunk/services/pload.c
--- corosync-0.92/services/pload.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/services/pload.c	2008-11-06 22:49:07.000000000 +0100
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include <corosync/swab.h>
+#include <corosync/corotypes.h>
+#include <corosync/ipc_gen.h>
+#include <corosync/lcr/lcr_comp.h>
+#include <corosync/engine/coroapi.h>
+#include <corosync/ipc_pload.h>
+#include <corosync/list.h>
+#include <corosync/engine/logsys.h>
+
+LOGSYS_DECLARE_SUBSYS ("PLOAD", LOG_INFO);
+
+enum pload_exec_message_req_types {
+	MESSAGE_REQ_EXEC_PLOAD_START = 0,
+	MESSAGE_REQ_EXEC_PLOAD_MCAST = 1
+};
+
+/*
+ * Service Interfaces required by service_message_handler struct
+ */
+static int pload_exec_init_fn (
+	struct corosync_api_v1 *corosync_api);
+
+static void pload_confchg_fn (
+	enum totem_configuration_type configuration_type,
+	unsigned int *member_list, int member_list_entries,
+	unsigned int *left_list, int left_list_entries,
+	unsigned int *joined_list, int joined_list_entries,
+	struct memb_ring_id *ring_id);
+
+static void message_handler_req_exec_pload_start (void *msg, unsigned int nodeid);
+
+static void message_handler_req_exec_pload_mcast (void *msg, unsigned int nodeid);
+
+static void req_exec_pload_start_endian_convert (void *msg);
+
+static void req_exec_pload_mcast_endian_convert (void *msg);
+
+static void message_handler_req_pload_start (void *conn, void *msg);
+
+static int pload_lib_init_fn (void *conn);
+
+static int pload_lib_exit_fn (void *conn);
+
+static char buffer[1000000];
+
+static unsigned int msgs_delivered = 0;
+
+static unsigned int msgs_wanted = 0;
+
+static unsigned int msg_size = 0;
+
+static unsigned int msg_code = 1;
+
+static unsigned int msgs_sent = 0;
+
+	
+static struct corosync_api_v1 *api;
+
+struct req_exec_pload_start {
+	mar_req_header_t header;
+	unsigned int msg_code;
+	unsigned int msg_count;
+	unsigned int msg_size;
+	unsigned int time_interval;
+};
+
+struct req_exec_pload_mcast {
+	mar_req_header_t header;
+	unsigned int msg_code;
+};
+
+static struct corosync_lib_handler pload_lib_engine[] =
+{
+	{ /* 0 */
+		.lib_handler_fn		= message_handler_req_pload_start,
+		.response_size		= sizeof (struct res_lib_pload_start),
+		.response_id		= MESSAGE_RES_PLOAD_START,
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	}
+};
+
+static struct corosync_exec_handler pload_exec_engine[] =
+{
+	{
+		.exec_handler_fn 	= message_handler_req_exec_pload_start,
+		.exec_endian_convert_fn	= req_exec_pload_start_endian_convert
+	},
+	{
+		.exec_handler_fn 	= message_handler_req_exec_pload_mcast,
+		.exec_endian_convert_fn	= req_exec_pload_mcast_endian_convert
+	}
+};
+
+struct corosync_service_engine pload_service_engine = {
+	.name			= "corosync profile loading service",
+	.id			= PLOAD_SERVICE,
+	.private_data_size	= 0,
+	.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED, 
+	.lib_init_fn		= pload_lib_init_fn,
+	.lib_exit_fn		= pload_lib_exit_fn,
+	.lib_engine		= pload_lib_engine,
+	.lib_engine_count	= sizeof (pload_lib_engine) / sizeof (struct corosync_lib_handler),
+	.exec_engine		= pload_exec_engine,
+	.exec_engine_count	= sizeof (pload_exec_engine) / sizeof (struct corosync_exec_handler),
+	.confchg_fn		= pload_confchg_fn,
+	.exec_init_fn		= pload_exec_init_fn,
+	.exec_dump_fn		= NULL
+};
+
+static DECLARE_LIST_INIT (confchg_notify);
+
+/*
+ * Dynamic loading descriptor
+ */
+
+static struct corosync_service_engine *pload_get_service_engine_ver0 (void);
+
+static struct corosync_service_engine_iface_ver0 pload_service_engine_iface = {
+	.corosync_get_service_engine_ver0	= pload_get_service_engine_ver0
+};
+
+static struct lcr_iface corosync_pload_ver0[1] = {
+	{
+		.name			= "corosync_pload",
+		.version		= 0,
+		.versions_replace	= 0,
+		.versions_replace_count = 0,
+		.dependencies		= 0,
+		.dependency_count	= 0,
+		.constructor		= NULL,
+		.destructor		= NULL,
+		.interfaces		= NULL,
+	}
+};
+
+static struct lcr_comp pload_comp_ver0 = {
+	.iface_count	= 1,
+	.ifaces		= corosync_pload_ver0
+};
+
+static struct corosync_service_engine *pload_get_service_engine_ver0 (void)
+{
+	return (&pload_service_engine);
+}
+
+__attribute__ ((constructor)) static void pload_comp_register (void) {
+	lcr_interfaces_set (&corosync_pload_ver0[0], &pload_service_engine_iface);
+
+	lcr_component_register (&pload_comp_ver0);
+}
+
+static int pload_exec_init_fn (
+	struct corosync_api_v1 *corosync_api)
+{
+	api = corosync_api;
+
+	return 0;
+}
+
+static void pload_confchg_fn (
+	enum totem_configuration_type configuration_type,
+	unsigned int *member_list, int member_list_entries,
+	unsigned int *left_list, int left_list_entries,
+	unsigned int *joined_list, int joined_list_entries,
+	struct memb_ring_id *ring_id)
+{
+}
+
+static int pload_lib_init_fn (void *conn)
+{
+	return (0);
+}
+
+static int pload_lib_exit_fn (void *conn)
+{
+	return (0);
+}
+
+static void message_handler_req_pload_start (void *conn, void *msg)
+{
+	struct req_lib_pload_start *req_lib_pload_start = (struct req_lib_pload_start *)msg;
+	struct req_exec_pload_start req_exec_pload_start;
+	struct iovec iov;
+
+	req_exec_pload_start.header.id =
+		SERVICE_ID_MAKE (PLOAD_SERVICE, MESSAGE_REQ_EXEC_PLOAD_START);
+	req_exec_pload_start.msg_code = req_lib_pload_start->msg_code;
+	req_exec_pload_start.msg_size = req_lib_pload_start->msg_size;
+	req_exec_pload_start.msg_count = req_lib_pload_start->msg_count;
+	req_exec_pload_start.time_interval = req_lib_pload_start->time_interval;
+	iov.iov_base = &req_exec_pload_start;
+	iov.iov_len = sizeof (struct req_exec_pload_start);
+
+	api->totem_mcast (&iov, 1, TOTEM_AGREED);
+}
+
+static void req_exec_pload_start_endian_convert (void *msg)
+{
+}
+
+static void req_exec_pload_mcast_endian_convert (void *msg)
+{
+}
+
+static int msg_no = 0;
+
+int send_message (enum totem_callback_token_type type, void *arg)
+{
+	struct req_exec_pload_mcast req_exec_pload_mcast;
+	struct iovec iov[2];
+	unsigned int res;
+	int iov_len = 2;
+
+	req_exec_pload_mcast.header.id =
+		SERVICE_ID_MAKE (PLOAD_SERVICE, MESSAGE_REQ_EXEC_PLOAD_MCAST);
+	req_exec_pload_mcast.header.size = sizeof (struct req_exec_pload_mcast) + msg_size;
+
+	iov[0].iov_base = &req_exec_pload_mcast;
+	iov[0].iov_len = sizeof (struct req_exec_pload_mcast);
+	iov[1].iov_base = buffer;
+	iov[1].iov_len = msg_size - sizeof (struct req_exec_pload_mcast);
+	if (iov[1].iov_len < 0) {
+		iov_len = 1;
+	}
+
+	do {
+		res = api->totem_mcast (iov, iov_len, TOTEM_AGREED);
+		if (res == -1) {
+			break;
+		} else {
+			msgs_sent++;
+			msg_code++;
+		}
+	} while (msgs_sent <= msgs_wanted);
+	if (msgs_sent == msgs_wanted) {
+		return (0);
+	} else {
+		return (-1);
+	}
+}
+
+void *token_callback;
+void start_mcasting (void)
+{
+	api->totem_callback_token_create (
+		&token_callback,
+		TOTEM_CALLBACK_TOKEN_RECEIVED,
+		1,
+		send_message,	
+		&token_callback);
+} 
+
+static void message_handler_req_exec_pload_start (
+	void *msg,
+	unsigned int nodeid)
+{
+	struct req_exec_pload_start *req_exec_pload_start = (struct req_exec_pload_start *)msg;
+
+	msgs_wanted = req_exec_pload_start->msg_count;
+	msg_size = req_exec_pload_start->msg_size;
+	msg_code = req_exec_pload_start->msg_code;
+
+	start_mcasting ();
+}
+
+# define timersub(a, b, result)                                               \
+  do {                                                                        \
+    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
+    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
+    if ((result)->tv_usec < 0) {                                              \
+      --(result)->tv_sec;                                                     \
+      (result)->tv_usec += 1000000;                                           \
+    }                                                                         \
+  } while (0)
+
+struct timeval tv1;
+struct timeval tv2;
+struct timeval tv_elapsed;
+int last_msg_no = 0;
+
+static void message_handler_req_exec_pload_mcast (
+	void *msg,
+	unsigned int nodeid)
+{
+	struct req_exec_pload_mcast *pload_mcast = (struct req_exec_pload_mcast *)msg;
+
+	assert (pload_mcast->msg_code - 1 == last_msg_no);
+	last_msg_no = pload_mcast->msg_code;
+	if (msgs_delivered == 0) {
+		gettimeofday (&tv1, NULL);
+	}
+	msgs_delivered += 1;
+	if (msgs_delivered == msgs_wanted) {
+		gettimeofday (&tv2, NULL);
+		timersub (&tv2, &tv1, &tv_elapsed);
+	        printf ("%5d Writes ", msgs_delivered);
+		printf ("%5d bytes per write ", msg_size);
+		printf ("%7.3f Seconds runtime ",
+		(tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)));
+		printf ("%9.3f TP/s ",
+		((float)msgs_delivered) /  (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)));
+		printf ("%7.3f MB/s.\n",
+		((float)msgs_delivered) * ((float)msg_size) /  ((tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)) * 1000000.0));
+	}
+}
diff -Naurd corosync-0.92/services/testquorum.c corosync-trunk/services/testquorum.c
--- corosync-0.92/services/testquorum.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/services/testquorum.c	2008-12-09 14:48:47.000000000 +0100
@@ -0,0 +1,153 @@
+/*
+ * 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 Red Hat, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <sched.h>
+#include <time.h>
+
+#include <corosync/engine/logsys.h>
+#include <corosync/ipc_gen.h>
+#include <corosync/lcr/lcr_comp.h>
+#include <corosync/engine/coroapi.h>
+
+#include <corosync/engine/quorum.h>
+
+LOGSYS_DECLARE_SUBSYS ("TEST", LOG_INFO);
+
+static void test_init(struct corosync_api_v1 *api, quorum_set_quorate_fn_t report);
+
+/*
+ * lcrso object definition
+ */
+static struct quorum_services_api_ver1 test_quorum_iface_ver0 = {
+	.init				= test_init
+};
+
+static struct lcr_iface corosync_test_quorum_ver0[1] = {
+	{
+		.name			= "testquorum",
+		.version		= 0,
+		.versions_replace	= 0,
+		.versions_replace_count	= 0,
+		.dependencies		= 0,
+		.dependency_count	= 0,
+		.constructor		= NULL,
+		.destructor		= NULL,
+		.interfaces		= (void **)(void *)&test_quorum_iface_ver0,
+	},
+};
+
+static struct lcr_comp test_quorum_comp_ver0 = {
+	.iface_count			= 1,
+	.ifaces				= corosync_test_quorum_ver0
+};
+
+__attribute__ ((constructor)) static void test_quorum_comp_register (void) {
+	lcr_interfaces_set (&corosync_test_quorum_ver0[0], &test_quorum_iface_ver0);
+	lcr_component_register (&test_quorum_comp_ver0);
+}
+
+/* -------------------------------------------------- */
+
+static quorum_set_quorate_fn_t set_quorum;
+
+static void key_change_notify(object_change_type_t change_type,
+			      unsigned int parent_object_handle,
+			      unsigned int object_handle,
+			      void *object_name_pt, int object_name_len,
+			      void *key_name_pt, int key_len,
+			      void *key_value_pt, int key_value_len,
+			      void *priv_data_pt)
+{
+	unsigned int members[1];
+	struct memb_ring_id ring_id;
+
+	memset(&ring_id, 0, sizeof(ring_id));
+
+	/* If the 'quorum.quorate' key changes, then that changes quorum */
+	if (strncmp(key_name_pt, "quorate", key_len) == 0) {
+		set_quorum(members, 0, atoi(key_value_pt), &ring_id);
+	}
+}
+
+static void quorum_callback(int quorate, void *context)
+{
+	log_printf(LOG_LEVEL_DEBUG, "quorum callback: quorate = %d\n", quorate);
+}
+
+static void test_init(struct corosync_api_v1 *api,
+		      quorum_set_quorate_fn_t report)
+{
+
+	unsigned int find_handle;
+	unsigned int quorum_handle = 0;
+
+	set_quorum = report;
+
+	/*
+	 * Register for objdb changes on quorum { }
+	 */
+	api->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle);
+        api->object_find_next(find_handle, &quorum_handle);
+	api->object_find_destroy(find_handle);
+
+	api->object_track_start(quorum_handle,
+				1,
+				key_change_notify,
+				NULL, // object_create_notify
+				NULL, // object_destroy_notify
+				NULL, // object_reload_notify
+				NULL); // priv_data
+
+	/* Register for quorum changes too! */
+	api->quorum_register_callback(quorum_callback, NULL);
+}
diff -Naurd corosync-0.92/services/votequorum.c corosync-trunk/services/votequorum.c
--- corosync-0.92/services/votequorum.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/services/votequorum.c	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,1619 @@
+/*
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#ifndef COROSYNC_BSD
+#include <alloca.h>
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <corosync/corotypes.h>
+#include <corosync/cfg.h>
+#include <corosync/list.h>
+#include <corosync/lcr/lcr_comp.h>
+#include <corosync/engine/logsys.h>
+#include <corosync/ipc_gen.h>
+#include <corosync/engine/coroapi.h>
+#include <corosync/engine/quorum.h>
+#include <corosync/ipc_votequorum.h>
+#include <corosync/list.h>
+
+#define VOTEQUORUM_MAJOR_VERSION 6
+#define VOTEQUORUM_MINOR_VERSION 3
+#define VOTEQUORUM_PATCH_VERSION 0
+
+ /* Silly default to prevent accidents! */
+#define DEFAULT_EXPECTED   1024
+#define DEFAULT_QDEV_POLL 10000
+
+LOGSYS_DECLARE_SUBSYS ("VOTEQ", LOG_INFO);
+
+enum quorum_message_req_types {
+	MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO  = 0,
+	MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE = 1,
+	MESSAGE_REQ_EXEC_VOTEQUORUM_KILLNODE = 2,
+};
+
+#define NODE_FLAGS_BEENDOWN         1
+#define NODE_FLAGS_SEESDISALLOWED   8
+#define NODE_FLAGS_HASSTATE        16
+#define NODE_FLAGS_QDISK           32
+#define NODE_FLAGS_REMOVED         64
+#define NODE_FLAGS_US             128
+
+
+typedef enum { NODESTATE_JOINING=1, NODESTATE_MEMBER,
+	       NODESTATE_DEAD, NODESTATE_LEAVING, NODESTATE_DISALLOWED } nodestate_t;
+
+
+/* This structure is tacked onto the start of a cluster message packet for our
+ * own nefarious purposes. */
+struct q_protheader {
+	unsigned char  tgtport; /* Target port number */
+	unsigned char  srcport; /* Source (originating) port number */
+	unsigned short pad;
+	unsigned int   flags;
+	int            srcid;	/* Node ID of the sender */
+	int            tgtid;	/* Node ID of the target */
+} __attribute__((packed));
+
+struct cluster_node {
+	int flags;
+	int node_id;
+	unsigned int expected_votes;
+	unsigned int votes;
+	time_t join_time;
+
+	nodestate_t state;
+
+	struct timeval last_hello; /* Only used for quorum devices */
+
+	struct list_head list;
+};
+
+static int quorum_flags;
+#define VOTEQUORUM_FLAG_FEATURE_DISALLOWED 1
+#define VOTEQUORUM_FLAG_FEATURE_TWONODE 1
+
+static int quorum;
+static int cluster_is_quorate;
+static int first_trans = 1;
+static unsigned int quorumdev_poll = DEFAULT_QDEV_POLL;
+
+static struct cluster_node *us;
+static struct cluster_node *quorum_device = NULL;
+static char quorum_device_name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
+static corosync_timer_handle_t quorum_device_timer;
+static struct list_head cluster_members_list;
+static struct corosync_api_v1 *corosync_api;
+static struct list_head trackers_list;
+static unsigned int quorum_members[PROCESSOR_COUNT_MAX+1];
+static int quorum_members_entries = 0;
+static struct memb_ring_id quorum_ringid;
+static cs_tpg_handle group_handle;
+
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+static struct cluster_node *find_node_by_nodeid(int nodeid);
+static struct cluster_node *allocate_node(int nodeid);
+static char *kill_reason(int reason);
+
+static struct corosync_tpg_group quorum_group[1] = {
+        { .group          = "VOTEQ", .group_len      = 5},
+};
+
+#define list_iterate(v, head) \
+        for (v = (head)->next; v != head; v = v->next)
+
+struct quorum_pd {
+	unsigned char track_flags;
+	int tracking_enabled;
+	uint64_t tracking_context;
+	struct list_head list;
+	void *conn;
+};
+
+/*
+ * Service Interfaces required by service_message_handler struct
+ */
+
+static void votequorum_init(struct corosync_api_v1 *api,
+			    quorum_set_quorate_fn_t report);
+
+static void quorum_confchg_fn (
+	enum totem_configuration_type configuration_type,
+	unsigned int *member_list, int member_list_entries,
+	unsigned int *left_list, int left_list_entries,
+	unsigned int *joined_list, int joined_list_entries,
+	struct memb_ring_id *ring_id);
+
+static void quorum_deliver_fn(unsigned int nodeid, struct iovec *iovec, int iov_len,
+			      int endian_conversion_required);
+
+static int votequorum_exec_init_fn (struct corosync_api_v1 *corosync_api);
+
+static int quorum_lib_init_fn (void *conn);
+
+static int quorum_lib_exit_fn (void *conn);
+
+static void message_handler_req_exec_quorum_nodeinfo (
+	void *message,
+	unsigned int nodeid);
+
+static void message_handler_req_exec_quorum_reconfigure (
+	void *message,
+	unsigned int nodeid);
+
+static void message_handler_req_exec_quorum_killnode (
+	void *message,
+	unsigned int nodeid);
+
+
+static void message_handler_req_lib_votequorum_getinfo (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_setexpected (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_setvotes (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_qdisk_register (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_qdisk_unregister (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_qdisk_poll (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_qdisk_getinfo (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_setstate (void *conn, void *message);
+
+static void message_handler_req_lib_votequorum_leaving (void *conn, void *message);
+static void message_handler_req_lib_votequorum_trackstart (void *conn, void *msg);
+static void message_handler_req_lib_votequorum_trackstop (void *conn, void *msg);
+
+static int quorum_exec_send_nodeinfo(void);
+static int quorum_exec_send_reconfigure(int param, int nodeid, int value);
+static int quorum_exec_send_killnode(int nodeid, unsigned int reason);
+
+static void add_votequorum_config_notification(unsigned int quorum_object_handle);
+
+
+/*
+ * Library Handler Definition
+ */
+static struct corosync_lib_handler quorum_lib_service[] =
+{
+	{ /* 0 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_getinfo,
+		.response_size				= sizeof (struct res_lib_votequorum_getinfo),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_GETINFO,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 1 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_setexpected,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 2 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_setvotes,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 3 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_qdisk_register,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 4 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_qdisk_unregister,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 5 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_qdisk_poll,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 6 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_qdisk_getinfo,
+		.response_size				= sizeof (struct res_lib_votequorum_qdisk_getinfo),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_QDISK_GETINFO,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 7 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_setstate,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 8 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_leaving,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 9 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_trackstart,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 10 */
+		.lib_handler_fn				= message_handler_req_lib_votequorum_trackstop,
+		.response_size				= sizeof (struct res_lib_votequorum_status),
+		.response_id				= MESSAGE_RES_VOTEQUORUM_STATUS,
+		.flow_control				= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
+	}
+};
+
+static quorum_set_quorate_fn_t set_quorum;
+/*
+ * lcrso object definition
+ */
+static struct quorum_services_api_ver1 votequorum_iface_ver0 = {
+	.init				= votequorum_init
+};
+
+static struct corosync_service_engine quorum_service_handler = {
+	.name				        = "corosync votes quorum service v0.90",
+	.id					= VOTEQUORUM_SERVICE,
+	.private_data_size			= sizeof (struct quorum_pd),
+	.allow_inquorate			= CS_LIB_ALLOW_INQUORATE,
+	.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED,
+	.lib_init_fn				= quorum_lib_init_fn,
+	.lib_exit_fn				= quorum_lib_exit_fn,
+	.lib_engine				= quorum_lib_service,
+	.lib_engine_count			= sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler),
+	.exec_init_fn				= votequorum_exec_init_fn,
+	.exec_engine				= NULL,
+	.exec_engine_count		        = 0,
+	.confchg_fn                             = NULL,
+};
+
+/*
+ * Dynamic loader definition
+ */
+static struct corosync_service_engine *quorum_get_service_handler_ver0 (void);
+
+static struct corosync_service_engine_iface_ver0 quorum_service_handler_iface = {
+	.corosync_get_service_engine_ver0 = quorum_get_service_handler_ver0
+};
+
+static struct lcr_iface corosync_quorum_ver0[2] = {
+	{
+		.name				= "corosync_votequorum",
+		.version			= 0,
+		.versions_replace		= 0,
+		.versions_replace_count         = 0,
+		.dependencies			= 0,
+		.dependency_count		= 0,
+		.constructor			= NULL,
+		.destructor			= NULL,
+		.interfaces			= (void **)(void *)&votequorum_iface_ver0
+	},
+	{
+		.name				= "corosync_votequorum_iface",
+		.version			= 0,
+		.versions_replace		= 0,
+		.versions_replace_count         = 0,
+		.dependencies			= 0,
+		.dependency_count		= 0,
+		.constructor			= NULL,
+		.destructor			= NULL,
+		.interfaces			= NULL
+	}
+};
+
+static struct lcr_comp quorum_comp_ver0 = {
+	.iface_count			= 2,
+	.ifaces			        = corosync_quorum_ver0
+};
+
+
+static struct corosync_service_engine *quorum_get_service_handler_ver0 (void)
+{
+	return (&quorum_service_handler);
+}
+
+__attribute__ ((constructor)) static void quorum_comp_register (void) {
+        lcr_interfaces_set (&corosync_quorum_ver0[0], &votequorum_iface_ver0);
+	lcr_interfaces_set (&corosync_quorum_ver0[1], &quorum_service_handler_iface);
+	lcr_component_register (&quorum_comp_ver0);
+}
+
+static void votequorum_init(struct corosync_api_v1 *api,
+			    quorum_set_quorate_fn_t report)
+{
+	ENTER();
+	set_quorum = report;
+
+	/* Load the library-servicing part of this module */
+	api->service_link_and_init(api, "corosync_votequorum_iface", 0);
+
+	LEAVE();
+}
+
+/* Message types */
+#define VOTEQUORUM_MSG_NODEINFO     5
+#define VOTEQUORUM_MSG_KILLNODE     6
+#define VOTEQUORUM_MSG_RECONFIGURE  8
+
+struct req_exec_quorum_nodeinfo {
+	unsigned char cmd;
+	unsigned char first_trans;
+	unsigned int  votes;
+	unsigned int  expected_votes;
+
+	unsigned int   major_version;	/* Not backwards compatible */
+	unsigned int   minor_version;	/* Backwards compatible */
+	unsigned int   patch_version;	/* Backwards/forwards compatible */
+	unsigned int   config_version;
+	unsigned int   flags;
+
+} __attribute__((packed));
+
+/* Parameters for RECONFIG command */
+#define RECONFIG_PARAM_EXPECTED_VOTES 1
+#define RECONFIG_PARAM_NODE_VOTES     2
+#define RECONFIG_PARAM_LEAVING        3
+
+struct req_exec_quorum_reconfigure {
+	unsigned char  cmd;
+	unsigned char  param;
+	unsigned short pad;
+	int            nodeid;
+	unsigned int   value;
+};
+
+struct req_exec_quorum_killnode {
+	unsigned char cmd;
+	unsigned char pad1;
+	uint16_t reason;
+	int nodeid;
+};
+
+/* These just make the access a little neater */
+static inline int objdb_get_string(struct corosync_api_v1 *corosync, unsigned int object_service_handle,
+				   char *key, char **value)
+{
+	int res;
+
+	*value = NULL;
+	if ( !(res = corosync_api->object_key_get(object_service_handle,
+					      key,
+					      strlen(key),
+					      (void *)value,
+					      NULL))) {
+		if (*value)
+			return 0;
+	}
+	return -1;
+}
+
+static inline void objdb_get_int(struct corosync_api_v1 *corosync, unsigned int object_service_handle,
+				 char *key, unsigned int *intvalue, unsigned int default_value)
+{
+	char *value = NULL;
+
+	*intvalue = default_value;
+
+	if (!corosync_api->object_key_get(object_service_handle, key, strlen(key),
+				 (void *)&value, NULL)) {
+		if (value) {
+			*intvalue = atoi(value);
+		}
+	}
+}
+
+static int votequorum_send_message(void *message, int len)
+{
+	struct iovec iov[2];
+	struct q_protheader header;
+
+	header.tgtport = 0;
+	header.srcport = 0;
+	header.flags   = 0;
+	header.srcid   = us->node_id;
+	header.tgtid   = 0;
+
+	iov[0].iov_base = &header;
+	iov[0].iov_len  = sizeof(header);
+	iov[1].iov_base = message;
+	iov[1].iov_len  = len;
+
+	return corosync_api->tpg_joined_mcast(group_handle, iov, 2, TOTEM_AGREED);
+}
+
+static void read_quorum_config(unsigned int quorum_handle)
+{
+	unsigned int value = 0;
+	int cluster_members = 0;
+	struct list_head *tmp;
+	struct cluster_node *node;
+
+	log_printf(LOG_INFO, "Reading configuration\n");
+
+	objdb_get_int(corosync_api, quorum_handle, "expected_votes", &us->expected_votes, DEFAULT_EXPECTED);
+	objdb_get_int(corosync_api, quorum_handle, "votes", &us->votes, 1);
+	objdb_get_int(corosync_api, quorum_handle, "quorumdev_poll", &quorumdev_poll, DEFAULT_QDEV_POLL);
+	objdb_get_int(corosync_api, quorum_handle, "disallowed", &value, 0);
+	if (value)
+		quorum_flags |= VOTEQUORUM_FLAG_FEATURE_DISALLOWED;
+	else
+		quorum_flags &= ~VOTEQUORUM_FLAG_FEATURE_DISALLOWED;
+
+	objdb_get_int(corosync_api, quorum_handle, "two_node", &value, 0);
+	if (value)
+		quorum_flags |= VOTEQUORUM_FLAG_FEATURE_TWONODE;
+	else
+		quorum_flags &= ~VOTEQUORUM_FLAG_FEATURE_TWONODE;
+
+	/*
+	 * two_node mode is invalid if there are more than 2 nodes in the cluster!
+	 */
+	list_iterate(tmp, &cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		cluster_members++;
+        }
+
+	if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_TWONODE && cluster_members > 2) {
+		log_printf(LOG_WARNING, "quorum.two_node was set but there are more than 2 nodes in the cluster. It will be ignored.");
+		quorum_flags &= ~VOTEQUORUM_FLAG_FEATURE_TWONODE;
+	}
+}
+
+static int votequorum_exec_init_fn (struct corosync_api_v1 *api)
+{
+	unsigned int object_handle;
+	unsigned int find_handle;
+
+	ENTER();
+
+	corosync_api = api;
+
+	list_init(&cluster_members_list);
+	list_init(&trackers_list);
+
+	/* Allocate a cluster_node for us */
+	us = allocate_node(corosync_api->totem_nodeid_get());
+	if (!us)
+		return (1);
+
+	us->flags |= NODE_FLAGS_US;
+	us->state = NODESTATE_MEMBER;
+	us->expected_votes = DEFAULT_EXPECTED;
+	us->votes = 1;
+	time(&us->join_time);
+
+	/* Get configuration variables */
+	corosync_api->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle);
+
+	if (corosync_api->object_find_next(find_handle, &object_handle) == 0) {
+		read_quorum_config(object_handle);
+	}
+	/* Listen for changes */
+	add_votequorum_config_notification(object_handle);
+	corosync_api->object_find_destroy(find_handle);
+
+	api->tpg_init(&group_handle, quorum_deliver_fn, quorum_confchg_fn);
+	api->tpg_join(group_handle, quorum_group, 1);
+
+	LEAVE();
+	return (0);
+}
+
+static int quorum_lib_exit_fn (void *conn)
+{
+	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+
+	ENTER();
+	if (quorum_pd->tracking_enabled) {
+		list_del (&quorum_pd->list);
+		list_init (&quorum_pd->list);
+	}
+	LEAVE();
+	return (0);
+}
+
+
+static int send_quorum_notification(void *conn, uint64_t context)
+{
+	struct res_lib_votequorum_notification *res_lib_votequorum_notification;
+	struct list_head *tmp;
+	struct cluster_node *node;
+	int cluster_members = 0;
+	int i = 0;
+	int size;
+	char *buf;
+
+	ENTER();
+	list_iterate(tmp, &cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		cluster_members++;
+        }
+	if (quorum_device)
+		cluster_members++;
+
+	size = sizeof(struct res_lib_votequorum_notification) + sizeof(struct votequorum_node) * cluster_members;
+	buf = alloca(size);
+	if (!buf) {
+		LEAVE();
+		return -1;
+	}
+
+	res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)buf;
+	res_lib_votequorum_notification->quorate = cluster_is_quorate;
+	res_lib_votequorum_notification->node_list_entries = cluster_members;
+	res_lib_votequorum_notification->context = context;
+	list_iterate(tmp, &cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		res_lib_votequorum_notification->node_list[i].nodeid = node->node_id;
+		res_lib_votequorum_notification->node_list[i++].state = node->state;
+        }
+	if (quorum_device) {
+		res_lib_votequorum_notification->node_list[i].nodeid = 0;
+		res_lib_votequorum_notification->node_list[i++].state = quorum_device->state | 0x80;
+	}
+	res_lib_votequorum_notification->header.id = MESSAGE_RES_VOTEQUORUM_NOTIFICATION;
+	res_lib_votequorum_notification->header.size = size;
+	res_lib_votequorum_notification->header.error = CS_OK;
+
+	/* Send it to all interested parties */
+	if (conn) {
+		int ret = corosync_api->ipc_conn_send_response(conn, buf, size);
+		LEAVE();
+		return ret;
+	}
+	else {
+		struct quorum_pd *qpd;
+
+		list_iterate(tmp, &trackers_list) {
+			qpd = list_entry(tmp, struct quorum_pd, list);
+			res_lib_votequorum_notification->context = qpd->tracking_context;
+			corosync_api->ipc_conn_send_response(corosync_api->ipc_conn_partner_get(qpd->conn), buf, size);
+		}
+	}
+	LEAVE();
+	return 0;
+}
+
+static void set_quorate(int total_votes)
+{
+	int quorate;
+
+	ENTER();
+	if (quorum > total_votes) {
+		quorate = 0;
+	}
+	else {
+		quorate = 1;
+	}
+
+	if (cluster_is_quorate && !quorate)
+		log_printf(LOG_INFO, "quorum lost, blocking activity\n");
+	if (!cluster_is_quorate && quorate)
+		log_printf(LOG_INFO, "quorum regained, resuming activity\n");
+
+	/* If we are newly quorate, then kill any DISALLOWED nodes */
+	if (!cluster_is_quorate && quorate) {
+		struct cluster_node *node = NULL;
+		struct list_head *tmp;
+
+		list_iterate(tmp, &cluster_members_list) {
+			node = list_entry(tmp, struct cluster_node, list);
+			if (node->state == NODESTATE_DISALLOWED)
+				quorum_exec_send_killnode(node->node_id, VOTEQUORUM_REASON_KILL_REJOIN);
+		}
+	}
+
+	cluster_is_quorate = quorate;
+	set_quorum(quorum_members, quorum_members_entries, quorate, &quorum_ringid);
+	ENTER();
+}
+
+static int calculate_quorum(int allow_decrease, int max_expected, unsigned int *ret_total_votes)
+{
+	struct list_head *nodelist;
+	struct cluster_node *node;
+	unsigned int total_votes = 0;
+	unsigned int highest_expected = 0;
+	unsigned int newquorum, q1, q2;
+	unsigned int total_nodes = 0;
+	unsigned int leaving = 0;
+
+	ENTER();
+	list_iterate(nodelist, &cluster_members_list) {
+		node = list_entry(nodelist, struct cluster_node, list);
+
+		log_printf(LOG_DEBUG, "node %x state=%d, votes=%d, expected=%d\n",
+			   node->node_id, node->state, node->votes, node->expected_votes);
+
+		if (node->state == NODESTATE_MEMBER) {
+			if (max_expected)
+				node->expected_votes = max_expected;
+			else
+				highest_expected = max(highest_expected, node->expected_votes);
+			total_votes += node->votes;
+			total_nodes++;
+		}
+		if (node->state == NODESTATE_LEAVING) {
+			leaving = 1;
+		}
+	}
+
+	if (quorum_device && quorum_device->state == NODESTATE_MEMBER)
+		total_votes += quorum_device->votes;
+
+	if (max_expected > 0)
+		highest_expected = max_expected;
+
+	/* This quorum calculation is taken from the OpenVMS Cluster Systems
+	 * manual, but, then, you guessed that didn't you */
+	q1 = (highest_expected + 2) / 2;
+	q2 = (total_votes + 2) / 2;
+	newquorum = max(q1, q2);
+
+	/* Normally quorum never decreases but the system administrator can
+	 * force it down by setting expected votes to a maximum value */
+	if (!allow_decrease)
+		newquorum = max(quorum, newquorum);
+
+	/* The special two_node mode allows each of the two nodes to retain
+	 * quorum if the other fails.  Only one of the two should live past
+	 * fencing (as both nodes try to fence each other in split-brain.)
+	 * Also: if there are more than two nodes, force us inquorate to avoid
+	 * any damage or confusion.
+	 */
+	if ((quorum_flags & VOTEQUORUM_FLAG_FEATURE_TWONODE) && total_nodes <= 2)
+		newquorum = 1;
+
+	if (ret_total_votes)
+		*ret_total_votes = total_votes;
+
+	LEAVE();
+	return newquorum;
+}
+
+/* Recalculate cluster quorum, set quorate and notify changes */
+static void recalculate_quorum(int allow_decrease)
+{
+	unsigned int total_votes;
+
+	ENTER();
+	quorum = calculate_quorum(allow_decrease, 0, &total_votes);
+	set_quorate(total_votes);
+	send_quorum_notification(NULL, 0L);
+	LEAVE();
+}
+
+static int have_disallowed(void)
+{
+	struct cluster_node *node;
+	struct list_head *tmp;
+
+	list_iterate(tmp, &cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		if (node->state == NODESTATE_DISALLOWED)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void node_add_ordered(struct cluster_node *newnode)
+{
+	struct cluster_node *node = NULL;
+	struct list_head *tmp;
+	struct list_head *newlist = &newnode->list;
+
+	list_iterate(tmp, &cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+
+                if (newnode->node_id < node->node_id)
+                        break;
+        }
+
+        if (!node)
+		list_add(&newnode->list, &cluster_members_list);
+        else {
+                newlist->prev = tmp->prev;
+                newlist->next = tmp;
+                tmp->prev->next = newlist;
+                tmp->prev = newlist;
+        }
+}
+
+static struct cluster_node *allocate_node(int nodeid)
+{
+	struct cluster_node *cl;
+
+	cl = malloc(sizeof(struct cluster_node));
+	if (cl) {
+		memset(cl, 0, sizeof(struct cluster_node));
+		cl->node_id = nodeid;
+		if (nodeid)
+			node_add_ordered(cl);
+	}
+	return cl;
+}
+
+static struct cluster_node *find_node_by_nodeid(int nodeid)
+{
+	struct cluster_node *node;
+	struct list_head *tmp;
+
+	list_iterate(tmp, &cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		if (node->node_id == nodeid)
+			return node;
+	}
+	return NULL;
+}
+
+
+static int quorum_exec_send_nodeinfo()
+{
+	struct req_exec_quorum_nodeinfo req_exec_quorum_nodeinfo;
+	int ret;
+
+	ENTER();
+
+	req_exec_quorum_nodeinfo.cmd = VOTEQUORUM_MSG_NODEINFO;
+	req_exec_quorum_nodeinfo.expected_votes = us->expected_votes;
+	req_exec_quorum_nodeinfo.votes = us->votes;
+	req_exec_quorum_nodeinfo.major_version = VOTEQUORUM_MAJOR_VERSION;
+	req_exec_quorum_nodeinfo.minor_version = VOTEQUORUM_MINOR_VERSION;
+	req_exec_quorum_nodeinfo.patch_version = VOTEQUORUM_PATCH_VERSION;
+	req_exec_quorum_nodeinfo.flags = us->flags;
+	req_exec_quorum_nodeinfo.first_trans = first_trans;
+	if (have_disallowed())
+		req_exec_quorum_nodeinfo.flags |= NODE_FLAGS_SEESDISALLOWED;
+
+	ret = votequorum_send_message(&req_exec_quorum_nodeinfo, sizeof(req_exec_quorum_nodeinfo));
+	LEAVE();
+	return ret;
+}
+
+
+static int quorum_exec_send_reconfigure(int param, int nodeid, int value)
+{
+	struct req_exec_quorum_reconfigure req_exec_quorum_reconfigure;
+	int ret;
+
+	ENTER();
+
+	req_exec_quorum_reconfigure.cmd = VOTEQUORUM_MSG_RECONFIGURE;
+	req_exec_quorum_reconfigure.param = param;
+	req_exec_quorum_reconfigure.nodeid = nodeid;
+	req_exec_quorum_reconfigure.value = value;
+
+	ret = votequorum_send_message(&req_exec_quorum_reconfigure, sizeof(req_exec_quorum_reconfigure));
+	LEAVE();
+	return ret;
+}
+
+static int quorum_exec_send_killnode(int nodeid, unsigned int reason)
+{
+	struct req_exec_quorum_killnode req_exec_quorum_killnode;
+	int ret;
+
+	ENTER();
+
+	req_exec_quorum_killnode.cmd = VOTEQUORUM_MSG_KILLNODE;
+	req_exec_quorum_killnode.nodeid = nodeid;
+	req_exec_quorum_killnode.reason = reason;
+
+	ret = votequorum_send_message(&req_exec_quorum_killnode, sizeof(req_exec_quorum_killnode));
+	LEAVE();
+	return ret;
+}
+
+static void quorum_confchg_fn (
+	enum totem_configuration_type configuration_type,
+	unsigned int *member_list, int member_list_entries,
+	unsigned int *left_list, int left_list_entries,
+	unsigned int *joined_list, int joined_list_entries,
+	struct memb_ring_id *ring_id)
+{
+	int i;
+	int leaving = 0;
+	struct cluster_node *node;
+
+	ENTER();
+	if (member_list_entries > 1)
+		first_trans = 0;
+
+	if (left_list_entries) {
+		for (i = 0; i< left_list_entries; i++) {
+			node = find_node_by_nodeid(left_list[i]);
+			if (node) {
+				if (node->state == NODESTATE_LEAVING)
+					leaving = 1;
+				node->state = NODESTATE_DEAD;
+				node->flags |= NODE_FLAGS_BEENDOWN;
+			}
+		}
+		recalculate_quorum(leaving);
+	}
+
+	if (member_list_entries) {
+		memcpy(quorum_members, member_list, sizeof(unsigned int) * member_list_entries);
+		quorum_members_entries = member_list_entries;
+		if (quorum_device) {
+			quorum_members[quorum_members_entries++] = 0;
+		}
+		quorum_exec_send_nodeinfo();
+	}
+
+	memcpy(&quorum_ringid, ring_id, sizeof(*ring_id));
+	LEAVE();
+}
+
+static void exec_quorum_nodeinfo_endian_convert (void *msg)
+{
+	struct req_exec_quorum_nodeinfo *nodeinfo = (struct req_exec_quorum_nodeinfo *)msg;
+
+	nodeinfo->votes = swab32(nodeinfo->votes);
+	nodeinfo->expected_votes = swab32(nodeinfo->expected_votes);
+	nodeinfo->major_version = swab32(nodeinfo->major_version);
+	nodeinfo->minor_version = swab32(nodeinfo->minor_version);
+	nodeinfo->patch_version = swab32(nodeinfo->patch_version);
+	nodeinfo->config_version = swab32(nodeinfo->config_version);
+	nodeinfo->flags = swab32(nodeinfo->flags);
+}
+
+static void exec_quorum_reconfigure_endian_convert (void *msg)
+{
+	struct req_exec_quorum_reconfigure *reconfigure = (struct req_exec_quorum_reconfigure *)msg;
+	reconfigure->nodeid = swab32(reconfigure->nodeid);
+	reconfigure->value = swab32(reconfigure->value);
+}
+
+static void exec_quorum_killnode_endian_convert (void *msg)
+{
+	struct req_exec_quorum_killnode *killnode = (struct req_exec_quorum_killnode *)msg;
+	killnode->reason = swab16(killnode->reason);
+	killnode->nodeid = swab32(killnode->nodeid);
+}
+
+static void quorum_deliver_fn(unsigned int nodeid, struct iovec *iovec, int iov_len,
+			      int endian_conversion_required)
+{
+	struct q_protheader *header = iovec->iov_base;
+	char *buf;
+
+	ENTER();
+
+	if (endian_conversion_required) {
+		header->srcid = swab32(header->srcid);
+		header->tgtid = swab32(header->tgtid);
+		header->flags = swab32(header->flags);
+	}
+
+	/* Only pass on messages for us or everyone */
+	if (header->tgtport == 0 &&
+	    (header->tgtid == us->node_id ||
+	     header->tgtid == 0)) {
+		buf = iovec->iov_base + sizeof(struct q_protheader);
+		switch (*buf) {
+
+		case VOTEQUORUM_MSG_NODEINFO:
+			if (endian_conversion_required)
+				exec_quorum_nodeinfo_endian_convert(buf);
+			message_handler_req_exec_quorum_nodeinfo (buf, header->srcid);
+			break;
+		case VOTEQUORUM_MSG_RECONFIGURE:
+			if (endian_conversion_required)
+				exec_quorum_reconfigure_endian_convert(buf);
+			message_handler_req_exec_quorum_reconfigure (buf, header->srcid);
+			break;
+		case VOTEQUORUM_MSG_KILLNODE:
+			if (endian_conversion_required)
+				exec_quorum_killnode_endian_convert(buf);
+			message_handler_req_exec_quorum_killnode (buf, header->srcid);
+			break;
+
+			/* Just ignore other messages */
+		}
+	}
+	LEAVE();
+}
+
+static void message_handler_req_exec_quorum_nodeinfo (
+	void *message,
+	unsigned int nodeid)
+{
+	struct req_exec_quorum_nodeinfo *req_exec_quorum_nodeinfo = (struct req_exec_quorum_nodeinfo *)message;
+	struct cluster_node *node;
+	int old_votes;
+	int old_expected;
+	nodestate_t old_state;
+	int new_node = 0;
+
+	ENTER();
+	log_printf(LOG_LEVEL_DEBUG, "got nodeinfo message from cluster node %d\n", nodeid);
+
+	node = find_node_by_nodeid(nodeid);
+	if (!node) {
+		node = allocate_node(nodeid);
+		new_node = 1;
+	}
+	if (!node) {
+		corosync_api->error_memory_failure();
+		return;
+	}
+
+	/*
+	 * If the node sending the message sees disallowed nodes and we don't, then
+	 * we have to leave
+	 */
+	if (req_exec_quorum_nodeinfo->flags & NODE_FLAGS_SEESDISALLOWED && !have_disallowed()) {
+		/* Must use syslog directly here or the message will never arrive */
+		syslog(LOG_CRIT, "[VOTEQ]: Joined a cluster with disallowed nodes. must die");
+		corosync_api->fatal_error(2, __FILE__, __LINE__);
+		exit(2);
+	}
+	old_votes = node->votes;
+	old_expected = node->expected_votes;
+	old_state = node->state;
+
+	/* Update node state */
+	if (req_exec_quorum_nodeinfo->minor_version >= 2)
+		node->votes = req_exec_quorum_nodeinfo->votes;
+	node->expected_votes = req_exec_quorum_nodeinfo->expected_votes;
+	node->state = NODESTATE_MEMBER;
+
+	/* Check flags for disallowed (if enabled) */
+	if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_DISALLOWED) {
+		if ((req_exec_quorum_nodeinfo->flags & NODE_FLAGS_HASSTATE && node->flags & NODE_FLAGS_BEENDOWN) ||
+		    (req_exec_quorum_nodeinfo->flags & NODE_FLAGS_HASSTATE && req_exec_quorum_nodeinfo->first_trans && !(node->flags & NODE_FLAGS_US))) {
+			if (node->state != NODESTATE_DISALLOWED) {
+				if (cluster_is_quorate) {
+					log_printf(LOG_CRIT, "Killing node %d because it has rejoined the cluster with existing state", node->node_id);
+					node->state = NODESTATE_DISALLOWED;
+					quorum_exec_send_killnode(nodeid, VOTEQUORUM_REASON_KILL_REJOIN);
+				}
+				else {
+					log_printf(LOG_CRIT, "Node %d not joined to quorum because it has existing state", node->node_id);
+					node->state = NODESTATE_DISALLOWED;
+				}
+			}
+		}
+	}
+	node->flags &= ~NODE_FLAGS_BEENDOWN;
+
+	if (new_node || old_votes != node->votes || old_expected != node->expected_votes || old_state != node->state)
+		recalculate_quorum(0);
+	LEAVE();
+}
+
+static void message_handler_req_exec_quorum_killnode (
+	void *message,
+	unsigned int nodeid)
+{
+	struct req_exec_quorum_killnode *req_exec_quorum_killnode = (struct req_exec_quorum_killnode *)message;
+
+	if (req_exec_quorum_killnode->nodeid == corosync_api->totem_nodeid_get()) {
+		log_printf(LOG_CRIT, "Killed by node %d: %s\n", nodeid, kill_reason(req_exec_quorum_killnode->reason));
+
+		corosync_api->fatal_error(1, __FILE__, __LINE__);
+		exit(1);
+	}
+}
+
+static void message_handler_req_exec_quorum_reconfigure (
+	void *message,
+	unsigned int nodeid)
+{
+	struct req_exec_quorum_reconfigure *req_exec_quorum_reconfigure = (struct req_exec_quorum_reconfigure *)message;
+	struct cluster_node *node;
+	struct list_head *nodelist;
+
+	log_printf(LOG_LEVEL_DEBUG, "got reconfigure message from cluster node %d\n", nodeid);
+
+	node = find_node_by_nodeid(req_exec_quorum_reconfigure->nodeid);
+	if (!node)
+		return;
+
+	switch(req_exec_quorum_reconfigure->param)
+	{
+	case RECONFIG_PARAM_EXPECTED_VOTES:
+		node->expected_votes = req_exec_quorum_reconfigure->value;
+
+		list_iterate(nodelist, &cluster_members_list) {
+			node = list_entry(nodelist, struct cluster_node, list);
+			if (node->state == NODESTATE_MEMBER &&
+			    node->expected_votes > req_exec_quorum_reconfigure->value) {
+				node->expected_votes = req_exec_quorum_reconfigure->value;
+			}
+		}
+		recalculate_quorum(1);  /* Allow decrease */
+		break;
+
+	case RECONFIG_PARAM_NODE_VOTES:
+		node->votes = req_exec_quorum_reconfigure->value;
+		recalculate_quorum(1);  /* Allow decrease */
+		break;
+
+	case RECONFIG_PARAM_LEAVING:
+		node->state = NODESTATE_LEAVING;
+		break;
+	}
+}
+
+static int quorum_lib_init_fn (void *conn)
+{
+	struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+
+	ENTER();
+
+	list_init (&pd->list);
+	pd->conn = conn;
+
+	LEAVE();
+	return (0);
+}
+
+/* Message from the library */
+static void message_handler_req_lib_votequorum_getinfo (void *conn, void *message)
+{
+	struct req_lib_votequorum_getinfo *req_lib_votequorum_getinfo = (struct req_lib_votequorum_getinfo *)message;
+	struct res_lib_votequorum_getinfo res_lib_votequorum_getinfo;
+	struct cluster_node *node;
+	unsigned int highest_expected = 0;
+	unsigned int total_votes = 0;
+	cs_error_t error = CS_OK;
+
+	log_printf(LOG_LEVEL_DEBUG, "got getinfo request on %p for node %d\n", conn, req_lib_votequorum_getinfo->nodeid);
+
+	if (req_lib_votequorum_getinfo->nodeid) {
+		node = find_node_by_nodeid(req_lib_votequorum_getinfo->nodeid);
+	}
+	else {
+		node = us;
+	}
+
+	if (node) {
+		struct cluster_node *iternode;
+		struct list_head *nodelist;
+
+		list_iterate(nodelist, &cluster_members_list) {
+			iternode = list_entry(nodelist, struct cluster_node, list);
+
+			if (node->state == NODESTATE_MEMBER) {
+				highest_expected =
+					max(highest_expected, node->expected_votes);
+				total_votes += node->votes;
+			}
+		}
+
+		if (quorum_device && quorum_device->state == NODESTATE_MEMBER) {
+			total_votes += quorum_device->votes;
+		}
+
+		res_lib_votequorum_getinfo.votes = us->votes;
+		res_lib_votequorum_getinfo.expected_votes = us->expected_votes;
+		res_lib_votequorum_getinfo.highest_expected = highest_expected;
+
+		res_lib_votequorum_getinfo.quorum = quorum;
+		res_lib_votequorum_getinfo.total_votes = total_votes;
+		res_lib_votequorum_getinfo.flags = 0;
+		res_lib_votequorum_getinfo.nodeid = node->node_id;
+
+		if (us->flags & NODE_FLAGS_HASSTATE)
+			res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_HASSTATE;
+		if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_TWONODE)
+			res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_TWONODE;
+		if (cluster_is_quorate)
+			res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_QUORATE;
+		if (us->flags & NODE_FLAGS_SEESDISALLOWED)
+			res_lib_votequorum_getinfo.flags |= VOTEQUORUM_INFO_FLAG_DISALLOWED;
+	}
+	else {
+		error = CS_ERR_NOT_EXIST;
+	}
+
+	res_lib_votequorum_getinfo.header.size = sizeof(res_lib_votequorum_getinfo);
+	res_lib_votequorum_getinfo.header.id = MESSAGE_RES_VOTEQUORUM_GETINFO;
+	res_lib_votequorum_getinfo.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_getinfo, sizeof(res_lib_votequorum_getinfo));
+	log_printf(LOG_LEVEL_DEBUG, "getinfo response error: %d\n", error);
+}
+
+/* Message from the library */
+static void message_handler_req_lib_votequorum_setexpected (void *conn, void *message)
+{
+	struct req_lib_votequorum_setexpected *req_lib_votequorum_setexpected = (struct req_lib_votequorum_setexpected *)message;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	cs_error_t error = CS_OK;
+	unsigned int newquorum;
+	unsigned int total_votes;
+
+	ENTER();
+
+	/*
+	 * If there are disallowed nodes, then we can't allow the user
+	 * to bypass them by fiddling with expected votes.
+	 */
+	if (quorum_flags & VOTEQUORUM_FLAG_FEATURE_DISALLOWED && have_disallowed()) {
+		error = CS_ERR_EXIST;
+		goto error_exit;
+	}
+
+	/* Validate new expected votes */
+	newquorum = calculate_quorum(1, req_lib_votequorum_setexpected->expected_votes, &total_votes);
+	if (newquorum < total_votes / 2
+	    || newquorum > total_votes) {
+		error = CS_ERR_INVALID_PARAM;
+		goto error_exit;
+	}
+
+	quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, req_lib_votequorum_setexpected->expected_votes);
+
+	/* send status */
+error_exit:
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+	LEAVE();
+}
+
+/* Message from the library */
+static void message_handler_req_lib_votequorum_setvotes (void *conn, void *message)
+{
+	struct req_lib_votequorum_setvotes *req_lib_votequorum_setvotes = (struct req_lib_votequorum_setvotes *)message;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	struct cluster_node *node;
+	unsigned int newquorum;
+	unsigned int total_votes;
+	unsigned int saved_votes;
+	cs_error_t error = CS_OK;
+
+	ENTER();
+
+	node = find_node_by_nodeid(req_lib_votequorum_setvotes->nodeid);
+	if (!node) {
+		error = CS_ERR_NAME_NOT_FOUND;
+		goto error_exit;
+	}
+
+	/* Check votes is valid */
+	saved_votes = node->votes;
+	node->votes = req_lib_votequorum_setvotes->votes;
+
+	newquorum = calculate_quorum(1, 0, &total_votes);
+
+	if (newquorum < total_votes / 2 || newquorum > total_votes) {
+		node->votes = saved_votes;
+		error = CS_ERR_INVALID_PARAM;
+		goto error_exit;
+	}
+
+	if (!req_lib_votequorum_setvotes->nodeid)
+		req_lib_votequorum_setvotes->nodeid = corosync_api->totem_nodeid_get();
+
+	quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, req_lib_votequorum_setvotes->nodeid, req_lib_votequorum_setvotes->votes);
+
+error_exit:
+	/* send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+	LEAVE();
+}
+
+static void message_handler_req_lib_votequorum_leaving (void *conn, void *message)
+{
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	cs_error_t error = CS_OK;
+
+	ENTER();
+
+	quorum_exec_send_reconfigure(RECONFIG_PARAM_LEAVING, us->node_id, 0);
+
+	/* send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+	LEAVE();
+}
+
+static void quorum_device_timer_fn(void *arg)
+{
+	struct timeval now;
+
+	ENTER();
+	if (!quorum_device || quorum_device->state == NODESTATE_DEAD)
+		return;
+	gettimeofday(&now, NULL);
+	if (quorum_device->last_hello.tv_sec + quorumdev_poll/1000 < now.tv_sec) {
+		quorum_device->state = NODESTATE_DEAD;
+		log_printf(LOG_INFO, "lost contact with quorum device\n");
+		recalculate_quorum(0);
+	}
+	else {
+		corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device,
+						 quorum_device_timer_fn, &quorum_device_timer);
+	}
+	LEAVE();
+}
+
+
+static void message_handler_req_lib_votequorum_qdisk_register (void *conn, void *message)
+{
+	struct req_lib_votequorum_qdisk_register *req_lib_votequorum_qdisk_register = (struct req_lib_votequorum_qdisk_register *)message;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	cs_error_t error = CS_OK;
+
+	ENTER();
+
+	if (quorum_device) {
+		error = CS_ERR_EXIST;
+	}
+	else {
+		quorum_device = allocate_node(0);
+		quorum_device->state = NODESTATE_DEAD;
+		quorum_device->votes = req_lib_votequorum_qdisk_register->votes;
+		strcpy(quorum_device_name, req_lib_votequorum_qdisk_register->name);
+		list_add(&quorum_device->list, &cluster_members_list);
+	}
+
+	/* send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+	LEAVE();
+}
+
+static void message_handler_req_lib_votequorum_qdisk_unregister (void *conn, void *message)
+{
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	cs_error_t error = CS_OK;
+
+	ENTER();
+
+	if (quorum_device) {
+		struct cluster_node *node = quorum_device;
+
+		quorum_device = NULL;
+		list_del(&node->list);
+		free(node);
+		recalculate_quorum(0);
+	}
+	else {
+		error = CS_ERR_NOT_EXIST;
+	}
+
+	/* send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+	LEAVE();
+}
+
+static void message_handler_req_lib_votequorum_qdisk_poll (void *conn, void *message)
+{
+	struct req_lib_votequorum_qdisk_poll *req_lib_votequorum_qdisk_poll = (struct req_lib_votequorum_qdisk_poll *)message;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	cs_error_t error = CS_OK;
+
+	ENTER();
+
+	if (quorum_device) {
+		if (req_lib_votequorum_qdisk_poll->state) {
+			gettimeofday(&quorum_device->last_hello, NULL);
+			if (quorum_device->state == NODESTATE_DEAD) {
+				quorum_device->state = NODESTATE_MEMBER;
+				recalculate_quorum(0);
+
+				corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device,
+								 quorum_device_timer_fn, &quorum_device_timer);
+			}
+		}
+		else {
+			if (quorum_device->state == NODESTATE_MEMBER) {
+				quorum_device->state = NODESTATE_DEAD;
+				recalculate_quorum(0);
+				corosync_api->timer_delete(quorum_device_timer);
+			}
+		}
+	}
+	else {
+		error = CS_ERR_NOT_EXIST;
+	}
+
+	/* send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+
+	LEAVE();
+}
+
+static void message_handler_req_lib_votequorum_qdisk_getinfo (void *conn, void *message)
+{
+	struct res_lib_votequorum_qdisk_getinfo res_lib_votequorum_qdisk_getinfo;
+	cs_error_t error = CS_OK;
+
+	ENTER();
+
+	if (quorum_device) {
+		log_printf(LOG_LEVEL_DEBUG, "got qdisk_getinfo state %d\n", quorum_device->state);
+		res_lib_votequorum_qdisk_getinfo.votes = quorum_device->votes;
+		if (quorum_device->state == NODESTATE_MEMBER)
+			res_lib_votequorum_qdisk_getinfo.state = 1;
+		else
+			res_lib_votequorum_qdisk_getinfo.state = 0;
+		strcpy(res_lib_votequorum_qdisk_getinfo.name, quorum_device_name);
+	}
+	else {
+		error = CS_ERR_NOT_EXIST;
+	}
+
+	/* send status */
+	res_lib_votequorum_qdisk_getinfo.header.size = sizeof(res_lib_votequorum_qdisk_getinfo);
+	res_lib_votequorum_qdisk_getinfo.header.id = MESSAGE_RES_VOTEQUORUM_GETINFO;
+	res_lib_votequorum_qdisk_getinfo.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_qdisk_getinfo, sizeof(res_lib_votequorum_qdisk_getinfo));
+
+	LEAVE();
+}
+
+static void message_handler_req_lib_votequorum_setstate (void *conn, void *message)
+{
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	cs_error_t error = CS_OK;
+
+	ENTER();
+
+	us->flags |= NODE_FLAGS_HASSTATE;
+
+	/* send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+
+	LEAVE();
+}
+
+static void message_handler_req_lib_votequorum_trackstart (void *conn, void *msg)
+{
+	struct req_lib_votequorum_trackstart *req_lib_votequorum_trackstart = (struct req_lib_votequorum_trackstart *)msg;
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+
+	ENTER();
+	/*
+	 * If an immediate listing of the current cluster membership
+	 * is requested, generate membership list
+	 */
+	if (req_lib_votequorum_trackstart->track_flags & CS_TRACK_CURRENT ||
+	    req_lib_votequorum_trackstart->track_flags & CS_TRACK_CHANGES) {
+		log_printf(LOG_LEVEL_DEBUG, "sending initial status to %p\n", conn);
+		send_quorum_notification(corosync_api->ipc_conn_partner_get (conn), req_lib_votequorum_trackstart->context);
+	}
+
+	/*
+	 * Record requests for tracking
+	 */
+	if (req_lib_votequorum_trackstart->track_flags & CS_TRACK_CHANGES ||
+	    req_lib_votequorum_trackstart->track_flags & CS_TRACK_CHANGES_ONLY) {
+
+		quorum_pd->track_flags = req_lib_votequorum_trackstart->track_flags;
+		quorum_pd->tracking_enabled = 1;
+		quorum_pd->tracking_context = req_lib_votequorum_trackstart->context;
+
+		list_add (&quorum_pd->list, &trackers_list);
+	}
+
+	/* Send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = CS_OK;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+
+	LEAVE();
+}
+
+static void message_handler_req_lib_votequorum_trackstop (void *conn, void *msg)
+{
+	struct res_lib_votequorum_status res_lib_votequorum_status;
+	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+	int error = CS_OK;
+
+	ENTER();
+
+	if (quorum_pd->tracking_enabled) {
+		error = CS_OK;
+		quorum_pd->tracking_enabled = 0;
+		list_del (&quorum_pd->list);
+		list_init (&quorum_pd->list);
+	} else {
+		error = CS_ERR_NOT_EXIST;
+	}
+
+	/* send status */
+	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
+	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
+	res_lib_votequorum_status.header.error = error;
+	corosync_api->ipc_conn_send_response(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
+
+	LEAVE();
+}
+
+
+static char *kill_reason(int reason)
+{
+	static char msg[1024];
+
+	switch (reason)
+	{
+	case VOTEQUORUM_REASON_KILL_REJECTED:
+		return "our membership application was rejected";
+
+	case VOTEQUORUM_REASON_KILL_APPLICATION:
+		return "we were killed by an application request";
+
+	case VOTEQUORUM_REASON_KILL_REJOIN:
+		return "we rejoined the cluster without a full restart";
+
+	default:
+		sprintf(msg, "we got kill message number %d", reason);
+		return msg;
+	}
+}
+
+static void reread_config(unsigned int object_handle)
+{
+	unsigned int old_votes;
+	unsigned int old_expected;
+
+	old_votes = us->votes;
+	old_expected = us->expected_votes;
+
+	/*
+	 * Reload the configuration
+	 */
+	read_quorum_config(object_handle);
+
+	/*
+	 * Check for fundamental changes that we need to propogate
+	 */
+	if (old_votes != us->votes) {
+		quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, us->node_id, us->votes);
+	}
+	if (old_expected != us->expected_votes) {
+		quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, us->expected_votes);
+	}
+}
+
+static void quorum_key_change_notify(object_change_type_t change_type,
+				     unsigned int parent_object_handle,
+				     unsigned int object_handle,
+				     void *object_name_pt, int object_name_len,
+				     void *key_name_pt, int key_len,
+				     void *key_value_pt, int key_value_len,
+				     void *priv_data_pt)
+{
+	if (memcmp(object_name_pt, "quorum", object_name_len) == 0)
+		reread_config(object_handle);
+}
+
+
+/* Called when the objdb is reloaded */
+static void votequorum_objdb_reload_notify(
+	objdb_reload_notify_type_t type, int flush,
+	void *priv_data_pt)
+{
+	/*
+	 * A new quorum {} key might exist, cancel the
+	 * existing notification at the start of reload,
+	 * and start a new one on the new object when
+	 * it's all settled.
+	 */
+
+	if (type == OBJDB_RELOAD_NOTIFY_START) {
+		corosync_api->object_track_stop(
+			quorum_key_change_notify,
+			NULL,
+			NULL,
+			NULL,
+			NULL);
+	}
+
+	if (type == OBJDB_RELOAD_NOTIFY_END ||
+	    type == OBJDB_RELOAD_NOTIFY_FAILED) {
+		unsigned int find_handle;
+		unsigned int object_handle;
+
+		corosync_api->object_find_create(OBJECT_PARENT_HANDLE, "quorum", strlen("quorum"), &find_handle);
+		if (corosync_api->object_find_next(find_handle, &object_handle) == 0) {
+			add_votequorum_config_notification(object_handle);
+
+			reread_config(object_handle);
+		}
+		else {
+			log_printf(LOG_LEVEL_ERROR, "votequorum objdb tracking stopped, cannot find quorum{} handle in objdb\n");
+		}
+	}
+}
+
+
+static void add_votequorum_config_notification(
+	unsigned int quorum_object_handle)
+{
+
+	corosync_api->object_track_start(quorum_object_handle,
+					 1,
+					 quorum_key_change_notify,
+					 NULL,
+					 NULL,
+					 NULL,
+					 NULL);
+
+	/*
+	 * Reload notify must be on the parent object
+	 */
+	corosync_api->object_track_start(OBJECT_PARENT_HANDLE,
+					 1,
+					 NULL,
+					 NULL,
+					 NULL,
+					 votequorum_objdb_reload_notify,
+					 NULL);
+}
diff -Naurd corosync-0.92/test/cpgbench.c corosync-trunk/test/cpgbench.c
--- corosync-0.92/test/cpgbench.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/test/cpgbench.c	2008-11-06 22:49:07.000000000 +0100
@@ -50,7 +50,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/cpg.h>
 
 #ifdef COROSYNC_SOLARIS
@@ -121,12 +121,12 @@
 		if (flow_control_state == CPG_FLOW_CONTROL_DISABLED) {
 retry:
 			res = cpg_mcast_joined (handle, CPG_TYPE_AGREED, &iov, 1);
-			if (res == CPG_ERR_TRY_AGAIN) {
+			if (res == CS_ERR_TRY_AGAIN) {
 				goto retry;
 			}
 		}
-		res = cpg_dispatch (handle, CPG_DISPATCH_ALL);
-		if (res != CPG_OK) {
+		res = cpg_dispatch (handle, CS_DISPATCH_ALL);
+		if (res != CS_OK) {
 			printf ("cpg dispatch returned error %d\n", res);
 			exit (1);
 		}
@@ -162,13 +162,13 @@
 	
 	signal (SIGALRM, sigalrm_handler);
 	res = cpg_initialize (&handle, &callbacks);
-	if (res != CPG_OK) {
+	if (res != CS_OK) {
 		printf ("cpg_initialize failed with result %d\n", res);
 		exit (1);
 	}
 	
 	res = cpg_join (handle, &group_name);
-	if (res != CPG_OK) {
+	if (res != CS_OK) {
 		printf ("cpg_join failed with result %d\n", res);
 		exit (1);
 	}
@@ -179,7 +179,7 @@
 	}
 
 	res = cpg_finalize (handle);
-	if (res != CPG_OK) {
+	if (res != CS_OK) {
 		printf ("cpg_join failed with result %d\n", res);
 		exit (1);
 	}
diff -Naurd corosync-0.92/test/evsbench.c corosync-trunk/test/evsbench.c
--- corosync-0.92/test/evsbench.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/test/evsbench.c	2008-11-06 22:49:07.000000000 +0100
@@ -49,7 +49,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/evs.h>
 
 #ifdef COROSYNC_SOLARIS
@@ -124,7 +124,7 @@
 	int write_size)
 {
 	struct timeval tv1, tv2, tv_elapsed;
-	evs_error_t result;
+	cs_error_t result;
 	int write_count = 0;
 
 	/*
@@ -139,12 +139,12 @@
 		if (outstanding < 10) {
 			result = evs_mcast_joined (handle, EVS_TYPE_AGREED, &iov, 1);
 
-			if (result != EVS_ERR_TRY_AGAIN) {
+			if (result != CS_ERR_TRY_AGAIN) {
 				write_count += 1;
 				outstanding++;
 			}
 		}
-		result = evs_dispatch (handle, EVS_DISPATCH_ALL);
+		result = evs_dispatch (handle, CS_DISPATCH_ALL);
 	} while (alarm_notice == 0);
 	gettimeofday (&tv2, NULL);
 	timersub (&tv2, &tv1, &tv_elapsed);
@@ -174,7 +174,7 @@
 int main (void) {
 	int size;
 	int i;
-	evs_error_t result;
+	cs_error_t result;
 	evs_handle_t handle;
 
 	signal (SIGALRM, sigalrm_handler);
diff -Naurd corosync-0.92/test/evsverify.c corosync-trunk/test/evsverify.c
--- corosync-0.92/test/evsverify.c	2008-09-25 07:31:42.000000000 +0200
+++ corosync-trunk/test/evsverify.c	2008-11-06 22:49:07.000000000 +0100
@@ -39,6 +39,7 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <string.h>
+#include <corosync/corotypes.h>
 #include <corosync/evs.h>
 #include "../exec/crypto.h"
 
@@ -112,22 +113,22 @@
 
 struct msg msg;
 
-char buffer[200000];
+unsigned char buffer[200000];
 int main (void)
 {
 	evs_handle_t handle;
-	evs_error_t result;
+	cs_error_t result;
 	unsigned int i = 0, j;
 	int fd;
 	unsigned int member_list[32];
 	unsigned int local_nodeid;
-	int member_list_entries = 32;
+	unsigned int member_list_entries = 32;
 	struct msg msg;
 	hash_state sha1_hash;
 	struct iovec iov[2];
 
 	result = evs_initialize (&handle, &callbacks);
-	if (result != EVS_OK) {
+	if (result != CS_OK) {
 		printf ("Couldn't initialize EVS service %d\n", result);
 		exit (0);
 	}
@@ -169,10 +170,10 @@
 try_again_one:
 		result = evs_mcast_joined (handle, EVS_TYPE_AGREED,
 			iov, 2);
-		if (result == EVS_ERR_TRY_AGAIN) {
+		if (result == CS_ERR_TRY_AGAIN) {
 			goto try_again_one;
 		}
-		result = evs_dispatch (handle, EVS_DISPATCH_ALL);
+		result = evs_dispatch (handle, CS_DISPATCH_ALL);
 	}
 
 	evs_fd_get (handle, &fd);
diff -Naurd corosync-0.92/test/logsysbench.c corosync-trunk/test/logsysbench.c
--- corosync-0.92/test/logsysbench.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/test/logsysbench.c	2008-10-30 23:25:56.000000000 +0100
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <corosync/engine/logsys.h>
+
+LOGSYS_DECLARE_SYSTEM ("logtest_rec",
+	LOG_MODE_OUTPUT_STDERR | LOG_MODE_THREADED,
+	NULL,
+	LOG_DAEMON,
+	"[%6s] %b",
+	100000);
+
+LOGSYS_DECLARE_NOSUBSYS(LOG_LEVEL_INFO);
+
+#define LOGREC_ID_CHECKPOINT_CREATE 2
+#define LOGREC_ARGS_CHECKPOINT_CREATE 2
+#define ITERATIONS 1000000
+
+struct timeval tv1, tv2, tv_elapsed;
+
+#define timersub(a, b, result)					\
+do {								\
+	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;		\
+	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec;	\
+	if ((result)->tv_usec < 0) {				\
+		--(result)->tv_sec;				\
+		(result)->tv_usec += 1000000;			\
+	}							\
+} while (0)
+
+void bm_start (void)
+{
+        gettimeofday (&tv1, NULL);
+}
+void bm_finish (char *operation)
+{
+        gettimeofday (&tv2, NULL);
+        timersub (&tv2, &tv1, &tv_elapsed);
+
+	if (strlen (operation) > 22) {
+        	printf ("%s\t\t", operation);
+	} else {
+        	printf ("%s\t\t\t", operation);
+	}
+        printf ("%9.3f operations/sec\n",
+                ((float)ITERATIONS) /  (tv_elapsed.tv_sec + (tv_elapsed.tv_usec / 1000000.0)));
+}
+
+char buffer[256];
+int main (void)
+{
+	int i;
+	char buf[1024];
+
+
+	printf ("heating up cache with logrec functionality\n");
+	for (i = 0; i < ITERATIONS; i++) {
+	log_rec (LOGREC_ID_CHECKPOINT_CREATE,
+		"recordA", 8, "recordB", 8, LOG_REC_END);
+	}
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+	log_rec (LOGREC_ID_CHECKPOINT_CREATE,
+		buffer, 7, LOG_REC_END);
+	}
+	bm_finish ("log_rec 1 arguments:");
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+	log_rec (LOGREC_ID_CHECKPOINT_CREATE,
+		"recordA", 8, LOG_REC_END);
+	}
+	bm_finish ("log_rec 2 arguments:");
+	bm_start();
+	for (i = 0; i < 10; i++) {
+	log_rec (LOGREC_ID_CHECKPOINT_CREATE,
+		"recordA", 8, "recordB", 8, LOG_REC_END);
+	}
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+	log_rec (LOGREC_ID_CHECKPOINT_CREATE,
+		"recordA", 8, "recordB", 8, "recordC", 8, LOG_REC_END);
+	}
+	bm_finish ("log_rec 3 arguments:");
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+	log_rec (LOGREC_ID_CHECKPOINT_CREATE,
+		"recordA", 8, "recordB", 8, "recordC", 8, "recordD", 8, LOG_REC_END);
+	}
+	bm_finish ("log_rec 4 arguments:");
+
+	/*
+	 * sprintf testing
+	 */
+	printf ("heating up cache with sprintf functionality\n");
+	for (i = 0; i < ITERATIONS; i++) {
+		sprintf (buf, "Some logging information %s", "recordA");
+	}
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+		sprintf (buf, "Some logging information %s", "recordA");
+	}
+	bm_finish ("sprintf 1 argument:");
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+		sprintf (buf, "Some logging information %s %s", "recordA", "recordB");
+	}
+	bm_finish ("sprintf 2 arguments:");
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+		sprintf (buf, "Some logging information %s %s %s", "recordA", "recordB", "recordC");
+	}
+	bm_finish ("sprintf 3 arguments:");
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+		sprintf (buf, "Some logging information %s %s %s %s", "recordA", "recordB", "recordC", "recordD");
+	}
+	bm_finish ("sprintf 4 arguments:");
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+		sprintf (buf, "Some logging information %s %s %s %d", "recordA", "recordB", "recordC", i);
+	}
+	bm_finish ("sprintf 4 arguments (1 int):");
+
+	logsys_log_rec_store ("fdata");
+/* TODO
+	currently fails under some circumstances
+
+	bm_start();
+	for (i = 0; i < ITERATIONS; i++) {
+	log_printf (LOG_LEVEL_NOTICE, "test %d", i);
+	}
+	bm_finish("log_printf");
+*/
+
+	return (0);
+}
diff -Naurd corosync-0.92/test/logsysrec.c corosync-trunk/test/logsysrec.c
--- corosync-0.92/test/logsysrec.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/test/logsysrec.c	2008-10-30 23:25:56.000000000 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <corosync/engine/logsys.h>
+
+LOGSYS_DECLARE_SYSTEM ("logtest_rec",
+	LOG_MODE_OUTPUT_STDERR | LOG_MODE_THREADED,
+	NULL,
+	LOG_DAEMON,
+	"[%6s] %b",
+	100000);
+
+LOGSYS_DECLARE_NOSUBSYS(LOG_LEVEL_INFO);
+
+#define LOGREC_ID_CHECKPOINT_CREATE 2
+#define LOGREC_ARGS_CHECKPOINT_CREATE 2
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		log_printf (LOG_LEVEL_NOTICE, "This is a test of %s\n", "stringparse");
+
+		log_rec (LOGREC_ID_CHECKPOINT_CREATE, "record1", 8, "record22", 9, "record333", 10, "record444", 11, LOG_REC_END);
+	}
+	logsys_log_rec_store ("fdata");
+
+	return 0;
+}
diff -Naurd corosync-0.92/test/logsys_s.c corosync-trunk/test/logsys_s.c
--- corosync-0.92/test/logsys_s.c	2008-05-12 15:48:06.000000000 +0200
+++ corosync-trunk/test/logsys_s.c	2008-10-30 23:25:56.000000000 +0100
@@ -38,7 +38,9 @@
 LOGSYS_DECLARE_SYSTEM ("logsystestsubsystems",
 	LOG_MODE_OUTPUT_STDERR | LOG_MODE_OUTPUT_SYSLOG_THREADED, 
 	NULL,
-	LOG_DAEMON);
+	LOG_DAEMON,
+	"[%8s] %b",
+	100000);
 
 extern void logsys_s1_print (void);
 extern void logsys_s2_print (void);
diff -Naurd corosync-0.92/test/logsys_t1.c corosync-trunk/test/logsys_t1.c
--- corosync-0.92/test/logsys_t1.c	2008-06-20 08:04:03.000000000 +0200
+++ corosync-trunk/test/logsys_t1.c	2008-10-30 23:25:56.000000000 +0100
@@ -38,7 +38,9 @@
 LOGSYS_DECLARE_SYSTEM ("logsystestNOsubsystems",
 	LOG_MODE_OUTPUT_STDERR | LOG_MODE_OUTPUT_SYSLOG_THREADED, 
 	NULL,
-	LOG_DAEMON);
+	LOG_DAEMON,
+	"%6s %b",
+	100000);
 
 LOGSYS_DECLARE_NOSUBSYS(LOG_LEVEL_DEBUG);
 
diff -Naurd corosync-0.92/test/logsys_t2.c corosync-trunk/test/logsys_t2.c
--- corosync-0.92/test/logsys_t2.c	2008-06-20 08:04:03.000000000 +0200
+++ corosync-trunk/test/logsys_t2.c	2008-10-30 23:25:56.000000000 +0100
@@ -36,9 +36,11 @@
 #include "../exec/logsys.h"
 
 LOGSYS_DECLARE_SYSTEM ("logtest_t2",
-	LOG_MODE_OUTPUT_STDERR | LOG_MODE_OUTPUT_SYSLOG_THREADED | LOG_MODE_BUFFER_BEFORE_CONFIG,
+	LOG_MODE_OUTPUT_STDERR | LOG_MODE_THREADED,
 	NULL,
-	LOG_DAEMON);
+	LOG_DAEMON,
+	"[%6s] %b"
+	100000);
 
 LOGSYS_DECLARE_NOSUBSYS(LOG_LEVEL_INFO);
 
@@ -48,7 +50,7 @@
 	/*
 	 * fork could occur here and the file to output to could be set
 	 */
-	logsys_config_mode_set (LOG_MODE_OUTPUT_STDERR | LOG_MODE_OUTPUT_SYSLOG_THREADED | LOG_MODE_FLUSH_AFTER_CONFIG);
+	logsys_config_mode_set (LOG_MODE_OUTPUT_STDERR | LOG_MODE_THREADED);
 
 	log_printf(LOG_NOTICE, "Hello, world!\n");
 	log_printf(LOG_DEBUG, "If you see this, the logger's busted\n");
diff -Naurd corosync-0.92/test/Makefile corosync-trunk/test/Makefile
--- corosync-0.92/test/Makefile	2008-09-25 07:31:42.000000000 +0200
+++ corosync-trunk/test/Makefile	2009-01-26 11:46:08.000000000 +0100
@@ -42,9 +42,10 @@
 	override LDFLAGS += -lnsl -lsocket -lrt
 endif
 
-LIBRARIES= ../lib/libevs.a ../lib/libcpg.a ../lib/libcfg.a ../lib/libconfdb.a
+LIBRARIES= ../lib/libevs.a ../lib/libcpg.a ../lib/libcfg.a ../lib/libconfdb.a ../lib/libquorum.a ../lib/libvotequorum.a
 LIBS = $(LIBRARIES) 
-BINARIES= testevs evsbench evsverify testcpg testcpg2 cpgbench testconfdb
+BINARIES= testevs evsbench evsverify testcpg testcpg2 cpgbench testconfdb logsysbench logsysrec testquorum \
+	testvotequorum1 testvotequorum2
 
 override CFLAGS += -I../include
 override LDFLAGS += -L../lib
@@ -75,12 +76,33 @@
 testcpg2: testcpg2.o $(LIBRARIES)
 	$(CC) $(LDFLAGS) -o testcpg2 testcpg2.o $(LIBS)
 
+testquorum: testquorum.o $(LIBRARIES)
+	$(CC) $(LDFLAGS) -o testquorum testquorum.o $(LIBS)
+
 cpgbench: cpgbench.o $(LIBRARIES)
 	$(CC) $(LDFLAGS) -o cpgbench cpgbench.o $(LIBS)
 
 testconfdb: testconfdb.o $(LIBRARIES)
 	$(CC) $(LDFLAGS) -o testconfdb testconfdb.o $(LIBS) -rdynamic
 
+logsysbench: logsysbench.o ../exec/liblogsys.a
+	$(CC) -o logsysbench logsysbench.o ../exec/liblogsys.a $(LDFLAGS)
+
+logsysrec: logsysrec.o ../exec/liblogsys.a
+	$(CC) -o logsysrec logsysrec.o ../exec/liblogsys.a $(LDFLAGS)
+
+testquorum1: testquorum1.o $(LIBRARIES)
+	$(CC) $(LDFLAGS) -o testquorum1 testquorum1.o $(LIBS)
+
+testquorum2: testquorum2.o $(LIBRARIES)
+	$(CC) $(LDFLAGS) -o testquorum2 testquorum2.o $(LIBS)
+
+testvotequorum1: testvotequorum1.o $(LIBRARIES)
+	$(CC) $(LDFLAGS) -o testvotequorum1 testvotequorum1.o $(LIBS)
+
+testvotequorum2: testvotequorum2.o $(LIBRARIES)
+	$(CC) $(LDFLAGS) -o testvotequorum2 testvotequorum2.o $(LIBS)
+
 logsys_s: logsys_s.o logsys_s1.o logsys_s2.o ../exec/liblogsys.a
 	$(CC) -o logsys_s logsys_s.o logsys_s1.o logsys_s2.o ../exec/liblogsys.a $(LDFLAGS)
 
diff -Naurd corosync-0.92/test/sa_error.c corosync-trunk/test/sa_error.c
--- corosync-0.92/test/sa_error.c	2006-01-24 08:19:11.000000000 +0100
+++ corosync-trunk/test/sa_error.c	2008-11-06 22:49:07.000000000 +0100
@@ -6,39 +6,39 @@
 
 const char *sa_error_list[] = {
 	"OUT_OF_RANGE",
-	"SA_AIS_OK",
-	"SA_AIS_ERR_LIBRARY",
-	"SA_AIS_ERR_VERSION",
-	"SA_AIS_ERR_INIT",
-	"SA_AIS_ERR_TIMEOUT",
-	"SA_AIS_ERR_TRY_AGAIN",
-	"SA_AIS_ERR_INVALID_PARAM",
-	"SA_AIS_ERR_NO_MEMORY",
-	"SA_AIS_ERR_BAD_HANDLE",
-	"SA_AIS_ERR_BUSY",
-	"SA_AIS_ERR_ACCESS",
-	"SA_AIS_ERR_NOT_EXIST",
-	"SA_AIS_ERR_NAME_TOO_LONG",
-	"SA_AIS_ERR_EXIST",
-	"SA_AIS_ERR_NO_SPACE",
-	"SA_AIS_ERR_INTERRUPT",
-	"SA_AIS_ERR_NAME_NOT_FOUND",
-	"SA_AIS_ERR_NO_RESOURCES",
-	"SA_AIS_ERR_NOT_SUPPORTED",
-	"SA_AIS_ERR_BAD_OPERATION",
-	"SA_AIS_ERR_FAILED_OPERATION",
-	"SA_AIS_ERR_MESSAGE_ERROR",
-	"SA_AIS_ERR_QUEUE_FULL",
-	"SA_AIS_ERR_QUEUE_NOT_AVAILABLE",
-	"SA_AIS_ERR_BAD_CHECKPOINT",
-	"SA_AIS_ERR_BAD_FLAGS",
-	"SA_AIS_ERR_NO_SECTIONS",
+	"CS_OK",
+	"CS_ERR_LIBRARY",
+	"CS_ERR_VERSION",
+	"CS_ERR_INIT",
+	"CS_ERR_TIMEOUT",
+	"CS_ERR_TRY_AGAIN",
+	"CS_ERR_INVALID_PARAM",
+	"CS_ERR_NO_MEMORY",
+	"CS_ERR_BAD_HANDLE",
+	"CS_ERR_BUSY",
+	"CS_ERR_ACCESS",
+	"CS_ERR_NOT_EXIST",
+	"CS_ERR_NAME_TOO_LONG",
+	"CS_ERR_EXIST",
+	"CS_ERR_NO_SPACE",
+	"CS_ERR_INTERRUPT",
+	"CS_ERR_NAME_NOT_FOUND",
+	"CS_ERR_NO_RESOURCES",
+	"CS_ERR_NOT_SUPPORTED",
+	"CS_ERR_BAD_OPERATION",
+	"CS_ERR_FAILED_OPERATION",
+	"CS_ERR_MESSAGE_ERROR",
+	"CS_ERR_QUEUE_FULL",
+	"CS_ERR_QUEUE_NOT_AVAILABLE",
+	"CS_ERR_BAD_CHECKPOINT",
+	"CS_ERR_BAD_FLAGS",
+	"CS_ERR_NO_SECTIONS",
 };
 
-int get_sa_error(SaAisErrorT error, char *str, int len)
+int get_sa_error(cs_error_t error, char *str, int len)
 {
-	if (error < SA_AIS_OK || 
-			error > SA_AIS_ERR_NO_SECTIONS || 
+	if (error < CS_OK || 
+			error > CS_ERR_NO_SECTIONS || 
 					len < strlen(sa_error_list[error])) {
 			errno = EINVAL;
 		return -1;
@@ -47,11 +47,11 @@
 	return 0;
 }
 
-char *get_sa_error_b (SaAisErrorT error) {
+char *get_sa_error_b (cs_error_t error) {
 	return ((char *)sa_error_list[error]);
 }
 
-char *get_test_output (SaAisErrorT result, SaAisErrorT expected) {
+char *get_test_output (cs_error_t result, cs_error_t expected) {
 static char test_result[256];
 
         if (result == expected) {
diff -Naurd corosync-0.92/test/sa_error.h corosync-trunk/test/sa_error.h
--- corosync-0.92/test/sa_error.h	2006-01-24 08:19:11.000000000 +0100
+++ corosync-trunk/test/sa_error.h	2008-11-06 22:49:07.000000000 +0100
@@ -1,5 +1,5 @@
-extern int get_sa_error(SaAisErrorT error, char *str, int len);
+extern int get_sa_error(cs_error_t error, char *str, int len);
 
-extern char *get_sa_error_b (SaAisErrorT error);
+extern char *get_sa_error_b (cs_error_t error);
 
-extern char *get_test_output (SaAisErrorT result, SaAisErrorT expected);
+extern char *get_test_output (cs_error_t result, cs_error_t expected);
diff -Naurd corosync-0.92/test/testconfdb.c corosync-trunk/test/testconfdb.c
--- corosync-0.92/test/testconfdb.c	2008-09-03 09:58:08.000000000 +0200
+++ corosync-trunk/test/testconfdb.c	2008-11-06 22:49:07.000000000 +0100
@@ -41,7 +41,7 @@
 #include <sys/types.h>
 #include <sys/un.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/confdb.h>
 
 #define INCDEC_VALUE 45
@@ -68,13 +68,13 @@
 
 	/* Show the keys */
 	res = confdb_key_iter_start(handle, parent_object_handle);
-	if (res != SA_AIS_OK) {
+	if (res != CS_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_value, &key_value_len)) == CS_OK) {
 		key_name[key_name_len] = '\0';
 		key_value[key_value_len] = '\0';
 		for (i=0; i<depth; i++)	printf("  ");
@@ -83,16 +83,16 @@
 
 	/* Show sub-objects */
 	res = confdb_object_iter_start(handle, parent_object_handle);
-	if (res != SA_AIS_OK) {
+	if (res != CS_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)	{
+	while ( (res = confdb_object_iter(handle, parent_object_handle, &object_handle, object_name, &object_name_len)) == CS_OK)	{
 		unsigned int parent;
 
 		res = confdb_object_parent_get(handle, object_handle, &parent);
-		if (res != SA_AIS_OK) {
+		if (res != CS_OK) {
 			printf( "error getting parent for object %d: %d\n", object_handle, res);
 			return;
 		}
@@ -116,25 +116,25 @@
 
 	/* 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) {
+	if (res != CS_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) {
+	if (res != CS_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) {
+	if (res != CS_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) {
+	if (res != CS_OK) {
 		printf( "error creating 'testconfdb' key 3: %d\n", res);
 		return;
 	}
@@ -142,7 +142,7 @@
 	res = confdb_key_replace(handle, object_handle, "testkey", strlen("testkey"), "two", strlen("two"),
 				 "newtwo", strlen("newtwo"));
 
-	if (res != SA_AIS_OK) {
+	if (res != CS_OK) {
 		printf( "error replace 'testconfdb' key 2: %d\n", res);
 		return;
 	}
@@ -152,12 +152,12 @@
 
 	incdec_value = INCDEC_VALUE;
 	res = confdb_key_create(handle, object_handle, "incdec", strlen("incdec"), &incdec_value, sizeof(incdec_value));
-	if (res != SA_AIS_OK) {
+	if (res != CS_OK) {
 		printf( "error creating 'testconfdb' key 4: %d\n", res);
 		return;
 	}
 	res = confdb_key_increment(handle, object_handle, "incdec", strlen("incdec"), &incdec_value);
-	if (res != SA_AIS_OK) {
+	if (res != CS_OK) {
 		printf( "error incrementing 'testconfdb' key 4: %d\n", res);
 		return;
 	}
@@ -167,7 +167,7 @@
 		printf("ERROR: incremented value = %d (should be %d)\n", incdec_value, INCDEC_VALUE+1);
 
 	res = confdb_key_decrement(handle, object_handle, "incdec", strlen("incdec"), &incdec_value);
-	if (res != SA_AIS_OK) {
+	if (res != CS_OK) {
 		printf( "error decrementing 'testconfdb' key 4: %d\n", res);
 		return;
 	}
@@ -181,7 +181,7 @@
 	/* 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) {
+	if (res != CS_OK) {
 		printf( "error destroying 'testconfdb' object: %d\n", res);
 		return;
 	}
@@ -199,7 +199,7 @@
 	int value_len;
 
 	result = confdb_initialize (&handle, &callbacks);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not initialize Cluster Configuration Database API instance error %d\n", result);
 		exit (1);
 	}
@@ -221,19 +221,19 @@
 
 	/* 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) {
+	if (result != CS_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) {
+	if (result != CS_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) {
+	if (result != CS_OK) {
 		printf ("Could not get \"version\" key: %d\n", result);
 		exit (1);
 	}
@@ -241,7 +241,7 @@
 	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) {
+	if (result != CS_OK) {
 		printf ("Could not get \"secauth\" key: %d\n", result);
 		exit (1);
 	}
diff -Naurd corosync-0.92/test/testcpg2.c corosync-trunk/test/testcpg2.c
--- corosync-0.92/test/testcpg2.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/test/testcpg2.c	2008-11-06 22:49:07.000000000 +0100
@@ -37,6 +37,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
+#include <corosync/corotypes.h>
 #include <corosync/cpg.h>
 
 void deliver(
@@ -70,17 +71,17 @@
 	int fd;
 
 	printf ("All of the nodeids should match on a single node configuration\n for the test to pass.");
-	assert(CPG_OK==cpg_initialize(&handle, &cb));
-	assert(CPG_OK==cpg_local_get(handle,&nodeid));
+	assert(CS_OK==cpg_initialize(&handle, &cb));
+	assert(CS_OK==cpg_local_get(handle,&nodeid));
 	printf("local_get: %x\n", nodeid);
-	assert(CPG_OK==cpg_join(handle, &group));
+	assert(CS_OK==cpg_join(handle, &group));
 	struct iovec msg={"hello", 5};
-	assert(CPG_OK==cpg_mcast_joined(handle,CPG_TYPE_AGREED,&msg,1));
+	assert(CS_OK==cpg_mcast_joined(handle,CPG_TYPE_AGREED,&msg,1));
 	cpg_fd_get (handle, &fd);
 	pfd.fd = fd;
 	pfd.events = POLLIN;
 		
 	poll (&pfd, 1, 1000);
-	cpg_dispatch(handle, CPG_DISPATCH_ALL);
+	cpg_dispatch(handle, CS_DISPATCH_ALL);
 	return (0);
 }
diff -Naurd corosync-0.92/test/testcpg.c corosync-trunk/test/testcpg.c
--- corosync-0.92/test/testcpg.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/test/testcpg.c	2008-11-06 22:49:07.000000000 +0100
@@ -45,7 +45,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/cpg.h>
 
 static int quit = 0;
@@ -206,25 +206,25 @@
 	}
 
 	result = cpg_initialize (&handle, &callbacks);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not initialize Cluster Process Group API instance error %d\n", result);
 		exit (1);
 	}
 	result = cpg_local_get (handle, &nodeid);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not get local node id\n");
 		exit (1);
 	}
 
 	printf ("Local node id is %x\n", nodeid);
 	result = cpg_join(handle, &group_name);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not join process group, error %d\n", result);
 		exit (1);
 	}
 
 	cpg_groups_get(handle, &num_groups);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not get list of groups, error %d\n", result);
 		exit (1);
 	}
@@ -255,7 +255,7 @@
 			}
 		}
 		if (FD_ISSET (select_fd, &read_fds)) {
-			if (cpg_dispatch (handle, CPG_DISPATCH_ALL) != SA_AIS_OK)
+			if (cpg_dispatch (handle, CS_DISPATCH_ALL) != CS_OK)
 				exit(1);
 		}
 	} while (result && !quit);
diff -Naurd corosync-0.92/test/testevs.c corosync-trunk/test/testevs.c
--- corosync-0.92/test/testevs.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/test/testevs.c	2008-11-06 22:49:07.000000000 +0100
@@ -38,6 +38,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <errno.h>
+#include <corosync/corotypes.h>
 #include <corosync/evs.h>
 
 char *delivery_string;
@@ -99,7 +100,7 @@
 int main (void)
 {
 	evs_handle_t handle;
-	evs_error_t result;
+	cs_error_t result;
 	int i = 0;
 	int fd;
 	unsigned int member_list[32];
@@ -107,7 +108,7 @@
 	unsigned int member_list_entries = 32;
 
 	result = evs_initialize (&handle, &callbacks);
-	if (result != EVS_OK) {
+	if (result != CS_OK) {
 		printf ("Couldn't initialize EVS service %d\n", result);
 		exit (0);
 	}
@@ -142,15 +143,15 @@
 try_again_one:
 		result = evs_mcast_joined (handle, EVS_TYPE_AGREED,
 			&iov, 1);
-		if (result == EVS_ERR_TRY_AGAIN) {
+		if (result == CS_ERR_TRY_AGAIN) {
 //printf ("try again\n");
 			goto try_again_one;
 		}
-		result = evs_dispatch (handle, EVS_DISPATCH_ALL);
+		result = evs_dispatch (handle, CS_DISPATCH_ALL);
 	}
 
 	do {
-		result = evs_dispatch (handle, EVS_DISPATCH_ALL);
+		result = evs_dispatch (handle, CS_DISPATCH_ALL);
 	} while (deliveries < 20);
 	/*
 	 * Demonstrate evs_mcast_joined
@@ -161,17 +162,17 @@
 try_again_two:
 		result = evs_mcast_groups (handle, EVS_TYPE_AGREED,
 			 &groups[1], 1, &iov, 1);
-		if (result == EVS_ERR_TRY_AGAIN) {
+		if (result == CS_ERR_TRY_AGAIN) {
 			goto try_again_two;
 		}
 	
-		result = evs_dispatch (handle, EVS_DISPATCH_ALL);
+		result = evs_dispatch (handle, CS_DISPATCH_ALL);
 	}
 	/*
 	 * Flush any pending callbacks
 	 */
 	do {
-		result = evs_dispatch (handle, EVS_DISPATCH_ALL);
+		result = evs_dispatch (handle, CS_DISPATCH_ALL);
 	} while (deliveries < 500);
 
 	evs_fd_get (handle, &fd);
diff -Naurd corosync-0.92/test/testquorum.c corosync-trunk/test/testquorum.c
--- corosync-0.92/test/testquorum.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/test/testquorum.c	2008-11-06 22:49:07.000000000 +0100
@@ -0,0 +1,58 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <corosync/corotypes.h>
+#include <corosync/quorum.h>
+
+static quorum_handle_t handle;
+
+static void quorum_notification_fn(
+	quorum_handle_t handle,
+	uint32_t quorate,
+	uint64_t ring_id,
+	uint32_t view_list_entries,
+	uint32_t *view_list)
+{
+	int i;
+
+	printf("quorum notification called \n");
+	printf("  quorate   = %d\n", quorate);
+	printf("  ring id   = %lld\n", ring_id);
+	printf("  num nodes = %d ", view_list_entries);
+
+	for (i=0; i<view_list_entries; i++) {
+		printf(" %d ", view_list[i]);
+	}
+	printf("\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+	int quorate;
+	quorum_callbacks_t callbacks;
+	int err;
+
+	callbacks.quorum_notify_fn = quorum_notification_fn;
+	if ( (err=quorum_initialize(&handle, &callbacks)) != CS_OK)
+		fprintf(stderr, "quorum_initialize FAILED: %d\n", err);
+
+	if ( (err=quorum_trackstart(handle, CS_TRACK_CHANGES)) != CS_OK)
+		fprintf(stderr, "quorum_trackstart FAILED: %d\n", err);
+
+	if ( (err=quorum_getquorate(handle, &quorate)) != CS_OK)
+		fprintf(stderr, "quorum_getquorate FAILED: %d\n", err);
+	else {
+		printf("quorate   %d\n", quorate);
+	}
+
+	printf("Waiting for quorum events, press ^C to finish\n");
+	printf("-------------------\n");
+
+	while (1)
+		quorum_dispatch(handle, CS_DISPATCH_ALL);
+
+	return 0;
+}
diff -Naurd corosync-0.92/test/testvotequorum1.c corosync-trunk/test/testvotequorum1.c
--- corosync-0.92/test/testvotequorum1.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/test/testvotequorum1.c	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <corosync/corotypes.h>
+#include <corosync/votequorum.h>
+
+static votequorum_handle_t handle;
+
+static char *node_state(int state)
+{
+	switch (state) {
+	case NODESTATE_JOINING:
+		return "Joining";
+		break;
+	case NODESTATE_MEMBER:
+		return "Member";
+		break;
+	case NODESTATE_DEAD:
+		return "Dead";
+		break;
+	case NODESTATE_LEAVING:
+		return "Leaving";
+		break;
+	case NODESTATE_DISALLOWED:
+		return "Disallowed";
+		break;
+	default:
+		return "UNKNOWN";
+		break;
+	}
+}
+
+static void votequorum_notification_fn(
+	votequorum_handle_t handle,
+	uint64_t context,
+	uint32_t quorate,
+	uint32_t node_list_entries,
+	votequorum_node_t node_list[]
+	)
+{
+	int i;
+
+	printf("votequorum notification called \n");
+	printf("  quorate         = %d\n", quorate);
+	printf("  number of nodes = %d\n", node_list_entries);
+
+	for (i = 0; i< node_list_entries; i++) {
+		printf("      %d: %s\n", node_list[i].nodeid, node_state(node_list[i].state));
+	}
+	printf("\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+	struct votequorum_info info;
+	votequorum_callbacks_t callbacks;
+	int err;
+
+	if (argc > 1 && strcmp(argv[1], "-h")==0) {
+		fprintf(stderr, "usage: %s [new-expected] [new-votes]\n", argv[0]);
+		return 0;
+	}
+
+	callbacks.votequorum_notify_fn = votequorum_notification_fn;
+	if ( (err=votequorum_initialize(&handle, &callbacks)) != CS_OK)
+		fprintf(stderr, "votequorum_initialize FAILED: %d\n", err);
+
+	if ( (err = votequorum_trackstart(handle, handle, CS_TRACK_CHANGES)) != CS_OK)
+		fprintf(stderr, "votequorum_trackstart FAILED: %d\n", err);
+
+	if ( (err=votequorum_getinfo(handle, 0, &info)) != CS_OK)
+		fprintf(stderr, "votequorum_getinfo FAILED: %d\n", err);
+	else {
+		printf("node votes       %d\n", info.node_votes);
+		printf("expected votes   %d\n", info.node_expected_votes);
+		printf("highest expected %d\n", info.highest_expected);
+		printf("total votes      %d\n", info.total_votes);
+		printf("quorum           %d\n", info.quorum);
+		printf("flags            ");
+		if (info.flags & VOTEQUORUM_INFO_FLAG_HASSTATE) printf("HasState ");
+		if (info.flags & VOTEQUORUM_INFO_FLAG_DISALLOWED) printf("Disallowed ");
+		if (info.flags & VOTEQUORUM_INFO_FLAG_TWONODE) printf("2Node ");
+		if (info.flags & VOTEQUORUM_INFO_FLAG_QUORATE) printf("Quorate ");
+		printf("\n");
+	}
+
+	if (argc >= 2 && atoi(argv[1])) {
+		if ( (err=votequorum_setexpected(handle, atoi(argv[1]))) != CS_OK)
+			fprintf(stderr, "set expected votes FAILED: %d\n", err);
+	}
+	if (argc >= 3 && atoi(argv[2])) {
+		if ( (err=votequorum_setvotes(handle, 0, atoi(argv[2]))) != CS_OK)
+			fprintf(stderr, "set votes FAILED: %d\n", err);
+	}
+
+	if (argc >= 2) {
+		if ( (err=votequorum_getinfo(handle, 0, &info)) != CS_OK)
+			fprintf(stderr, "votequorum_getinfo2 FAILED: %d\n", err);
+		else {
+			printf("-------------------\n");
+			printf("node votes       %d\n", info.node_votes);
+			printf("expected votes   %d\n", info.node_expected_votes);
+			printf("highest expected %d\n", info.highest_expected);
+			printf("total votes      %d\n", info.total_votes);
+			printf("votequorum           %d\n", info.quorum);
+			printf("flags            ");
+			if (info.flags & VOTEQUORUM_INFO_FLAG_HASSTATE) printf("HasState ");
+			if (info.flags & VOTEQUORUM_INFO_FLAG_DISALLOWED) printf("Disallowed ");
+			if (info.flags & VOTEQUORUM_INFO_FLAG_TWONODE) printf("2Node ");
+			if (info.flags & VOTEQUORUM_INFO_FLAG_QUORATE) printf("Quorate ");
+			printf("\n");
+		}
+	}
+
+	printf("Waiting for votequorum events, press ^C to finish\n");
+	printf("-------------------\n");
+
+	while (1)
+		votequorum_dispatch(handle, CS_DISPATCH_ALL);
+
+	return 0;
+}
diff -Naurd corosync-0.92/test/testvotequorum2.c corosync-trunk/test/testvotequorum2.c
--- corosync-0.92/test/testvotequorum2.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/test/testvotequorum2.c	2009-01-26 11:46:08.000000000 +0100
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield (ccaulfie@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <corosync/corotypes.h>
+#include <corosync/votequorum.h>
+
+static votequorum_handle_t handle;
+
+
+static void print_info(int ok_to_fail)
+{
+	struct votequorum_qdisk_info qinfo;
+	int err;
+
+	if ( (err=votequorum_qdisk_getinfo(handle, &qinfo)) != CS_OK)
+		fprintf(stderr, "votequorum_qdisk_getinfo error %d: %s\n", err, ok_to_fail?"OK":"FAILED");
+	else {
+		printf("qdisk votes  %d\n", qinfo.votes);
+		printf("state        %d\n", qinfo.state);
+		printf("name         %s\n", qinfo.name);
+		printf("\n");
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	int pollcount=0, polltime=1;
+	int err;
+
+	if ( (err=votequorum_initialize(&handle, NULL)) != CS_OK) {
+		fprintf(stderr, "votequorum_initialize FAILED: %d\n", err);
+		return -1;
+	}
+
+	print_info(1);
+
+	if (argc >= 2 && atoi(argv[1])) {
+		pollcount = atoi(argv[1]);
+	}
+	if (argc >= 3 && atoi(argv[2])) {
+		polltime = atoi(argv[2]);
+	}
+
+	if (argc >= 2) {
+		if ( (err=votequorum_qdisk_register(handle, "QDISK", 4)) != CS_OK)
+			fprintf(stderr, "qdisk_register FAILED: %d\n", err);
+
+		while (pollcount--) {
+			print_info(0);
+			if ((err=votequorum_qdisk_poll(handle, 1)) != CS_OK)
+				fprintf(stderr, "qdisk poll FAILED: %d\n", err);
+			print_info(0);
+			sleep(polltime);
+		}
+		if ((err= votequorum_qdisk_unregister(handle)) != CS_OK)
+			fprintf(stderr, "qdisk unregister FAILED: %d\n", err);
+	}
+	print_info(1);
+
+	return 0;
+}
diff -Naurd corosync-0.92/tools/corosync-cfgtool.c corosync-trunk/tools/corosync-cfgtool.c
--- corosync-0.92/tools/corosync-cfgtool.c	2008-08-14 18:54:46.000000000 +0200
+++ corosync-trunk/tools/corosync-cfgtool.c	2009-01-19 09:31:21.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2007 Red Hat, Inc.
+ * Copyright (c) 2006-2009 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -38,6 +38,7 @@
 #include <signal.h>
 #include <unistd.h>
 #include <string.h>
+#include <pthread.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/select.h>
@@ -45,12 +46,13 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
+#include <corosync/totem/totem.h>
 #include <corosync/cfg.h>
 
 static void ringstatusget_do (void)
 {
-	SaAisErrorT result;
+	cs_error_t result;
 	corosync_cfg_handle_t handle;
 	unsigned int interface_count;
 	char **interface_names;
@@ -59,84 +61,199 @@
 
 	printf ("Printing ring status.\n");
 	result = corosync_cfg_initialize (&handle, NULL);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not initialize corosync configuration API error %d\n", result);
 		exit (1);
 	}
 
-	corosync_cfg_ring_status_get (handle,
-		&interface_names,
-		&interface_status,
-		&interface_count);
-
-	for (i = 0; i < interface_count; i++) {
-		printf ("RING ID %d\n", i);
-		printf ("\tid\t= %s\n", interface_names[i]);
-		printf ("\tstatus\t= %s\n", interface_status[i]);
+	result = corosync_cfg_ring_status_get (handle,
+				&interface_names,
+				&interface_status,
+				&interface_count);
+	if (result != CS_OK) {
+		printf ("Could not get the ring status, the error is: %d\n", result);
+	} else {
+		for (i = 0; i < interface_count; i++) {
+			printf ("RING ID %d\n", i);
+			printf ("\tid\t= %s\n", interface_names[i]);
+			printf ("\tstatus\t= %s\n", interface_status[i]);
+		}
 	}
-
-	corosync_cfg_finalize (handle);
+	(void)corosync_cfg_finalize (handle);
 }
 
 static void ringreenable_do (void)
 {
-	SaAisErrorT result;
+	cs_error_t result;
 	corosync_cfg_handle_t handle;
 
 	printf ("Re-enabling all failed rings.\n");
 	result = corosync_cfg_initialize (&handle, NULL);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not initialize corosync configuration API error %d\n", result);
 		exit (1);
 	}
 
 	result = corosync_cfg_ring_reenable (handle);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not reenable ring error %d\n", result);
 	}
 
-	corosync_cfg_finalize (handle);
+	(void)corosync_cfg_finalize (handle);
 }
 
 void service_load_do (char *service, unsigned int version)
 {
-	SaAisErrorT result;
+	cs_error_t result;
 	corosync_cfg_handle_t handle;
 
 	printf ("Loading service '%s' version '%d'\n", service, version);
 	result = corosync_cfg_initialize (&handle, NULL);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not initialize corosync configuration API error %d\n", result);
 		exit (1);
 	}
 	result = corosync_cfg_service_load (handle, service, version);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not load service (error = %d)\n", result);
 	}
-	corosync_cfg_finalize (handle);
+	(void)corosync_cfg_finalize (handle);
 }
 
 void service_unload_do (char *service, unsigned int version)
 {
-	SaAisErrorT result;
+	cs_error_t result;
 	corosync_cfg_handle_t handle;
 
 	printf ("Unloading service '%s' version '%d'\n", service, version);
 	result = corosync_cfg_initialize (&handle, NULL);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not initialize corosync configuration API error %d\n", result);
 		exit (1);
 	}
 	result = corosync_cfg_service_unload (handle, service, version);
-	if (result != SA_AIS_OK) {
+	if (result != CS_OK) {
 		printf ("Could not unload service (error = %d)\n", result);
 	}
-	corosync_cfg_finalize (handle);
+	(void)corosync_cfg_finalize (handle);
+}
+
+void shutdown_callback (corosync_cfg_handle_t cfg_handle, corosync_cfg_shutdown_flags_t flags)
+{
+	printf("shutdown callback called, flags = %d\n",flags);
+
+	(void)corosync_cfg_replyto_shutdown (cfg_handle, COROSYNC_CFG_SHUTDOWN_FLAG_YES);
+}
+
+void *shutdown_dispatch_thread(void *arg)
+{
+	int res = CS_OK;
+	corosync_cfg_handle_t *handle = arg;
+
+	while (res == CS_OK) {
+		res = corosync_cfg_dispatch(*handle, CS_DISPATCH_ALL);
+		if (res != CS_OK)
+			printf ("Could not dispatch cfg messages: %d\n", res);
+	}
+	return NULL;
+}
+
+void shutdown_do()
+{
+	cs_error_t result;
+	corosync_cfg_handle_t handle;
+	corosync_cfg_callbacks_t callbacks;
+	corosync_cfg_state_notification_t notification_buffer;
+	pthread_t dispatch_thread;
+
+	printf ("Shutting down corosync\n");
+	callbacks.corosync_cfg_shutdown_callback = shutdown_callback;
+
+	result = corosync_cfg_initialize (&handle, &callbacks);
+	if (result != CS_OK) {
+		printf ("Could not initialize corosync configuration API error %d\n", result);
+		exit (1);
+	}
+
+	pthread_create(&dispatch_thread, NULL, shutdown_dispatch_thread, &handle);
+
+	result = corosync_cfg_state_track (handle,
+					   0,
+					   &notification_buffer);
+	if (result != CS_OK) {
+		printf ("Could not start corosync cfg tracking error %d\n", result);
+		exit (1);
+	}
+
+	result = corosync_cfg_try_shutdown (handle, COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST);
+	if (result != CS_OK) {
+		printf ("Could not shutdown (error = %d)\n", result);
+	}
+
+	(void)corosync_cfg_finalize (handle);
 }
 
+void showaddrs_do(int nodeid)
+{
+	cs_error_t result;
+	corosync_cfg_handle_t handle;
+	corosync_cfg_callbacks_t callbacks;
+	int numaddrs;
+	int i;
+	corosync_cfg_node_address_t addrs[INTERFACE_MAX];
+
+
+	result = corosync_cfg_initialize (&handle, &callbacks);
+	if (result != CS_OK) {
+		printf ("Could not initialize corosync configuration API error %d\n", result);
+		exit (1);
+	}
+
+	if (!corosync_cfg_get_node_addrs(handle, nodeid, INTERFACE_MAX, &numaddrs, addrs) == CS_OK) {
+		for (i=0; i<numaddrs; i++) {
+			char buf[INET6_ADDRSTRLEN];
+			struct sockaddr_storage *ss = (struct sockaddr_storage *)addrs[i].address;
+			struct sockaddr_in *sin = (struct sockaddr_in *)addrs[i].address;
+			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addrs[i].address;
+			void *saddr;
+
+			if (ss->ss_family == AF_INET6)
+				saddr = &sin6->sin6_addr;
+			else
+				saddr = &sin->sin_addr;
+
+			inet_ntop(ss->ss_family, saddr, buf, sizeof(buf));
+			printf("%s", buf);
+		}
+		printf("\n");
+	}
+
+
+	(void)corosync_cfg_finalize (handle);
+}
+
+void killnode_do(unsigned int nodeid)
+{
+	cs_error_t result;
+	corosync_cfg_handle_t handle;
+
+	printf ("Killing node %d\n", nodeid);
+	result = corosync_cfg_initialize (&handle, NULL);
+	if (result != CS_OK) {
+		printf ("Could not initialize corosync configuration API error %d\n", result);
+		exit (1);
+	}
+	result = corosync_cfg_kill_node (handle, nodeid, "Killed by corosync-cfgtool");
+	if (result != CS_OK) {
+		printf ("Could not kill node (error = %d)\n", result);
+	}
+	(void)corosync_cfg_finalize (handle);
+}
+
+
 void usage_do (void)
 {
-	printf ("corosync-cfgtool [-s] [-r] [-l] [-u] [service_name] [-v] [version]\n\n");
+	printf ("corosync-cfgtool [-s] [-r] [-l] [-u] [service_name] [-v] [version] [-k] [nodeid] [-a] [nodeid]\n\n");
 	printf ("A tool for displaying and configuring active parameters within corosync.\n");
 	printf ("options:\n");
 	printf ("\t-s\tDisplays the status of the current rings on this node.\n");
@@ -144,15 +261,19 @@
 	printf ("\t\tre-enable redundant ring operation.\n");
 	printf ("\t-l\tLoad a service identified by name.\n");
 	printf ("\t-u\tUnload a service identified by name.\n");
+	printf ("\t-a\tDisplay the IP address(es) of a node\n");
+	printf ("\t-k\tKill a node identified by node id.\n");
+	printf ("\t-h\tShutdown corosync cleanly on this node.\n");
 }
 
 int main (int argc, char *argv[]) {
-	const char *options = "srl:u:v:";
+	const char *options = "srl:u:v:k:a:h";
 	int opt;
 	int service_load = 0;
+	unsigned int nodeid;
 	int service_unload = 0;
-	char *service;
-	unsigned int version;
+	char *service = NULL;
+	unsigned int version = 0;
 
 	if (argc == 1) {
 		usage_do ();
@@ -173,17 +294,28 @@
 			service_unload = 1;
 			service = strdup (optarg);
 			break;
+		case 'k':
+			nodeid = atoi (optarg);
+			killnode_do(nodeid);
+			break;
+		case 'h':
+			shutdown_do();
+			break;
+		case 'a':
+			showaddrs_do( atoi(optarg) );
+			break;
 		case 'v':
 			version = atoi (optarg);
+			break;
 		}
 	}
 
 	if (service_load) {
 		service_load_do (service, version);
-	} else 
+	} else
 	if (service_unload) {
 		service_unload_do (service, version);
 	}
-		
+
 	return (0);
 }
diff -Naurd corosync-0.92/tools/corosync-fplay.c corosync-trunk/tools/corosync-fplay.c
--- corosync-0.92/tools/corosync-fplay.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/tools/corosync-fplay.c	2008-11-11 18:25:22.000000000 +0100
@@ -0,0 +1,485 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdint.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <corosync/engine/logsys.h>
+
+unsigned int flt_data_size = 1000000;
+
+unsigned int *flt_data;
+#define FDHEAD_INDEX		(flt_data_size)
+#define FDTAIL_INDEX		(flt_data_size + 1)
+
+#define TOTEMIP_ADDRLEN (sizeof(struct in6_addr))
+
+struct totem_ip_address {
+        unsigned int   nodeid;
+        unsigned short family;
+        unsigned char  addr[TOTEMIP_ADDRLEN];
+} __attribute__((packed));
+
+struct memb_ring_id {
+        struct totem_ip_address rep;
+        unsigned long long seq;
+} __attribute__((packed));
+
+const char *totemip_print(struct totem_ip_address *addr)
+{
+	static char buf[INET6_ADDRSTRLEN];
+
+	return inet_ntop(addr->family, addr->addr, buf, sizeof(buf));
+}
+
+char *print_string_len (unsigned char *str, unsigned int len)
+{
+	unsigned int i;
+	static char buf[1024];
+	memset (buf, 0, sizeof (buf));
+	for (i = 0; i < len; i++) {
+		buf[i] = str[i];
+	}
+	return (buf);
+}
+
+void sync_printer_confchg_set_sync (void **record)
+{
+	unsigned int *my_should_sync = record[0];
+	printf ("Setting my_should_sync to %d\n", *my_should_sync);
+}
+
+void sync_printer_set_sync_state (void **record)
+{
+	unsigned int *my_sync_state = record[0];
+	printf ("Setting my_sync_state to %d\n", *my_sync_state);
+}
+
+void sync_printer_process_currentstate (void **record)
+{
+	unsigned int *my_sync_state = record[0];
+	printf ("Retrieving my_sync_state %d\n", *my_sync_state);
+}
+
+void sync_printer_process_get_shouldsync (void **record)
+{
+	unsigned int *my_should_sync = record[0];
+	printf ("Getting my_should_sync %d\n", *my_should_sync);
+}
+
+void sync_printer_checkpoint_release (void **record)
+{
+	unsigned char *name = record[0];
+	uint16_t *name_len = record[1];
+	unsigned int *ckpt_id = record[2];
+	unsigned int *from = record[3];
+
+	printf ("Checkpoint release name=[%s] id=[%d] from=[%d] len=[%d]\n",
+		print_string_len (name, *name_len),
+		*ckpt_id,
+		*from,
+		*name_len);
+}
+
+void sync_printer_checkpoint_transmit (void **record)
+{
+	unsigned char *name = record[0];
+	uint16_t *name_len = record[1];
+	unsigned int *ckpt_id = record[2];
+	unsigned int *xmit_id = record[3];
+
+	printf ("xmit_id=[%d] Checkpoint transmit name=[%s] id=[%d]\n",
+		*xmit_id, print_string_len (name, *name_len),
+		*ckpt_id);
+}
+
+void sync_printer_section_transmit (void **record)
+{
+	unsigned char *ckpt_name = record[0];
+	uint16_t *name_len = record[1];
+	unsigned int *ckpt_id = record[2];
+	unsigned int *xmit_id = record[3];
+	unsigned char *section_name = record[4];
+	uint16_t *section_name_len = record[5];
+	
+	printf ("xmit_id=[%d] Section transmit checkpoint name=[%s] id=[%d] ",
+		*xmit_id, print_string_len (ckpt_name, *name_len),
+		*ckpt_id);
+	printf ("section=[%s]\n",
+		print_string_len (section_name, *section_name_len));
+}
+void sync_printer_checkpoint_receive (void **record)
+{
+	unsigned char *ckpt_name = record[0];
+	uint16_t *name_len = record[1];
+	unsigned int *ckpt_id = record[2];
+	unsigned int *xmit_id = record[3];
+	
+	printf ("xmit_id=[%d] Checkpoint receive checkpoint name=[%s] id=[%d]\n",
+		*xmit_id, print_string_len (ckpt_name, *name_len), *ckpt_id);
+}
+
+void sync_printer_section_receive (void **record)
+{
+	unsigned char *ckpt_name = record[0];
+	uint16_t *name_len = record[1];
+	unsigned int *ckpt_id = record[2];
+	unsigned int *xmit_id = record[3];
+	unsigned char *section_name = record[4];
+	unsigned int *section_name_len = record[5];
+
+	printf ("xmit_id=[%d] Section receive checkpoint name=[%s] id=[%d] ",
+		*xmit_id, print_string_len (ckpt_name, *name_len),
+		*ckpt_id);
+
+	printf ("section=[%s]\n",
+		print_string_len (section_name, *section_name_len));
+}
+
+void sync_printer_nada (void **record)
+{
+printf ("nada\n");
+}
+void sync_printer_confchg_fn (void **record)
+{
+	unsigned int i;
+
+	unsigned int *members = record[0];
+	unsigned int *member_count = record[1];
+	struct memb_ring_id *ring_id = record[2];
+	struct in_addr addr;
+
+	printf ("sync confchg fn ringid [ip=%s seq=%lld]\n",
+		totemip_print (&ring_id->rep),
+		ring_id->seq);
+	printf ("members [%d]:\n", *member_count);
+	for (i = 0; i < *member_count; i++) {
+		addr.s_addr = members[i];
+		printf ("\tmember [%s]\n", inet_ntoa (addr));
+	}
+}
+
+void printer_totemsrp_mcast (void **record)
+{
+	unsigned int *msgid = record[0];
+
+	printf ("totemsrp_mcast %d\n", *msgid);
+}
+
+void printer_totemsrp_delv (void **record)
+{
+	unsigned int *msgid = record[0];
+
+	printf ("totemsrp_delv %d\n", *msgid);
+}
+
+void printer_totempg_mcast_fits (void **record)
+{
+	unsigned int *index = record[0];
+	unsigned int *iov_len = record[1];
+	unsigned int *copy_len = record[2];
+	unsigned int *fragment_size = record[3];
+	unsigned int *max_packet_size = record[4];
+	unsigned int *copy_base = record[5];
+	unsigned char *next_fragment = record[6];
+
+	printf ("totempg_mcast index=[%d] iov_len=[%d] copy_len=[%d] fragment_size=[%d] max_packet_size=[%d] copy_base=[%d] next_fragment[%d]\n",
+	*index, *iov_len, *copy_len, *fragment_size, *max_packet_size, *copy_base, *next_fragment);
+}
+
+void sync_printer_service_process (void **record)
+{
+	struct memb_ring_id *ring_id = record[0];
+	struct memb_ring_id *sync_ring_id = record[1];
+
+	printf ("sync service process callback ringid [ip=%s seq=%lld] ",
+		totemip_print (&ring_id->rep),
+		ring_id->seq);
+	printf ("sync ringid [ip=%s seq=%lld]\n",
+		totemip_print (&sync_ring_id->rep),
+		sync_ring_id->seq);
+}
+
+struct printer_subsys_record_print {
+	int ident;
+	void (*print_fn)(void **record);
+	int record_length;
+};
+
+struct printer_subsys {
+	char *subsys;
+	struct printer_subsys_record_print *record_printers;
+	int record_printers_count;
+};
+
+#define LOGREC_ID_SYNC_CONFCHG_FN 0
+#define LOGREC_ID_SYNC_SERVICE_PROCESS 1
+
+/*
+ * CKPT subsystem
+ */
+#define LOGREC_ID_CONFCHG_SETSYNC 0
+#define LOGREC_ID_SETSYNCSTATE 1
+#define LOGREC_ID_SYNC_PROCESS_CURRENTSTATE 2
+#define LOGREC_ID_SYNC_PROCESS_GETSHOULDSYNC 3
+#define LOGREC_ID_SYNC_CHECKPOINT_TRANSMIT 4
+#define LOGREC_ID_SYNC_SECTION_TRANSMIT 5
+#define LOGREC_ID_SYNC_CHECKPOINT_RECEIVE 6
+#define LOGREC_ID_SYNC_SECTION_RECEIVE 7
+#define LOGREC_ID_SYNC_CHECKPOINT_RELEASE 8
+
+#define LOGREC_ID_TOTEMSRP_MCAST 0
+#define LOGREC_ID_TOTEMSRP_DELV 1
+#define LOGREC_ID_TOTEMPG_MCAST_FITS 2
+
+
+struct printer_subsys_record_print record_print_sync[] = {
+	{
+		.ident				= LOGREC_ID_SYNC_CONFCHG_FN,
+		.print_fn			= sync_printer_confchg_fn,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_SERVICE_PROCESS,
+		.print_fn			= sync_printer_service_process,
+		.record_length			= 28
+	}
+};
+
+struct printer_subsys_record_print record_print_ckpt[] = {
+	{
+		.ident				= LOGREC_ID_CONFCHG_SETSYNC,
+		.print_fn			= sync_printer_confchg_set_sync,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SETSYNCSTATE,
+		.print_fn			= sync_printer_set_sync_state,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_PROCESS_CURRENTSTATE,
+		.print_fn			= sync_printer_process_currentstate,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_PROCESS_GETSHOULDSYNC,
+		.print_fn			= sync_printer_process_get_shouldsync,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_CHECKPOINT_TRANSMIT,
+		.print_fn			= sync_printer_checkpoint_transmit,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_SECTION_TRANSMIT,
+		.print_fn			= sync_printer_section_transmit,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_CHECKPOINT_RECEIVE,
+		.print_fn			= sync_printer_checkpoint_receive,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_SECTION_RECEIVE,
+		.print_fn			= sync_printer_section_receive,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_SYNC_CHECKPOINT_RELEASE,
+		.print_fn			= sync_printer_checkpoint_release,
+		.record_length			= 28
+	}
+
+};
+struct printer_subsys_record_print record_print_totem[] = {
+	{
+		.ident				= LOGREC_ID_TOTEMSRP_MCAST,
+		.print_fn			= printer_totemsrp_mcast,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_TOTEMSRP_DELV,
+		.print_fn			= printer_totemsrp_delv,
+		.record_length			= 28
+	},
+	{
+		.ident				= LOGREC_ID_TOTEMPG_MCAST_FITS,
+		.print_fn			= printer_totempg_mcast_fits,
+		.record_length			= 28
+	}
+};
+
+struct printer_subsys printer_subsystems[] = {
+	{
+		.subsys =			"SYNC",
+		.record_printers = 		record_print_sync,
+		.record_printers_count = 	sizeof (record_print_sync) / sizeof (struct printer_subsys_record_print)
+	},
+	{
+		.subsys =			"CKPT",
+		.record_printers = 		record_print_ckpt,
+		.record_printers_count = 	sizeof (record_print_ckpt) / sizeof (struct printer_subsys_record_print)
+	},
+	{
+		.subsys =			"TOTEM",
+		.record_printers = 		record_print_totem,
+		.record_printers_count = 	sizeof (record_print_totem) / sizeof (struct printer_subsys_record_print)
+	}
+};
+
+unsigned int printer_subsys_count = sizeof (printer_subsystems) / sizeof (struct printer_subsys);
+	
+unsigned int records_printed = 1;
+
+unsigned int record[10000];
+
+/*
+ * Copy record, dealing with wrapping
+ */
+int logsys_rec_get (int rec_idx) {
+	unsigned int rec_size;
+	int firstcopy, secondcopy;
+
+	rec_size = flt_data[rec_idx];
+
+	firstcopy = rec_size;
+	secondcopy = 0;
+	if (firstcopy + rec_idx > flt_data_size) {
+		firstcopy = flt_data_size - rec_idx; 
+		secondcopy -= firstcopy - rec_size;
+	}
+	memcpy (&record[0], &flt_data[rec_idx], firstcopy<<2);
+	if (secondcopy) {
+		memcpy (&record[firstcopy], &flt_data[0], secondcopy<<2);
+	}
+	return ((rec_idx + rec_size) % flt_data_size);
+}
+
+void logsys_rec_print (void *record)
+{
+	unsigned int *buf_uint32t = (unsigned int *)record;
+	unsigned int rec_size;
+	unsigned int rec_ident;
+	unsigned int line;
+	unsigned int arg_size_idx;
+	unsigned int i;
+	unsigned int j;
+	unsigned int rec_idx = 0;
+	unsigned int record_number;
+	unsigned int words_processed;
+	unsigned int found;
+	void *arguments[64];
+	int arg_count = 0;
+
+	rec_size = buf_uint32t[rec_idx];
+	rec_ident = buf_uint32t[rec_idx+1];
+	line = buf_uint32t[rec_idx+2];
+	record_number = buf_uint32t[rec_idx+3];
+
+printf ("rec=[%d] ", record_number);
+	arg_size_idx = rec_idx + 4;
+	words_processed = 4;
+	for (i = 0; words_processed < rec_size; i++) {
+		arguments[arg_count++] = &buf_uint32t[arg_size_idx + 1];
+		words_processed += buf_uint32t[arg_size_idx] + 1;
+		arg_size_idx += buf_uint32t[arg_size_idx] + 1;
+		
+	}
+
+	found = 0;
+	for (i = 0; i < printer_subsys_count; i++) {
+		if (strcmp ((char *)arguments[0], printer_subsystems[i].subsys) == 0) {
+			for (j = 0; j < printer_subsystems[i].record_printers_count; j++) {
+				if (rec_ident == printer_subsystems[i].record_printers[j].ident) {
+					printer_subsystems[i].record_printers[j].print_fn (&arguments[3]);
+					found = 1;
+				}
+			}
+		}	
+	}
+	if (rec_ident & LOGSYS_TAG_LOG) {
+		printf ("Log Message=%s\n", (char *)arguments[3]);
+		found = 1;
+	}
+	if (rec_ident & LOGSYS_TAG_ENTER) {
+		printf ("ENTERING function [%s] line [%d]\n", (char *)arguments[2], line);
+		found = 1;
+	}
+	if (rec_ident & LOGSYS_TAG_LEAVE) {
+		printf ("LEAVING function [%s] line [%d]\n", (char *)arguments[2], line);
+		found = 1;
+	}
+	if (found == 0) {
+		printf ("Unknown record type found subsys=[%s] ident=[%d]\n",
+		(char *)arguments[0], rec_ident);
+	}
+
+
+	if (rec_ident == 999) {
+		printf ("ENTERING function [%s] line [%d]\n", (char *)arguments[2], line);
+		found = 1;
+	}
+	if (rec_ident == 1000) {
+		printf ("LEAVING function [%s] line [%d]\n", (char *)arguments[2], line);
+		found = 1;
+	}
+	if (found == 0) {
+		printf ("Unknown record type found subsys=[%s] ident=[%d]\n",
+			(char *)arguments[0], rec_ident);
+	}
+		
+
+#ifdef COMPILE_OUT
+printf ("\n");
+#endif
+}
+
+int main (void)
+{
+	unsigned int fd;
+	int rec_idx;
+	int end_rec;
+	int record_count = 1;
+	int size_read;
+
+	flt_data = malloc ((flt_data_size + 2) * sizeof (unsigned int));
+	fd = open ("/var/lib/corosync/fdata", O_RDONLY);
+	size_read = (int)read (fd, flt_data, (flt_data_size + 2) * sizeof (unsigned int));
+
+	if (size_read != (flt_data_size + 2) * sizeof (unsigned int)) {
+		printf ("Warning: read %d bytes, but expected %d\n",
+				size_read, (flt_data_size + 2) * sizeof (unsigned int));
+	}
+
+	rec_idx = flt_data[FDTAIL_INDEX];
+	end_rec = flt_data[FDHEAD_INDEX];
+
+	printf ("Starting replay: head [%d] tail [%d]\n",
+		flt_data[FDHEAD_INDEX],
+		flt_data[FDTAIL_INDEX]);
+
+	for (;;) {
+		rec_idx = logsys_rec_get (rec_idx);
+		logsys_rec_print (record);
+		if (rec_idx == end_rec) {
+			break;
+		}
+		record_count += 1;
+	}
+
+	printf ("Finishing replay: records found [%d]\n", record_count);
+	return (0);
+}
diff -Naurd corosync-0.92/tools/corosync-keygen.c corosync-trunk/tools/corosync-keygen.c
--- corosync-0.92/tools/corosync-keygen.c	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/tools/corosync-keygen.c	2008-11-11 19:13:47.000000000 +0100
@@ -44,7 +44,7 @@
 	int authkey_fd;
 	int random_fd;
 	unsigned char key[128];
-	int res;
+	ssize_t res;
 	
 	printf ("Corosync Cluster Engine Authentication key generator.\n");
 	if (geteuid() != 0) {
@@ -80,7 +80,7 @@
 	/*
 	 * Set security of authorization key to uid = 0 uid = 0 mode = 0400
 	 */
-	res = fchown (authkey_fd, 0, 0);
+	fchown (authkey_fd, 0, 0);
 	fchmod (authkey_fd, 0400);
 
 	printf ("Writing corosync key to /etc/ais/authkey.\n");
diff -Naurd corosync-0.92/tools/corosync-objctl.c corosync-trunk/tools/corosync-objctl.c
--- corosync-0.92/tools/corosync-objctl.c	2008-08-14 18:44:26.000000000 +0200
+++ corosync-trunk/tools/corosync-objctl.c	2008-12-08 17:11:07.000000000 +0100
@@ -32,6 +32,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/select.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -41,7 +42,7 @@
 #include <sys/types.h>
 #include <sys/un.h>
 
-#include <corosync/saAis.h>
+#include <corosync/corotypes.h>
 #include <corosync/confdb.h>
 
 #define SEPERATOR '.'
@@ -104,12 +105,12 @@
 	int key_name_len;
 	char key_value[OBJ_NAME_SIZE];
 	int key_value_len;
-	confdb_error_t res;
+	cs_error_t res;
 	int children_printed;
 
 	/* Show the keys */
 	res = confdb_key_iter_start(handle, parent_object_handle);
-	if (res != CONFDB_OK) {
+	if (res != CS_OK) {
 		fprintf(stderr, "error resetting key iterator for object %d: %d\n", parent_object_handle, res);
 		exit(EXIT_FAILURE);
 	}
@@ -120,7 +121,7 @@
 								   key_name,
 								   &key_name_len,
 								   key_value,
-								   &key_value_len)) == CONFDB_OK) {
+								   &key_value_len)) == CS_OK) {
 		key_name[key_name_len] = '\0';
 		key_value[key_value_len] = '\0';
 		if (parent_name != NULL)
@@ -133,7 +134,7 @@
 
 	/* Show sub-objects */
 	res = confdb_object_iter_start(handle, parent_object_handle);
-	if (res != CONFDB_OK) {
+	if (res != CS_OK) {
 		fprintf(stderr, "error resetting object iterator for object %d: %d\n", parent_object_handle, res);
 		exit(EXIT_FAILURE);
 	}
@@ -142,7 +143,7 @@
 									  parent_object_handle,
 									  &object_handle,
 									  object_name,
-									  &object_name_len)) == CONFDB_OK)	{
+									  &object_name_len)) == CS_OK)	{
 
 		object_name[object_name_len] = '\0';
 		if (parent_name != NULL) {
@@ -165,7 +166,7 @@
 	int result;
 
 	result = confdb_initialize (&handle, &callbacks);
-	if (result != CONFDB_OK) {
+	if (result != CS_OK) {
 		fprintf (stderr, "Could not initialize objdb library. Error %d\n", result);
 		return 1;
 	}
@@ -181,22 +182,23 @@
 static int print_help(void)
 {
 	printf("\n");
-	printf ("usage:  corosync-objctl object%ckey ...\n", SEPERATOR);
-	printf ("        corosync-objctl -c object%cchild_obj ...\n", SEPERATOR);
-	printf ("        corosync-objctl -d object%cchild_obj ...\n", SEPERATOR);
-	printf ("        corosync-objctl -w object%cchild_obj.key=value ...\n", SEPERATOR);
-	printf ("        corosync-objctl -a (print all objects)\n");
+	printf ("usage:  corosync-objctl object%ckey ...                    Print an object\n", SEPERATOR);
+	printf ("        corosync-objctl -c object%cchild_obj ...           Create Object\n", SEPERATOR);
+	printf ("        corosync-objctl -d object%cchild_obj ...           Delete object\n", SEPERATOR);
+	printf ("        corosync-objctl -w object%cchild_obj.key=value ... Create a key\n", SEPERATOR);
+	printf ("        corosync-objctl -t object%cchild_obj ...           Track changes\n", SEPERATOR);
+	printf ("        corosync-objctl -a                                Print all objects\n");
 	printf("\n");
 	return 0;
 }
 
-static confdb_error_t validate_name(char * obj_name_pt)
+static cs_error_t validate_name(char * obj_name_pt)
 {
 	if ((strchr (obj_name_pt, SEPERATOR) == NULL) &&
 		(strchr (obj_name_pt, '=') == NULL))
-		return CONFDB_OK;
+		return CS_OK;
 	else
-		return CONFDB_ERR_INVALID_PARAM;
+		return CS_ERR_INVALID_PARAM;
 }
 
 void get_child_name(char * name_pt, char * child_name)
@@ -251,7 +253,7 @@
 	strcpy(key_name, tmp+1);
 }
 
-static confdb_error_t find_object (confdb_handle_t handle,
+static cs_error_t find_object (confdb_handle_t handle,
 			char * name_pt,
 			find_object_of_type_t type,
 			uint32_t * out_handle)
@@ -261,21 +263,21 @@
 	uint32_t obj_handle;
 	confdb_handle_t parent_object_handle = OBJECT_PARENT_HANDLE;
 	char tmp_name[OBJ_NAME_SIZE];
-	confdb_error_t res;
+	cs_error_t res;
 
 	strncpy (tmp_name, name_pt, OBJ_NAME_SIZE);
 	obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt);
 
 	while (obj_name_pt != NULL) {
 		res = confdb_object_find_start(handle, parent_object_handle);
-		if (res != CONFDB_OK) {
+		if (res != CS_OK) {
 			fprintf (stderr, "Could not start object_find %d\n", res);
 			exit (EXIT_FAILURE);
 		}
 
 		res = confdb_object_find(handle, parent_object_handle,
 				obj_name_pt, strlen (obj_name_pt), &obj_handle);
-		if (res != CONFDB_OK) {
+		if (res != CS_OK) {
 			return res;
 		}
 
@@ -291,11 +293,11 @@
 {
 	char parent_name[OBJ_NAME_SIZE];
 	uint32_t obj_handle;
-	confdb_error_t res;
+	cs_error_t res;
 
 	get_parent_name(name_pt, parent_name);
 	res = find_object (handle, name_pt, FIND_OBJECT_OR_KEY, &obj_handle);
-	if (res == CONFDB_OK) {
+	if (res == CS_OK) {
 		print_config_tree(handle, obj_handle, parent_name);
 	}
 }
@@ -308,19 +310,19 @@
 	char key_value[OBJ_NAME_SIZE];
 	char old_key_value[OBJ_NAME_SIZE];
 	int old_key_value_len;
-	confdb_error_t res;
+	cs_error_t res;
 
 	/* find the parent object */
 	get_parent_name(path_pt, parent_name);
 	get_key(path_pt, key_name, key_value);
 
-	if (validate_name(key_name) != CONFDB_OK) {
+	if (validate_name(key_name) != CS_OK) {
 		fprintf(stderr, "Incorrect key name, can not have \"=\" or \"%c\"\n", SEPERATOR);
 		exit(EXIT_FAILURE);
 	}
 	res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle);
 
-	if (res != CONFDB_OK) {
+	if (res != CS_OK) {
 		fprintf(stderr, "Can't find parent object of \"%s\"\n", path_pt);
 		exit(EXIT_FAILURE);
 	}
@@ -333,7 +335,7 @@
 						  old_key_value,
 						  &old_key_value_len);
 
-	if (res == CONFDB_OK) {
+	if (res == CS_OK) {
 		/* replace the current value */
 		res = confdb_key_replace (handle,
 								  obj_handle,
@@ -344,7 +346,7 @@
 								  key_value,
 								  strlen(key_value));
 
-		if (res != CONFDB_OK)
+		if (res != CS_OK)
 			fprintf(stderr, "Failed to replace the key %s=%s. Error %d\n", key_name, key_value, res);
 	} else {
 		/* not there, create a new key */
@@ -354,7 +356,7 @@
 								 strlen(key_name),
 								 key_value,
 								 strlen(key_value));
-		if (res != CONFDB_OK)
+		if (res != CS_OK)
 			fprintf(stderr, "Failed to create the key %s=%s. Error %d\n", key_name, key_value, res);
 	}
 
@@ -367,23 +369,23 @@
 	uint32_t obj_handle;
 	uint32_t parent_object_handle = OBJECT_PARENT_HANDLE;
 	char tmp_name[OBJ_NAME_SIZE];
-	confdb_error_t res;
+	cs_error_t res;
 
 	strncpy (tmp_name, name_pt, OBJ_NAME_SIZE);
 	obj_name_pt = strtok_r(tmp_name, SEPERATOR_STR, &save_pt);
 
 	while (obj_name_pt != NULL) {
 		res = confdb_object_find_start(handle, parent_object_handle);
-		if (res != CONFDB_OK) {
+		if (res != CS_OK) {
 			fprintf (stderr, "Could not start object_find %d\n", res);
 			exit (EXIT_FAILURE);
 		}
 
 		res = confdb_object_find(handle, parent_object_handle,
 								 obj_name_pt, strlen (obj_name_pt), &obj_handle);
-		if (res != CONFDB_OK) {
+		if (res != CS_OK) {
 
-			if (validate_name(obj_name_pt) != CONFDB_OK) {
+			if (validate_name(obj_name_pt) != CS_OK) {
 				fprintf(stderr, "Incorrect object name \"%s\", \"=\" not allowed.\n",
 						obj_name_pt);
 				exit(EXIT_FAILURE);
@@ -393,7 +395,7 @@
 										obj_name_pt,
 										strlen (obj_name_pt),
 										&obj_handle);
-			if (res != CONFDB_OK)
+			if (res != CS_OK)
 				fprintf(stderr, "Failed to create object \"%s\". Error %d.\n",
 						obj_name_pt, res);
 		}
@@ -449,10 +451,13 @@
 	int result;
 	fd_set read_fds;
 	int select_fd;
-	SaBoolT quit = SA_FALSE;
+	int quit = CS_FALSE;
 
 	FD_ZERO (&read_fds);
-	confdb_fd_get(handle, &select_fd);
+	if (confdb_fd_get (handle, &select_fd) != CS_OK) {
+		printf ("can't get the confdb selector object.\n");
+		return;
+	}
 	printf ("Type \"q\" to finish\n");
 	do {
 		FD_SET (select_fd, &read_fds);
@@ -464,35 +469,36 @@
 		if (FD_ISSET (STDIN_FILENO, &read_fds)) {
 			char inbuf[3];
 
-			fgets(inbuf, sizeof(inbuf), stdin);
-			if (strncmp(inbuf, "q", 1) == 0)
-				quit = SA_TRUE;
+			if (fgets(inbuf, sizeof(inbuf), stdin) == NULL)
+				quit = CS_TRUE;
+			else if (strncmp(inbuf, "q", 1) == 0)
+				quit = CS_TRUE;
 		}
 		if (FD_ISSET (select_fd, &read_fds)) {
-			if (confdb_dispatch (handle, CONFDB_DISPATCH_ALL) != CONFDB_OK)
+			if (confdb_dispatch (handle, CONFDB_DISPATCH_ALL) != CS_OK)
 				exit(1);
 		}
-	} while (result && quit == SA_FALSE);
+	} while (result && quit == CS_FALSE);
 
-	confdb_stop_track_changes(handle);
+	(void)confdb_stop_track_changes(handle);
 
 }
 
 static void track_object(confdb_handle_t handle, char * name_pt)
 {
-	confdb_error_t res;
+	cs_error_t res;
 	uint32_t obj_handle;
 
 	res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle);
 
-	if (res != CONFDB_OK) {
+	if (res != CS_OK) {
 		fprintf (stderr, "Could not find object \"%s\". Error %d\n",
 				 name_pt, res);
 		return;
 	}
 
 	res = confdb_track_changes (handle, obj_handle, CONFDB_TRACK_DEPTH_RECURSIVE);
-	if (res != CONFDB_OK) {
+	if (res != CS_OK) {
 		fprintf (stderr, "Could not enable tracking on object \"%s\". Error %d\n",
 				 name_pt, res);
 		return;
@@ -501,10 +507,10 @@
 
 static void stop_tracking(confdb_handle_t handle)
 {
-	confdb_error_t res;
+	cs_error_t res;
 
 	res = confdb_stop_track_changes (handle);
-	if (res != CONFDB_OK) {
+	if (res != CS_OK) {
 		fprintf (stderr, "Could not stop tracking. Error %d\n", res);
 		return;
 	}
@@ -512,14 +518,14 @@
 
 static void delete_object(confdb_handle_t handle, char * name_pt)
 {
-	confdb_error_t res;
+	cs_error_t res;
 	uint32_t obj_handle;
 	res = find_object (handle, name_pt, FIND_OBJECT_ONLY, &obj_handle);
 
-	if (res == CONFDB_OK) {
+	if (res == CS_OK) {
 		res = confdb_object_destroy (handle, obj_handle);
 
-		if (res != CONFDB_OK)
+		if (res != CS_OK)
 			fprintf(stderr, "Failed to find object \"%s\" to delete. Error %d\n", name_pt, res);
 	} else {
 		char parent_name[OBJ_NAME_SIZE];
@@ -531,7 +537,7 @@
 		get_key(name_pt, key_name, key_value);
 		res = find_object (handle, parent_name, FIND_OBJECT_ONLY, &obj_handle);
 
-		if (res != CONFDB_OK) {
+		if (res != CS_OK) {
 			fprintf(stderr, "Failed to find the key's parent object \"%s\". Error %d\n", parent_name, res);
 			exit (EXIT_FAILURE);
 		}
@@ -543,7 +549,7 @@
 								 key_value,
 								 strlen(key_value));
 
-		if (res != CONFDB_OK)
+		if (res != CS_OK)
 			fprintf(stderr, "Failed to delete key \"%s=%s\" from object \"%s\". Error %d\n",
 					key_name, key_value, parent_name, res);
 	}
@@ -552,8 +558,8 @@
 
 int main (int argc, char *argv[]) {
 	confdb_handle_t handle;
-	confdb_error_t result;
-	char c;
+	cs_error_t result;
+	int c;
 
 	action = ACTION_READ;
 
@@ -603,7 +609,7 @@
 	}
 
 	result = confdb_initialize (&handle, &callbacks);
-	if (result != CONFDB_OK) {
+	if (result != CS_OK) {
 		fprintf (stderr, "Failed to initialize the objdb API. Error %d\n", result);
 		exit (EXIT_FAILURE);
 	}
@@ -633,7 +639,7 @@
 	}
 
 	result = confdb_finalize (handle);
-	if (result != CONFDB_OK) {
+	if (result != CS_OK) {
 		fprintf (stderr, "Error finalizing objdb API. Error %d\n", result);
 		exit(EXIT_FAILURE);
 	}
diff -Naurd corosync-0.92/tools/corosync-pload.c corosync-trunk/tools/corosync-pload.c
--- corosync-0.92/tools/corosync-pload.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-trunk/tools/corosync-pload.c	2008-11-06 22:49:07.000000000 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Steven Dake (sdake@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <corosync/corotypes.h>
+#include <corosync/pload.h>
+
+#define timersub(a, b, result)						\
+do {									\
+	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;			\
+	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec;		\
+	if ((result)->tv_usec < 0) {					\
+		--(result)->tv_sec;					\
+		(result)->tv_usec += 1000000;				\
+	}								\
+} while (0)
+
+int main (void) {
+	pload_error_t result;
+	pload_handle_t handle;
+
+	result = pload_initialize (&handle, NULL);
+	printf ("Init result %d\n", result);
+	result = pload_start (
+		handle,
+		0, /* code */
+		150000000, /* count */
+		300); /* size */
+	return (0);
+}
diff -Naurd corosync-0.92/tools/Makefile corosync-trunk/tools/Makefile
--- corosync-0.92/tools/Makefile	2008-08-15 08:15:26.000000000 +0200
+++ corosync-trunk/tools/Makefile	2008-11-11 18:28:22.000000000 +0100
@@ -41,8 +41,8 @@
 	override LDFLAGS += -lnsl -lsocket -lrt
 endif
 
-LIBS = ../lib/libconfdb.a ../lib/libcfg.a
-BINARIES=corosync-objctl corosync-cfgtool corosync-keygen
+LIBS = ../lib/libconfdb.a ../lib/libcfg.a ../lib/libpload.a
+BINARIES=corosync-objctl corosync-cfgtool corosync-keygen corosync-fplay corosync-pload
 APPS_SRC=$(addsuffix .c,$(BINARIES))
 EXTRA_CFLAGS = -I$(srcdir)include
 
@@ -57,9 +57,22 @@
 corosync-keygen: corosync-keygen.o
 	$(CC) $(LDFLAGS) -o $@ $<
 
+corosync-fplay: corosync-fplay.o
+	$(CC) $(LDFLAGS) -o $@ $<
+
+corosync-pload: corosync-pload.o
+	$(CC) $(LDFLAGS) -o $@ $< $(LIBS)
+
 clean:
 	rm -f *.o $(BINARIES)
 
+lint:
+	-splint $(LINT_FLAGS) $(CFLAGS) corosync-objctl.c
+	-splint $(LINT_FLAGS) $(CFLAGS) corosync-cfgtool.c
+	-splint $(LINT_FLAGS) $(CFLAGS) corosync-keygen.c
+	-splint $(LINT_FLAGS) $(CFLAGS) corosync-fplay.c
+	-splint $(LINT_FLAGS) $(CFLAGS) corosync-pload.c
+
 %.o: %.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<