This is the mail archive of the cluster-cvs@sourceware.org mailing list for the cluster.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

cluster: master - groupd/libgroup: remove them


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=f723d9c72f60af142ab4d9c49d762ebf7a45f0e5
Commit:        f723d9c72f60af142ab4d9c49d762ebf7a45f0e5
Parent:        3a4eab96426ad3312a4616488a58071ed6b460a4
Author:        David Teigland <teigland@redhat.com>
AuthorDate:    Fri Jan 9 14:47:40 2009 -0600
Committer:     David Teigland <teigland@redhat.com>
CommitterDate: Fri Jan 9 14:47:40 2009 -0600

groupd/libgroup: remove them

and make group_tool a simple wrapper around fence_tool,
dlm_tool and gfs_control.

Signed-off-by: David Teigland <teigland@redhat.com>
---
 group/Makefile             |    2 +-
 group/daemon/Makefile      |   35 -
 group/daemon/app.c         | 1842 --------------------------------------------
 group/daemon/cman.c        |  206 -----
 group/daemon/cpg.c         | 1072 --------------------------
 group/daemon/gd_internal.h |  323 --------
 group/daemon/groupd.h      |   13 -
 group/daemon/joinleave.c   |  165 ----
 group/daemon/logging.c     |   60 --
 group/daemon/main.c        | 1082 --------------------------
 group/lib/Makefile         |   17 -
 group/lib/libgroup.c       |  524 -------------
 group/lib/libgroup.h       |   81 --
 group/man/groupd.8         |   43 -
 group/test/Makefile        |   16 -
 group/test/client.c        |   45 --
 group/test/clientd.c       |  179 -----
 group/tool/Makefile        |   21 +-
 group/tool/main.c          |  635 +---------------
 19 files changed, 21 insertions(+), 6340 deletions(-)

diff --git a/group/Makefile b/group/Makefile
index eab99ca..792c2e5 100644
--- a/group/Makefile
+++ b/group/Makefile
@@ -1,4 +1,4 @@
 include ../make/defines.mk
 include $(OBJDIR)/make/passthrough.mk
 
-SUBDIRS = lib daemon man
+SUBDIRS = man tool
diff --git a/group/daemon/Makefile b/group/daemon/Makefile
deleted file mode 100644
index 36268db..0000000
--- a/group/daemon/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-TARGET= groupd
-
-SBINDIRT=$(TARGET)
-
-all: ${TARGET}
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-OBJS=	app.o \
-	cpg.o \
-	cman.o \
-	joinleave.o \
-	main.o \
-	logging.o
-
-CFLAGS += -I${ccsincdir} -I${cmanincdir} -I${logtincdir} -I${corosyncincdir}
-CFLAGS += -I$(S) -I$(S)/../include/ -I$(S)/../lib/
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${ccslibdir} -lccs 
-LDFLAGS += -L${cmanlibdir} -lcman
-LDFLAGS += -L${logtlibdir} -llogthread
-LDFLAGS += -L${corosynclibdir} -lcpg -lpthread
-LDFLAGS += -L${libdir}
-
-${TARGET}: ${OBJS}
-	$(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
-
--include $(OBJS:.o=.d)
diff --git a/group/daemon/app.c b/group/daemon/app.c
deleted file mode 100644
index 9ca2801..0000000
--- a/group/daemon/app.c
+++ /dev/null
@@ -1,1842 +0,0 @@
-
-/* Apply queued events to apps */
-
-#include "gd_internal.h"
-
-struct list_head recovery_sets;
-
-struct nodeid {
-	struct list_head list;
-	int nodeid;
-};
-
-char *msg_type(int type)
-{
-	switch (type) {
-	case MSG_APP_STOPPED:
-		return "stopped";
-	case MSG_APP_STARTED:
-		return "started";
-	case MSG_APP_RECOVER:
-		return "recover";
-	case MSG_APP_INTERNAL:
-		return "internal";
-	case MSG_GLOBAL_ID:
-		return "global_id";
-	}
-	return "unknown";
-}
-
-void msg_bswap_out(msg_t *msg)
-{
-	msg->ms_version[0]	= cpu_to_le32(MSG_VER_MAJOR);
-	msg->ms_version[1]	= cpu_to_le32(MSG_VER_MINOR);
-	msg->ms_version[2]	= cpu_to_le32(MSG_VER_PATCH);
-	msg->ms_type		= cpu_to_le16(msg->ms_type);
-	msg->ms_level		= cpu_to_le16(msg->ms_level);
-	msg->ms_length		= cpu_to_le32(msg->ms_length);
-	msg->ms_global_id	= cpu_to_le32(msg->ms_global_id);
-	msg->ms_event_id	= cpu_to_le64(msg->ms_event_id);
-}
-
-void msg_bswap_in(msg_t *msg)
-{
-	msg->ms_version[0]	= le32_to_cpu(MSG_VER_MAJOR);
-	msg->ms_version[1]	= le32_to_cpu(MSG_VER_MINOR);
-	msg->ms_version[2]	= le32_to_cpu(MSG_VER_PATCH);
-	msg->ms_type		= le16_to_cpu(msg->ms_type);
-	msg->ms_level		= le16_to_cpu(msg->ms_level);
-	msg->ms_length		= le32_to_cpu(msg->ms_length);
-	msg->ms_global_id	= le32_to_cpu(msg->ms_global_id);
-	msg->ms_event_id	= le64_to_cpu(msg->ms_event_id);
-}
-
-uint64_t make_event_id(group_t *g, int state, int nodeid)
-{
-	uint64_t id;
-	uint32_t n = nodeid;
-	uint32_t memb_count = g->memb_count;
-	uint16_t type = 0;
-
-	if (state == EST_JOIN_BEGIN)
-		type = 1;
-	else if (state == EST_LEAVE_BEGIN)
-		type = 2;
-	else if (state == EST_FAIL_BEGIN)
-		type = 3;
-	else
-		log_error(g, "make_event_id invalid state %d", state);
-
-	id = n;
-	id = id << 32;
-	memb_count = memb_count << 16;
-	id = id | memb_count;
-	id = id | type;
-
-	log_group(g, "make_event_id %llx nodeid %d memb_count %d type %u",
-		  (unsigned long long)id, nodeid, g->memb_count, type);
-
-	return id;
-}
-
-void free_event(event_t *ev)
-{
-	struct nodeid *id, *id_safe;
-
-	list_for_each_entry_safe(id, id_safe, &ev->extended, list) {
-		list_del(&id->list);
-		free(id);
-	}
-	free(ev);
-}
-
-int event_id_to_nodeid(uint64_t id)
-{
-	int nodeid;
-	uint64_t n = id >> 32;
-	nodeid = n & 0xFFFFFFFF;
-	return nodeid;
-}
-
-int event_id_to_type(uint64_t id)
-{
-	uint64_t n;
-	n = id & 0x000000000000FFFF;
-	return ((int) n);
-}
-
-/*
- * Free queued message if:
- * - the id indicates a join for node X and X is a member
- * - the id indicates a leave for node X and X is not a member
- *
- * Note sure if all these cases are relevant, currently we only
- * purge messages after we join.
- */
-
-static void purge_messages(group_t *g)
-{
-	struct save_msg *save, *tmp;
-	node_t *node;
-	int nodeid, type;
-	char *state_str;
-
-	list_for_each_entry_safe(save, tmp, &g->messages, list) {
-		if (save->msg.ms_type == MSG_APP_INTERNAL)
-			continue;
-
-		nodeid = event_id_to_nodeid(save->msg.ms_event_id);
-		type = event_id_to_type(save->msg.ms_event_id);
-		node = find_app_node(g->app, nodeid);
-
-		if ((type == 1 && node) || (type != 1 && !node) ||
-		    (save->msg.ms_type == MSG_APP_RECOVER)) {
-
-			if (save->msg.ms_type == MSG_APP_RECOVER)
-				state_str = "MSG_APP_RECOVER";
-			else if (type == 1)
-				state_str = "EST_JOIN_BEGIN";
-			else if (type == 2)
-				state_str = "EST_LEAVE_BEGIN";
-			else if (type == 3)
-				state_str = "EST_FAIL_BEGIN";
-			else
-				state_str = "error";
-
-			log_group(g, "purge msg %llx from %d %s",
-				  (unsigned long long)save->msg.ms_event_id,
-				  nodeid, state_str);
-
-			list_del(&save->list);
-			if (save->msg_long)
-				free(save->msg_long);
-			free(save);
-		}
-	}
-}
-
-/* For a recovery event where multiple nodes have failed, the event id
-   is based on the lowest nodeid of all the failed nodes.  The event
-   id is also based on the number of remaining group members which
-   changes as failed nodes are added to the recovery event. */
-
-void extend_recover_event(group_t *g, event_t *ev, int nodeid)
-{
-	struct nodeid *id;
-	int new_id_nodeid = nodeid;
-
-	log_group(g, "extend_recover_event for %d with node %d",
-		  ev->nodeid, nodeid);
-
-	/* the lowest nodeid in a recovery event is kept in ev->nodeid,
-	   the other nodeid's are kept in the extended list */
-
-	if (nodeid < ev->nodeid) {
-		new_id_nodeid = ev->nodeid;
-		ev->nodeid = nodeid;
-		ev->id = make_event_id(g, EST_FAIL_BEGIN, nodeid);
-	}
-
-	id = malloc(sizeof(struct nodeid));
-	// FIXME: handle failed malloc
-	id->nodeid = new_id_nodeid;
-	list_add(&id->list, &ev->extended);
-}
-
-struct recovery_set *get_recovery_set(int nodeid)
-{
-	struct recovery_set *rs;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		if (rs->nodeid == nodeid)
-			return rs;
-	}
-
-	rs = malloc(sizeof(*rs));
-	ASSERT(rs);
-	memset(rs, 0, sizeof(struct recovery_set));
-	rs->nodeid = nodeid;
-	rs->cman_update = 0;
-	rs->cpg_update = 0;
-	INIT_LIST_HEAD(&rs->entries);
-
-	list_add_tail(&rs->list, &recovery_sets);
-
-	return rs;
-}
-
-/* When a node fails, all the groups that that node was in are tracked by
-   one of these recovery_sets.  These are the groups that will need layered
-   recovery, i.e. all effected groups must be completely stopped (the app
-   stopped on all nodes) before any are restarted.  When restarted, the groups
-   must be restarted in order from lowest level first.  All groups on each
-   level must complete recovery (on all nodes) before recovery can begin for
-   the next level. */
-
-/* FIXME: do we need to worry about the case where we get an
-   add_recovery_set_cman() that finds an old rs, the old rs completes
-   and goes away, and then we get the add_recovery_set_cpg() matching
-   the _cman() variant that we ignored? */
-
-void add_recovery_set_cman(int nodeid)
-{
-	struct recovery_set *rs;
-
-	log_debug("add_recovery_set_cman nodeid %d", nodeid);
-
-	rs = get_recovery_set(nodeid);
-	if (rs->cman_update) {
-		log_debug("old recovery for %d still in progress", nodeid);
-		return;
-	}
-	rs->cman_update = 1;
-
-	if (!rs->cpg_update && !in_groupd_cpg(nodeid)) {
-		log_debug("free recovery set %d not running groupd", nodeid);
-		list_del(&rs->list);
-		free(rs);
-		return;
-	}
-
-	if (list_empty(&rs->entries) && rs->cpg_update) {
-		log_debug("free unused recovery set %d cman", nodeid);
-		list_del(&rs->list);
-		free(rs);
-	}
-}
-
-/* procdown of 1 means the groupd daemon process exited, but the node didn't
-   fail.  when only the process fails, we won't get a cman callback which is
-   only for nodedown.  if the node wasn't in any groups we don't add a recovery
-   set and don't care about the exited groupd; if the node with the failed
-   groupd _was_ in any groups, we add a rs and process_groupd_confchg() will do
-   cman_kill_node() to make the node really fail (and we'll get an
-   add_recovery_set_cman()). */
-
-struct recovery_set *add_recovery_set_cpg(int nodeid, int procdown)
-{
-	struct recovery_set *rs;
-	struct recovery_entry *re;
-	group_t *g;
-	node_t *node;
-
-	log_debug("add_recovery_set_cpg nodeid %d procdown %d",
-		  nodeid, procdown);
-
-	rs = get_recovery_set(nodeid);
-	if (rs->cpg_update) {
-		log_debug("old recovery for %d still in progress", nodeid);
-		return rs;
-	}
-	rs->cpg_update = 1;
-
-	list_for_each_entry(g, &gd_groups, list) {
-		list_for_each_entry(node, &g->app->nodes, list) {
-			if (node->nodeid == nodeid) {
-				log_group(g, "add to recovery set %d", nodeid);
-				re = malloc(sizeof(*re));
-				// FIXME: handle failed malloc
-				memset(re, 0, sizeof(struct recovery_entry));
-				re->group = g;
-				list_add_tail(&re->list, &rs->entries);
-				break;
-			}
-		}
-	}
-
-	if (list_empty(&rs->entries)) {
-		if (rs->cman_update || procdown) {
-			log_debug("free unused recovery set %d cpg", nodeid);
-			list_del(&rs->list);
-			free(rs);
-			return NULL;
-		}
-	}
-
-	return rs;
-}
-
-void _del_recovery_set(group_t *g, int nodeid, int purge)
-{
-	struct recovery_set *rs, *rs2;
-	struct recovery_entry *re, *re2;
-	int found = 0, entries_not_recovered;
-
-	list_for_each_entry_safe(rs, rs2, &recovery_sets, list) {
-		if (rs->nodeid != nodeid)
-			continue;
-
-		entries_not_recovered = 0;
-
-		list_for_each_entry_safe(re, re2, &rs->entries, list) {
-			if (re->group == g) {
-				if (purge) {
-					list_del(&re->list);
-					free(re);
-					log_group(g, "purged from rs %d",
-						  rs->nodeid);
-				} else {
-					re->recovered = 1;
-					log_group(g, "done in recovery set %d",
-					  	  rs->nodeid);
-					found++;
-				}
-			} else {
-				if (re->recovered == 0)
-					entries_not_recovered++;
-			}
-		}
-
-		if (entries_not_recovered) {
-			log_debug("recovery set %d has %d entries not done",
-				  rs->nodeid, entries_not_recovered);
-			continue;
-		}
-
-		/* all entries in this rs are recovered, free it */
-		log_debug("recovery set %d is all done", rs->nodeid);
-
-		list_for_each_entry_safe(re, re2, &rs->entries, list) {
-			list_del(&re->list);
-			free(re);
-		}
-		list_del(&rs->list);
-		free(rs);
-	}
-
-	if (!found)
-		log_group(g, "not found in any recovery sets for %d", nodeid);
-}
-
-/* A group has finished recovery for given event (which can encompass more than
-   one failed nodeid).  Remove this group from recovery sets for those nodeids
-   and free any recovery sets that are now completed. */
-
-void del_recovery_set(group_t *g, event_t *ev, int purge)
-{
-	struct nodeid *id;
-
-	log_group(g, "rev %llx done, remove group from rs %d",
-		  (unsigned long long)ev->id, ev->nodeid);
-	_del_recovery_set(g, ev->nodeid, purge);
-
-	list_for_each_entry(id, &ev->extended, list) {
-		log_group(g, "rev %llx done, remove group from rs %d",
-			  (unsigned long long)ev->id, id->nodeid);
-		_del_recovery_set(g, id->nodeid, purge);
-	}
-}
-
-/* go through all recovery sets and check that all failed nodes have
-   been removed by cman callbacks; if they haven't then cman may be
-   inquorate and we just haven't gotten the cman callback yet that
-   will set cman_quorate = 0  [group recoveries are driven by cpg
-   callbacks, not cman callbacks, so that's why we might be trying
-   to do recovery without having heard from cman yet.] */
-
-int cman_quorum_updated(void)
-{
-	struct recovery_set *rs;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		if (rs->cman_update)
-			continue;
-		log_debug("no cman update for recovery_set %d quorate %d",
-			  rs->nodeid, cman_quorate);
-		return 0;
-	}
-	return 1;
-}
-
-int is_recovery_event(event_t *ev)
-{
-	if (event_id_to_type(ev->id) == 3)
-		return 1;
-	return 0;
-}
-
-/* all groups referenced by a recovery set are stopped on all nodes,
-   and stopped for recovery */
-
-static int set_is_all_stopped(struct recovery_set *rs, event_t *rev)
-{
-	struct recovery_entry *re;
-	event_t *ev;
-
-	list_for_each_entry(re, &rs->entries, list) {
-		ev = re->group->app->current_event;
-
-		/* we need to use ev->fail_all_stopped instead of checking
-		   ev->state == FAIL_ALL_STOPPED because if two groups are at
-		   the low level, one will detect all_levels_all_stopped first
-		   and then immediately move on to starting before the other,
-		   also checking all_levels_all_stopped, can see it's in
-		   FAIL_ALL_STOPPED */
-
-		if (ev && is_recovery_event(ev) && ev->fail_all_stopped)
-			continue;
-		else
-			return 0;
-	}
-	return 1;
-}
-
-/* for every recovery set that this group is in, are all other groups in
-   each of those sets in the "all stopped" state for recovery? */
-
-static int all_levels_all_stopped(group_t *g, event_t *rev)
-{
-	struct recovery_set *rs;
-	struct recovery_entry *re;
-	int found = 0;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		list_for_each_entry(re, &rs->entries, list) {
-			if (re->group == g) {
-				found = 1;
-				if (set_is_all_stopped(rs, rev))
-					break;
-				else
-					return 0;
-			}
-		}
-	}
-
-	if (!found)
-		return 0;
-	return 1;
-}
-
-void dump_recovery_sets(void)
-{
-	struct recovery_set *rs;
-	struct recovery_entry *re;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		log_debug("recovery_set %d", rs->nodeid);
-		list_for_each_entry(re, &rs->entries, list) {
-			log_debug("  recovery_entry %d:%s recovered %d",
-				  re->group->level, re->group->name,
-				  re->recovered);
-		}
-	}
-}
-
-static int group_in_recovery_set(struct recovery_set *rs, group_t *g)
-{
-	struct recovery_entry *re;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		list_for_each_entry(re, &rs->entries, list) {
-			if (re->group == g)
-				return 1;
-		}
-	}
-	return 0;
-}
-
-static int rs_lower_levels_recovered(struct recovery_set *rs, int level)
-{
-	struct recovery_entry *re;
-
-	list_for_each_entry(re, &rs->entries, list) {
-		if (re->group->level < level && !re->recovered)
-			return 0;
-	}
-	return 1;
-}
-
-/* lower level groups should be recovered in each rs this group is in */
-
-static int lower_levels_recovered(group_t *g)
-{
-	struct recovery_set *rs;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		if (!group_in_recovery_set(rs, g))
-			continue;
-
-		if (rs_lower_levels_recovered(rs, g->level))
-			continue;
-
-		log_group(g, "lower levels not recovered in rs %d", rs->nodeid);
-		return 0;
-	}
-	return 1;
-}
-
-/* We're interested in any unrecovered group at a lower level than g, not
-   just lower groups in the same recovery set. */
-
-static int lower_groups_need_recovery(group_t *g)
-{
-	struct recovery_set *rs;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		if (rs_lower_levels_recovered(rs, g->level))
-			continue;
-		log_group(g, "lower group not recovered in rs %d", rs->nodeid);
-		return 1;
-	}
-	return 0;
-}
-
-static int level_is_lowest(struct recovery_set *rs, int level)
-{
-	struct recovery_entry *re;
-
-	list_for_each_entry(re, &rs->entries, list) {
-		if (re->group->level < level)
-			return 0;
-	}
-	return 1;
-}
-
-/* this group is at the lowest level in any recovery sets it's in */
-
-static int lowest_level(group_t *g)
-{
-	struct recovery_set *rs;
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		if (!group_in_recovery_set(rs, g))
-			continue;
-		if (level_is_lowest(rs, g->level))
-			continue;
-		return 0;
-	}
-	return 1;
-}
-
-static event_t *create_event(group_t *g)
-{
-	event_t *ev;
-
-	ev = malloc(sizeof(event_t));
-	ASSERT(ev);
-
-	memset(ev, 0, sizeof(event_t));
-
-	INIT_LIST_HEAD(&ev->memb);
-	INIT_LIST_HEAD(&ev->extended);
-	ev->event_nr = ++gd_event_nr;
-
-	return ev;
-}
-
-int queue_app_recover(group_t *g, int nodeid)
-{
-	event_t *ev;
-
-	ev = create_event(g);
-	ev->nodeid = nodeid;
-	ev->state = EST_FAIL_BEGIN;
-	ev->fail_all_stopped = 0;
-	ev->id = make_event_id(g, EST_FAIL_BEGIN, nodeid);
-
-	log_group(g, "queue recover event for nodeid %d", nodeid);
-
-	list_add_tail(&ev->list, &g->app->events);
-	return 0;
-}
-
-void del_event_nodes(event_t *ev)
-{
-	node_t *node, *n;
-
-	list_for_each_entry_safe(node, n, &ev->memb, list) {
-		list_del(&node->list);
-		free(node);
-	}
-}
-
-static void add_event_nodes(group_t *g, event_t *ev)
-{
-	node_t *node, *n;
-
-	list_for_each_entry(node, &g->memb, list) {
-		n = new_node(node->nodeid);
-		list_add(&n->list, &ev->memb);
-	}
-}
-
-event_t *search_event(group_t *g, int nodeid)
-{
-	event_t *ev;
-
-	list_for_each_entry(ev, &g->app->events, list) {
-		if (ev->nodeid == nodeid)
-			return ev;
-	}
-	return NULL;
-}
-
-void dump_queued_events(group_t *g)
-{
-	event_t *ev;
-
-	list_for_each_entry(ev, &g->app->events, list) {
-		log_group(g, "    queued ev %d %llx %s",
-			  ev->nodeid, (unsigned long long)ev->id,
-			  ev_state_str(ev));
-	}
-}
-
-int queue_app_join(group_t *g, int nodeid)
-{
-	event_t *ev;
-
-	/* sanity check */
-	ev = g->app->current_event;
-	if (ev && ev->nodeid == nodeid) {
-		log_group(g, "queue_app_join: current event %d %llx %s",
-			  nodeid, (unsigned long long)ev->id, ev_state_str(ev));
-	}
-
-	/* sanity check */
-	ev = search_event(g, nodeid);
-	if (ev) {
-		log_group(g, "queue_app_join: queued event %d %llx %s",
-			  nodeid, (unsigned long long)ev->id, ev_state_str(ev));
-	}
-
-	ev = create_event(g);
-	ev->nodeid = nodeid;
-	ev->state = EST_JOIN_BEGIN;
-	ev->id = make_event_id(g, EST_JOIN_BEGIN, nodeid);
-
-	log_group(g, "queue join event for nodeid %d", nodeid);
-	dump_queued_events(g);
-
-	if (nodeid == our_nodeid)
-		add_event_nodes(g, ev);
-
-	list_add_tail(&ev->list, &g->app->events);
-	return 0;
-}
-
-int queue_app_leave(group_t *g, int nodeid)
-{
-	event_t *ev;
-
-	/* sanity check */
-	ev = g->app->current_event;
-	if (ev && ev->nodeid == nodeid) {
-		log_group(g, "queue_app_leave: current event %d %llx %s",
-			  nodeid, (unsigned long long)ev->id, ev_state_str(ev));
-	}
-
-	/* sanity check */
-	ev = search_event(g, nodeid);
-	if (ev) {
-		log_group(g, "queue_app_leave: queued event %d %llx %s",
-			  nodeid, (unsigned long long)ev->id, ev_state_str(ev));
-	}
-
-	ev = create_event(g);
-	ev->nodeid = nodeid;
-	ev->state = EST_LEAVE_BEGIN;
-	ev->id = make_event_id(g, EST_LEAVE_BEGIN, nodeid);
-
-	log_group(g, "queue leave event for nodeid %d", nodeid);
-	dump_queued_events(g);
-
-	list_add_tail(&ev->list, &g->app->events);
-	return 0;
-}
-
-int queue_app_message(group_t *g, struct save_msg *save)
-{
-	/* log_group(g, "queue message %s from %d",
-	             msg_type(save->msg.ms_type), save->nodeid); */
-	list_add_tail(&save->list, &g->messages);
-	return 0;
-}
-
-/* This is called when we get the nodedown for the per-group cpg; we know
-   that after the cpg nodedown we won't get any further messages. bz 436984
-   It's conceivable but unlikely that the nodedown processing (initiated by
-   the groupd cpg nodedown) could begin before the per-group cpg nodedown
-   is received where this purging occurs.  If it does, then we may need to
-   add code to wait for the nodedown to happen in both the groupd cpg and the
-   per-group cpg before processing the nodedown. */
-
-void purge_node_messages(group_t *g, int nodeid)
-{
-	struct save_msg *save, *tmp;
-
-	list_for_each_entry_safe(save, tmp, &g->messages, list) {
-		if (save->nodeid != nodeid)
-			continue;
-
-		log_group(g, "purge msg from dead node %d", nodeid);
-
-		list_del(&save->list);
-		if (save->msg_long)
-			free(save->msg_long);
-		free(save);
-	}
-}
-
-static void del_app_nodes(app_t *a)
-{
-	node_t *node, *tmp;
-
-	list_for_each_entry_safe(node, tmp, &a->nodes, list) {
-		list_del(&node->list);
-		free(node);
-	}
-}
-
-node_t *find_app_node(app_t *a, int nodeid)
-{
-	node_t *node;
-
-	list_for_each_entry(node, &a->nodes, list) {
-		if (node->nodeid == nodeid)
-			return node;
-	}
-	return NULL;
-}
-
-int is_our_join(event_t *ev)
-{
-	return (ev->nodeid == our_nodeid);
-}
-
-static int is_our_leave(event_t *ev)
-{
-	return (ev->nodeid == our_nodeid);
-}
-
-/* Called after all nodes have acked that they're stopped for our
-   leave.  We get their stopped messages even though we've left the
-   cpg because the messages are sent through the groupd cpg.
-   groupd_down() will fill in stops for us for nodes that fail before
-   sending stopped for our leave. */
-
-void finalize_our_leave(group_t *g)
-{
-	struct recovery_set *rs;
-	struct recovery_entry *re, *re2;
-	app_t *a = g->app;
-
-	log_group(g, "finalize_our_leave");
-
-	app_terminate(a);
-	cpg_finalize(g->cpg_handle);
-	client_dead(g->cpg_client);
-	g->app = NULL;
-	del_app_nodes(a);
-	free(a);
-
-	/* this group shouldn't be in any recovery sets... sanity check
-	   and avoid future segfault by removing re's referencing this g */
-
-	list_for_each_entry(rs, &recovery_sets, list) {
-		list_for_each_entry_safe(re, re2, &rs->entries, list) {
-			if (re->group == g) {
-				log_error(g, "finalize: still in recovery "
-					  "set %d", rs->nodeid);
-				list_del(&re->list);
-				free(re);
-			}
-		}
-	}
-
-	remove_group(g);
-}
-
-static int send_stopped(group_t *g)
-{
-	msg_t msg;
-	event_t *ev = g->app->current_event;
-
-	memset(&msg, 0, sizeof(msg));
-	msg.ms_type = MSG_APP_STOPPED;
-	msg.ms_global_id = g->global_id;
-	msg.ms_event_id = ev->id;
-	msg.ms_level = g->level;
-	memcpy(&msg.ms_name, &g->name, MAX_NAMELEN);
-
-	msg_bswap_out(&msg);
-
-	log_group(g, "send stopped");
-	return send_message_groupd(g, &msg, sizeof(msg), MSG_APP_STOPPED);
-}
-
-static int send_started(group_t *g)
-{
-	msg_t msg;
-	event_t *ev = g->app->current_event;
-
-	memset(&msg, 0, sizeof(msg));
-	msg.ms_type = MSG_APP_STARTED;
-	msg.ms_global_id = g->global_id;
-	msg.ms_event_id = ev->id;
-	msg.ms_level = g->level;
-	memcpy(&msg.ms_name, &g->name, MAX_NAMELEN);
-
-	msg_bswap_out(&msg);
-
-	log_group(g, "send started");
-	return send_message_groupd(g, &msg, sizeof(msg), MSG_APP_STARTED);
-}
-
-static int send_recover(group_t *g, event_t *rev)
-{
-	msg_t msg;
-
-	memset(&msg, 0, sizeof(msg));
-	msg.ms_type = MSG_APP_RECOVER;
-	msg.ms_global_id = g->global_id;
-	msg.ms_event_id = rev->id;
-	msg.ms_level = g->level;
-	memcpy(&msg.ms_name, &g->name, MAX_NAMELEN);
-
-	msg_bswap_out(&msg);
-
-	log_group(g, "send recover");
-	return send_message_groupd(g, &msg, sizeof(msg), MSG_APP_RECOVER);
-}
-
-int do_stopdone(char *name, int level)
-{
-	group_t *g;
-	g = find_group_level(name, level);
-	return send_stopped(g);
-}
-
-int do_startdone(char *name, int level, int event_nr)
-{
-	group_t *g;
-	event_t *ev;
-	char *state;
-
-	g = find_group_level(name, level);
-	if (!g) {
-		log_print("do_startdone: no group level %d name %s",
-			  level, name);
-		return -1;
-	}
-
-	ev = g->app->current_event;
-
-	state = ev ? ev_state_str(ev) : "no-event";
-
-	if (!ev || ev->event_nr != event_nr) {
-		log_group(g, "ignore startdone %d state %s", event_nr, state);
-		return 0;
-	}
-
-	if (!event_state_starting(g->app)) {
-		log_error(g, "IGNORE startdone %d state %s", event_nr, state);
-		return 0;
-	}
-
-	return send_started(g);
-}
-
-char *ev_state_str(event_t *ev)
-{
-	switch (ev->state) {
-	case EST_JOIN_BEGIN:
-		return "JOIN_BEGIN";
-	case EST_JOIN_STOP_WAIT:
-		return "JOIN_STOP_WAIT";
-	case EST_JOIN_ALL_STOPPED:
-		return "JOIN_ALL_STOPPED";
-	case EST_JOIN_START_WAIT:
-		return "JOIN_START_WAIT";
-	case EST_JOIN_ALL_STARTED:
-		return "JOIN_ALL_STARTED";
-	case EST_LEAVE_BEGIN:
-		return "LEAVE_BEGIN";
-	case EST_LEAVE_STOP_WAIT:
-		return "LEAVE_STOP_WAIT";
-	case EST_LEAVE_ALL_STOPPED:
-		return "LEAVE_ALL_STOPPED";
-	case EST_LEAVE_START_WAIT:
-		return "LEAVE_START_WAIT";
-	case EST_LEAVE_ALL_STARTED:
-		return "LEAVE_ALL_STARTED";
-	case EST_FAIL_BEGIN:
-		return "FAIL_BEGIN";
-	case EST_FAIL_STOP_WAIT:
-		return "FAIL_STOP_WAIT";
-	case EST_FAIL_ALL_STOPPED:
-		return "FAIL_ALL_STOPPED";
-	case EST_FAIL_START_WAIT:
-		return "FAIL_START_WAIT";
-	case EST_FAIL_ALL_STARTED:
-		return "FAIL_ALL_STARTED";
-	default:
-		return "unknown";
-	}
-}
-
-static int count_nodes_not_stopped(app_t *a)
-{
-	node_t *node;
-	int i = 0;
-
-	list_for_each_entry(node, &a->nodes, list) {
-		if (!node->stopped)
-			i++;
-	}
-	return i;
-}
-
-int event_state_begin(app_t *a)
-{
-	if (a->current_event->state == EST_JOIN_BEGIN ||
-	    a->current_event->state == EST_LEAVE_BEGIN ||
-	    a->current_event->state == EST_FAIL_BEGIN)
-		return TRUE;
-	return FALSE;
-}
-
-int event_state_stopping(app_t *a)
-{
-	if (a->current_event->state == EST_JOIN_STOP_WAIT ||
-	    a->current_event->state == EST_LEAVE_STOP_WAIT ||
-	    a->current_event->state == EST_FAIL_STOP_WAIT)
-		return TRUE;
-	return FALSE;
-}
-
-int event_state_starting(app_t *a)
-{
-	if (a->current_event->state == EST_JOIN_START_WAIT ||
-	    a->current_event->state == EST_LEAVE_START_WAIT ||
-	    a->current_event->state == EST_FAIL_START_WAIT)
-		return TRUE;
-	return FALSE;
-}
-
-int event_state_all_stopped(app_t *a)
-{
-	if (a->current_event->state == EST_JOIN_ALL_STOPPED ||
-	    a->current_event->state == EST_LEAVE_ALL_STOPPED ||
-	    a->current_event->state == EST_FAIL_ALL_STOPPED)
-		return TRUE;
-	return FALSE;
-}
-
-int event_state_all_started(app_t *a)
-{
-	if (a->current_event->state == EST_JOIN_ALL_STARTED ||
-	    a->current_event->state == EST_LEAVE_ALL_STARTED ||
-	    a->current_event->state == EST_FAIL_ALL_STARTED)
-		return TRUE;
-	return FALSE;
-}
-
-static int process_current_event(group_t *g)
-{
-	app_t *a = g->app;
-	event_t *ev = a->current_event;
-	node_t *node, *n;
-	struct nodeid *id;
-	int rv = 0, do_start = 0, count;
-
-	if (!(event_state_stopping(a) || event_state_starting(a)))
-		log_group(g, "process_current_event %llx %d %s",
-			  (unsigned long long)ev->id, ev->nodeid,
-			  ev_state_str(ev));
-
-	switch (ev->state) {
-
-	case EST_JOIN_BEGIN:
-		ev->state = EST_JOIN_STOP_WAIT;
-
-		if (is_our_join(ev)) {
-			/* the initial set of members that we've joined,
-			   includes us */
-
-			list_for_each_entry_safe(node, n, &ev->memb, list) {
-				list_move(&node->list, &a->nodes);
-				a->node_count++;
-				log_group(g, "app node init: add %d total %d",
-					  node->nodeid, a->node_count);
-			}
-
-			/* we could have the joining node send out a stopped
-			   message here for all to receive and count but
-			   that's unnecessary, we just have everyone
-			   set the joining node as stopped initially */
-
-			node = find_app_node(a, our_nodeid);
-			ASSERT(node);
-			node->stopped = 1;
-
-			/* if we're the first node to be joining, move
-			   ahead to the JOIN_ALL_STOPPED state */
-
-			if (a->node_count == 1)
-				ev->state++;
-
-			rv = 1;
-		} else {
-			app_stop(a);
-
-			node = new_node(ev->nodeid);
-			list_add(&node->list, &a->nodes);
-			a->node_count++;
-			log_group(g, "app node join: add %d total %d",
-				  node->nodeid, a->node_count);
-			node->stopped = 1;
-		}
-		break;
-
-	case EST_JOIN_STOP_WAIT:
-		count = count_nodes_not_stopped(a);
-		log_group(g, "waiting for %d more stopped messages "
-			  "before JOIN_ALL_STOPPED %d", count, ev->nodeid);
-		break;
-
-	case EST_JOIN_ALL_STOPPED:
-		if (!cman_quorate) {
-			log_group(g, "wait for quorum before starting app");
-			break;
-		}
-
-		/* We want to move ahead to start here if this ev is to be
-		   started before a pending rev that will abort it.  Once
-		   started, the rev becomes current and stops the app
-		   immediately. */
-
-		if (lower_groups_need_recovery(g) &&
-		    !ev->start_app_before_pending_rev) {
-			log_group(g, "wait for lower_groups_need_recovery "
-				  "before starting app");
-			break;
-		}
-		ev->start_app_before_pending_rev = 0;
-
-		ev->state = EST_JOIN_START_WAIT;
-
-		if (!g->have_set_id) {
-			g->have_set_id = 1;
-			app_setid(a);
-		}
-
-		app_start(a);
-		break;
-
-	case EST_JOIN_ALL_STARTED:
-		app_finish(a);
-
-		if (is_our_join(ev)) {
-			purge_messages(g);
-			g->joining = 0;
-		}
-		free_event(ev);
-		a->current_event = NULL;
-		rv = 1;
-		break;
-
-	case EST_LEAVE_BEGIN:
-		ev->state = EST_LEAVE_STOP_WAIT;
-		app_stop(a);
-		break;
-
-	case EST_LEAVE_STOP_WAIT:
-		count = count_nodes_not_stopped(a);
-		log_group(g, "waiting for %d more stopped messages "
-			  "before LEAVE_ALL_STOPPED %d", count, ev->nodeid);
-		break;
-
-	case EST_LEAVE_ALL_STOPPED:
-		if (is_our_leave(ev)) {
-			/* frees group structure */
-			finalize_our_leave(g);
-			rv = -1;
-			break;
-		}
-		ev->state = EST_LEAVE_START_WAIT;
-
-		node = find_app_node(a, ev->nodeid);
-		list_del(&node->list);
-		a->node_count--;
-		log_group(g, "app node leave: del %d total %d",
-			  node->nodeid, a->node_count);
-		free(node);
-		app_start(a);
-		break;
-
-	case EST_LEAVE_ALL_STARTED:
-		app_finish(a);
-		free_event(ev);
-		a->current_event = NULL;
-		rv = 1;
-		break;
-
-	case EST_FAIL_BEGIN:
-		ev->state = EST_FAIL_STOP_WAIT;
-		app_stop(a);
-
-		/* set the failed nodes as stopped since we won't
-		   be getting a "stopped" message from them.  the node
-		   may already have been removed in the case where one
-		   rev interrupts another */
-
-		node = find_app_node(a, ev->nodeid);
-		if (node)
-			node->stopped = 1;
-
-		/* multiple nodes failed together making an extended event */
-		list_for_each_entry(id, &ev->extended, list) {
-			node = find_app_node(a, id->nodeid);
-			if (node)
-				node->stopped = 1;
-		}
-
-		break;
-
-	case EST_FAIL_STOP_WAIT:
-		count = count_nodes_not_stopped(a);
-		log_group(g, "waiting for %d more stopped messages "
-			  "before FAIL_ALL_STOPPED %d", count, ev->nodeid);
-		break;
-
-	case EST_FAIL_ALL_STOPPED:
-		ev->fail_all_stopped = 1;
-
-		/* when recovering for failed nodes, we immediately stop all
-		   apps the node was involved with but wait for quorum before
-		   starting them again  */
-
-		/* we make sure that cman has updated our quorum status since
-		   the last node failure */
-
-		if (!cman_quorum_updated())
-			break;
-
-		if (!cman_quorate)
-			break;
-
-		if (lowest_level(g)) {
-			if (all_levels_all_stopped(g, ev)) {
-				ev->state = EST_FAIL_START_WAIT;
-				do_start = 1;
-			} else
-				log_group(g, "wait for all_levels_all_stopped");
-		} else {
-			if (lower_levels_recovered(g)) {
-				ev->state = EST_FAIL_START_WAIT;
-				do_start = 1;
-			} else
-				log_group(g, "wait for lower_levels_recovered");
-		}
-
-		if (!do_start)
-			break;
-
-		node = find_app_node(a, ev->nodeid);
-		if (node) {
-			a->node_count--;
-			log_group(g, "app node fail: del node %d total %d",
-			  	  node->nodeid, a->node_count);
-			list_del(&node->list);
-			free(node);
-		} else
-			log_group(g, "app node fail: %d prev removed",
-				  ev->nodeid);
-
-		list_for_each_entry(id, &ev->extended, list) {
-			node = find_app_node(a, id->nodeid);
-			if (node) {
-				a->node_count--;
-				log_group(g, "app node fail: del node %d "
-					  "total %d, ext", node->nodeid,
-					  a->node_count);
-				list_del(&node->list);
-				free(node);
-			} else
-				log_group(g, "app node fail: %d prev removed",
-					  id->nodeid);
-		}
-
-		app_start(a);
-		break;
-
-	case EST_FAIL_ALL_STARTED:
-		app_finish(a);
-		del_recovery_set(g, ev, 0);
-		free_event(ev);
-		a->current_event = NULL;
-		rv = 1;
-		break;
-
-	default:
-		/*
-		log_group(g, "nothing to do: %llx %d %s",
-			  (unsigned long long)ev->id, ev->nodeid,
-			  ev_state_str(ev));
-		*/
-		break;
-	}
-
-	return rv;
-}
-
-static void clear_all_nodes_stopped(app_t *a)
-{
-	node_t *node;
-	log_group(a->g, "clear_all_nodes_stopped");
-	list_for_each_entry(node, &a->nodes, list)
-		node->stopped = 0;
-}
-
-static int mark_node_stopped(app_t *a, int nodeid)
-{
-	node_t *node;
-
-	/* we might get a stopped message from another node who's going
-	   through X_BEGIN before we get to X_BEGIN ourselves, so we need
-	   to accept their message if we're in X_BEGIN, too */
-
-	if (!event_state_stopping(a) && !event_state_begin(a)) {
-		log_error(a->g, "mark_node_stopped: event not stopping/begin: "
-			  "state %s from %d",
-			  ev_state_str(a->current_event), nodeid);
-		return -1;
-	}
-
-	node = find_app_node(a, nodeid);
-	if (!node) {
-		log_error(a->g, "mark_node_stopped: no nodeid %d", nodeid);
-		return -1;
-	}
-
-	log_group(a->g, "mark node %d stopped", nodeid);
-
-	node->stopped = 1;
-	node->started = 0;
-
-	return 0;
-}
-
-static int mark_node_started(app_t *a, int nodeid)
-{
-	node_t *node;
-
-	if (!event_state_starting(a))
-		log_group(a->g, "mark_node_started: event not starting %d "
-			  "from %d", a->current_event->state, nodeid);
-
-	node = find_app_node(a, nodeid);
-	if (!node) {
-		log_error(a->g, "mark_node_started: no nodeid %d", nodeid);
-		return -1;
-	}
-
-	log_group(a->g, "mark node %d started", nodeid);
-
-	node->stopped = 0;
-	node->started = 1;
-
-	return 0;
-}
-
-static int all_nodes_stopped(app_t *a)
-{
-	node_t *node;
-
-	list_for_each_entry(node, &a->nodes, list) {
-		if (!node->stopped) {
-			/* ASSERT(node->started); */
-			return FALSE;
-		}
-	}
-	return TRUE;
-}
-
-static int all_nodes_started(app_t *a)
-{
-	node_t *node;
-
-	list_for_each_entry(node, &a->nodes, list) {
-		if (!node->started) {
-			/* ASSERT(node->stopped); */
-			return FALSE;
-		}
-	}
-	return TRUE;
-}
-
-static int process_app_messages(group_t *g)
-{
-	app_t *a = g->app;
-	struct save_msg *save, *tmp;
-	event_t *ev;
-	int rv = 0;
-
-	list_for_each_entry_safe(save, tmp, &g->messages, list) {
-
-		/* internal messages, sent not by groupd but by apps
-		   to each other, are delivered to the apps in
-		   deliver_app_messages() */
-
-		if (save->msg.ms_type == MSG_APP_INTERNAL)
-			continue;
-
-		ev = a->current_event;
-
-		if (save->msg.ms_type == MSG_APP_RECOVER) {
-			if (ev && ev->state == EST_JOIN_STOP_WAIT &&
-			    is_our_join(ev)) {
-				/* keep this msg around for
-				   recover_current_event() to see, it will
-				   be purged later */
-				if (!save->print_ignore) {
-					log_group(g, "rev %llx taken on node %d",
-						   (unsigned long long)save->msg.ms_event_id,
-						   save->nodeid);
-					save->print_ignore = 1;
-				}
-				continue;
-			} else {
-				goto free_save;
-			}
-		}
-
-
-		if (!ev || ev->id != save->msg.ms_event_id) {
-			if (!save->print_ignore) {
-				log_group(g, "ignore msg from %d id %llx %s",
-				  	  save->nodeid,
-					  (unsigned long long)save->msg.ms_event_id,
-				  	  msg_type(save->msg.ms_type));
-				save->print_ignore = 1;
-			}
-			continue;
-		}
-
-		switch (save->msg.ms_type) {
-
-		case MSG_APP_STOPPED:
-			mark_node_stopped(a, save->nodeid);
-			break;
-
-		case MSG_APP_STARTED:
-			mark_node_started(a, save->nodeid);
-			break;
-
-		default:
-			log_error(g, "process_app_messages: invalid type %d "
-				  "from %d", save->msg.ms_type, save->nodeid);
-		}
-
-		if (g->global_id == 0 && save->msg.ms_global_id != 0) {
-			g->global_id = save->msg.ms_global_id;
-			log_group(g, "set global_id %x from %d",
-				  g->global_id, save->nodeid);
-		}
-	 free_save:
-		list_del(&save->list);
-		if (save->msg_long)
-			free(save->msg_long);
-		free(save);
-		rv = 1;
-	}
-
-	/* state changes to X_ALL_STOPPED or X_ALL_STARTED */
-
-	if (event_state_stopping(a) && all_nodes_stopped(a))
-		a->current_event->state++;
-
-	if (event_state_starting(a) && all_nodes_started(a))
-		a->current_event->state++;
-
-	return rv;
-}
-
-static void deliver_app_messages(group_t *g)
-{
-	app_t *a = g->app;
-	struct save_msg *save, *tmp;
-
-	list_for_each_entry_safe(save, tmp, &g->messages, list) {
-		switch (save->msg.ms_type) {
-		case MSG_APP_INTERNAL:
-			app_deliver(a, save);
-			break;
-		default:
-			continue;
-		}
-
-		list_del(&save->list);
-		if (save->msg_long)
-			free(save->msg_long);
-		free(save);
-	}
-}
-
-event_t *find_queued_recover_event(group_t *g)
-{
-	event_t *ev;
-
-	list_for_each_entry(ev, &g->app->events, list) {
-		if (ev->state == EST_FAIL_BEGIN)
-			return ev;
-	}
-	return NULL;
-}
-
-#if 0
-static int group_started(event_t *ev)
-{
-	switch (ev->state) {
-	case EST_JOIN_BEGIN:
-	case EST_JOIN_STOP_WAIT:
-	case EST_JOIN_ALL_STOPPED:
-	case EST_LEAVE_BEGIN:
-	case EST_LEAVE_STOP_WAIT:
-	case EST_LEAVE_ALL_STOPPED:
-	case EST_FAIL_BEGIN:
-	case EST_FAIL_STOP_WAIT:
-	case EST_FAIL_ALL_STOPPED:
-		return 0;
-	default:
-		return 1;
-	};
-}
-#endif
-
-void dump_group(group_t *g)
-{
-	app_t *a = g->app;
-	node_t *node;
-	struct save_msg *save;
-	event_t *ev;
-
-	printf("---\n");
-	printf("name: %s\n", g->name);
-	printf("level: %d\n", g->level);
-	printf("global_id: %u\n", g->global_id);
-	printf("cpg handle: %llx\n", (unsigned long long)g->cpg_handle);
-	printf("cpg client: %d\n", g->cpg_client);
-	printf("app client: %d\n", g->app->client);
-
-	printf("memb count: %u\n", g->memb_count);
-	printf("memb list: ");
-	list_for_each_entry(node, &g->memb, list)
-		printf("%d ", node->nodeid);
-	printf("\n");
-
-	printf("app node count: %u\n", g->app->node_count);
-	printf("app node list: ");
-	list_for_each_entry(node, &g->app->nodes, list)
-		printf("%d ", node->nodeid);
-	printf("\n");
-
-	printf("saved messages: ");
-	list_for_each_entry(save, &g->messages, list)
-		printf("%d/%d ", save->nodeid, save->msg.ms_type);
-	printf("\n");
-
-	if (a->current_event)
-		printf("current_event %d-%d\n", a->current_event->nodeid, a->current_event->state);
-
-	printf("events: ");
-	list_for_each_entry(ev, &a->events, list)
-		printf("%d-%d ", ev->nodeid, ev->state);
-	printf("\n");
-
-	printf("---\n");
-}
-
-void dump_all_groups(void)
-{
-	group_t *g;
-	list_for_each_entry(g, &gd_groups, list)
-		dump_group(g);
-}
-
-/* handle a node failure while processing an event. returning > 0 means
-   we want process_current_event() to be called for the group */
-
-int recover_current_event(group_t *g)
-{
-	app_t *a = g->app;
-	event_t *ev, *rev;
-	node_t *node, *us;
-	struct save_msg *save;
-	struct nodeid *id, *safe;
-	int rv = 0;
-
-	ev = a->current_event;
-	if (!ev)
-		return 0;
-
-	rev = find_queued_recover_event(g);
-	if (!rev)
-		return 0;
-
-	/* if the current ev is for recovery, we merge the new rev into it;
-	   if the current ev is still stopping (or all stopped), it just
-	   continues as usual; if the current ev is starting, the state is
-	   reset back to FAIL_BEGIN so it goes through a stopping cycle for
-	   the new node failure that's been added to it */
-
-	if (is_recovery_event(ev)) {
-		log_group(g, "merge new rev %d into current rev %d %s",
-			  rev->nodeid, ev->nodeid, ev_state_str(ev));
-
-		if (ev->state > EST_FAIL_ALL_STOPPED) {
-			ev->state = EST_FAIL_BEGIN;
-			ev->fail_all_stopped = 0;
-			clear_all_nodes_stopped(a);
-		} else if (event_state_stopping(a)) {
-			mark_node_stopped(a, rev->nodeid);
-			list_for_each_entry(id, &rev->extended, list)
-				mark_node_stopped(a, id->nodeid);
-		}
-
-		id = malloc(sizeof(struct nodeid));
-		// FIXME: handle failed malloc
-		id->nodeid = rev->nodeid;
-		list_add(&id->list, &ev->extended);
-		log_group(g, "extend active rev %d with failed node %d",
-			  ev->nodeid, rev->nodeid);
-		list_for_each_entry_safe(id, safe, &rev->extended, list) {
-			list_del(&id->list);
-			list_add(&id->list, &ev->extended);
-			log_group(g, "extend active rev %d with failed node %d",
-				  ev->nodeid, id->nodeid);
-		}
-
-		send_recover(g, rev);
-		list_del(&rev->list);
-		free_event(rev);
-		return 1;
-	}
-
-	/* This is a really gross situation, wish I could find a better way
-	   to deal with it... (rev's skip ahead of other queued ev's, I think
-	   that's the root of the difficulties here, we don't know if the
-	   rev has skipped ahead of our join on remote nodes or not).
-
-	   If our own join event is current on other nodes, then we want a
-	   rev (which will replace our join ev once it's starting).  If our
-	   join event isn't current on other nodes, then recovery will occur
-	   before we're added to the app group and the rev doesn't apply to us
-	   (apart from needing to remove the failed node from the memb list).
-
-	   We won't know if our join ev is current on other nodes, though,
-	   until we see a message -- if the message event id is for our join,
-	   then our ev is current and we'll process the rev after our ev, if
-	   the message event id is for the rev, then the rev is being done
-	   by the current members without us and our ev will be done later;
-	   the rev doesn't apply to us.
-
-	   Do nothing until we see a message indicating whether other nodes
-	   are on our join ev (in which case go to "rev will abort curr" code),
-	   or whether they're processing this rev (before our join ev comes
-	   up) in which case we can drop the rev (NB attend to rs, too). */
-
-	if (ev->state == EST_JOIN_STOP_WAIT && is_our_join(ev)) {
-
-		log_group(g, "rev %d is for group we're waiting to join",
-			  rev->nodeid);
-
-		/* If the failed node is the only other app member apart
-		   from us in the pending membership list, then we must go
-		   ahead with our own join event, there will be no remote nodes
-		   processing a rev or an ev for this group.  We send a recover
-		   message so other nodes waiting to join after us will purge
-		   their rev on the group. */
-
-		if (a->node_count == 2) {
-			node = find_app_node(a, rev->nodeid);
-			us = find_app_node(a, our_nodeid);
-
-			if (node && us) {
-				log_group(g, "joining group with one other node"
-					  " now dead rev %d", rev->nodeid);
-				a->node_count--;
-				list_del(&node->list);
-				free(node);
-				send_recover(g, rev);
-				del_recovery_set(g, rev, 1);
-				list_del(&rev->list);
-				free_event(rev);
-				return 0;
-			}
-		}
-
-		/* Look for a remote node with stopped of 1, if we find one,
-		   then fall through to the 'else if (event_state_stopping)'
-		   below.  A remote node with stopped of 1 means we've received
-		   a stopped message with an event_id of our join event. */
-
-		list_for_each_entry(node, &a->nodes, list) {
-			if (node->nodeid == our_nodeid)
-				continue;
-			if (node->stopped) {
-				log_group(g, "our join is current on %d",
-					  node->nodeid);
-				log_group(g, "rev %d behind our join ev %llx",
-					  rev->nodeid,
-					  (unsigned long long)ev->id);
-				goto next;
-			}
-		}
-
-		/* Look through saved messages for one with an event_id
-		   matching the rev, if we find one, then we get rid of this
-		   rev and clear this group (that we're joining) from any
-		   recovery sets that are sequencing recovery of groups the
-		   failed node was in.  The other nodes are processing the
-		   rev before processing our join ev. */
-		   
-		list_for_each_entry(save, &g->messages, list) {
-			if (save->msg.ms_type == MSG_APP_INTERNAL)
-				continue;
-			if (save->msg.ms_event_id != rev->id)
-				continue;
-
-			log_group(g, "rev %d %llx ahead of our join ev %llx",
-				  rev->nodeid,
-				  (unsigned long long)rev->id,
-				  (unsigned long long)ev->id);
-
-			node = find_app_node(a, rev->nodeid);
-			if (node) {
-				a->node_count--;
-				log_group(g, "not joined, remove %d rev %d",
-					  node->nodeid, rev->nodeid);
-				list_del(&node->list);
-				free(node);
-			}
-			list_for_each_entry(id, &rev->extended, list) {
-				node = find_app_node(a, id->nodeid);
-				if (node) {
-					a->node_count--;
-					log_group(g, "not joined, remove %d "
-						  "rev %d", id->nodeid,
-						  rev->nodeid);
-					list_del(&node->list);
-					free(node);
-				}
-			}
-
-			del_recovery_set(g, rev, 1);
-			list_del(&rev->list);
-			log_group(g, "got rid of rev %d for unjoined group",
-				  rev->nodeid);
-			free_event(rev);
-			return 0;
-		}
-
-		log_group(g, "no messages indicating remote state of group");
-		return 0;
-	}
-
- next:
-	/* Before starting the rev we need to apply the node addition/removal
-	 * of the current ev to the app.  This means processing the current ev
-	 * up through the starting stage.  So, we're sending the app the start
-	 * to inform it of the ev node change, knowing that the start won't
-	 * complete due to the node failure (pending rev), and knowing that
-	 * we'll shortly be sending it a stop and new start for the rev.
-	 *
-	 * If the current event is waiting for a "stopped" message from failed
-	 * node(s), fill in those stopped messages so we move along to the
-	 * starting state so the recovery event can then take over. */
-
-	if (event_state_starting(a) || event_state_all_started(a)) {
-		log_group(g, "rev %d replaces current ev %d %s",
-			  rev->nodeid, ev->nodeid, ev_state_str(ev));
-
-		/* what we do for our own join when reaching JOIN_ALL_STARTED */
-		if (is_our_join(ev)) {
-			purge_messages(g);
-			g->joining = 0;
-		}
-		clear_all_nodes_stopped(a);
-		list_del(&rev->list);
-		a->current_event = rev;
-		free_event(ev);
-		send_recover(g, rev);
-		rv = 1;
-	} else if (event_state_stopping(a)) {
-		/* We'll come back through here multiple times until all the
-		   stopped messages are received; we need to continue to
-		   process this event that's stopping so it will get to the
-		   starting state at which point the rev can replace it. */
-
-		log_group(g, "rev %d will abort current ev %d %s",
-			  rev->nodeid, ev->nodeid, ev_state_str(ev));
-
-		ev->start_app_before_pending_rev = 1;
-
-		mark_node_stopped(a, rev->nodeid);
-		list_for_each_entry(id, &rev->extended, list)
-			mark_node_stopped(a, id->nodeid);
-		rv = 1;
-	} else {
-		log_group(g, "rev %d delayed for ev %d %s",
-			  rev->nodeid, ev->nodeid, ev_state_str(ev));
-	}
-
-	/* FIXME: does the code above work ok if ev->nodeid == rev->noded
-	   (joining node failed) */
-
-	/* FIXME: if the current event is a leave and the leaving node has
-	   failed, then replace the current event with the rev */
-
-	return rv;
-}
-
-int process_app(group_t *g)
-{
-	app_t *a = g->app;
-	event_t *ev = NULL;
-	int rv = 0, ret;
-
-	if (a->current_event) {
-		rv += process_app_messages(g);
-
-		ret = process_current_event(g);
-		if (ret < 0)
-			goto out;
-		rv += ret;
-
-		ret = recover_current_event(g);
-		if (ret <= 0)
-			goto out;
-
-		ret = process_current_event(g);
-		if (ret < 0)
-			goto out;
-		rv += ret;
-	} else {
-
-		/* We only take on a new non-recovery event if there are
-		   no recovery sets outstanding.  The new event may be
-		   to mount gfs X where there are no living mounters of X,
-		   and the pending recovery set is to fence a node that
-		   had X mounted.  update: relax this so events are taken
-		   if there are unrecovered groups _at a lower level_. */
-
-		ev = find_queued_recover_event(g);
-		if (ev) {
-			log_group(g, "set current event to recovery for %d",
-				  ev->nodeid);
-			list_del(&ev->list);
-		} else if (!list_empty(&a->events)) {
-#if 0
-			if (!cman_quorate) {
-				log_group(g, "no new event while inquorate");
-			} else if (lower_groups_need_recovery(g)) {
-				log_group(g, "no new event while lower level "
-					  "groups need recovery");
-			} else {
-				ev = list_entry(a->events.next, event_t, list);
-				list_del(&ev->list);
-			}
-#endif
-			ev = list_entry(a->events.next, event_t, list);
-			list_del(&ev->list);
-		}
-
-		if (ev) {
-			a->need_first_event = 0;
-			a->current_event = ev;
-			rv = process_current_event(g);
-		} else if (a->need_first_event) {
-			log_group(g, "waiting for first cpg event");
-		}
-	}
- out:
-	return rv;
-}
-
-/* process_apps() will be called again immediately if it returns > 0 */
-
-int process_apps(void)
-{
-	group_t *g, *safe;
-	int rv = 0;
-
-	if (group_mode != GROUP_LIBGROUP)
-		return 0;
-
-	list_for_each_entry_safe(g, safe, &gd_groups, list) {
-		rv += process_app(g);
-		deliver_app_messages(g);
-	}
-
-	return rv;
-}
-
-/* This is a bit of a hack that may not be entirely necessary.  The problem
-   we're solving with this function is when a node leaves a group and is
-   collecting all the "stopped" messages from the remaining members, some
-   of those members may fail, so we wouldn't get a stopped message from
-   them and never finalize_our_leave (terminate the group).  I'm not entirely
-   sure that we _need_ to wait for stopped messages from remaining members
-   before we do the finalize_our_leave/terminate... The reasoning at this
-   point is that when gfs is withdrawing, we want to be sure gfs is
-   suspended everywhere before we leave the lockspace (which happens at
-   terminate for the withdraw/leave) */
-
-void groupd_down(int nodeid)
-{
-	group_t *g;
-
-	list_for_each_entry(g, &gd_groups, list) {
-		if (g->app &&
-		    g->app->current_event &&
-		    g->app->current_event->state == EST_LEAVE_STOP_WAIT &&
-		    is_our_leave(g->app->current_event)) {
-			log_group(g, "groupd down on %d, push our leave",
-				  nodeid);
-			mark_node_stopped(g->app, nodeid);
-		}
-	}
-}
-
diff --git a/group/daemon/cman.c b/group/daemon/cman.c
deleted file mode 100644
index 0c0bbfa..0000000
--- a/group/daemon/cman.c
+++ /dev/null
@@ -1,206 +0,0 @@
-
-/* Interface with corosync's cman API */
-
-#include <libcman.h>
-#include "gd_internal.h"
-
-static cman_handle_t	ch;
-static cman_handle_t	ch_admin;
-static int		old_quorate;
-static cman_node_t	old_nodes[MAX_NODES];
-static int		old_node_count;
-static cman_node_t	cman_nodes[MAX_NODES];
-static int		cman_node_count;
-static char		name_buf[CMAN_MAX_NODENAME_LEN+1];
-
-
-int kill_cman(int nodeid)
-{
-	return cman_kill_node(ch_admin, nodeid);
-}
-
-static int is_member(cman_node_t *node_list, int count, int nodeid)
-{
-	int i;
-
-	for (i = 0; i < count; i++) {
-		if (node_list[i].cn_nodeid == nodeid)
-			return node_list[i].cn_member;
-	}
-	return 0;
-}
-
-static int is_old_member(int nodeid)
-{
-	return is_member(old_nodes, old_node_count, nodeid);
-}
-
-static int is_cman_member(int nodeid)
-{
-	return is_member(cman_nodes, cman_node_count, nodeid);
-}
-
-static void statechange(void)
-{
-	int i, rv;
-
-	old_quorate = cman_quorate;
-	old_node_count = cman_node_count;
-	memcpy(&old_nodes, &cman_nodes, sizeof(old_nodes));
-
-	cman_quorate = cman_is_quorate(ch);
-
-	cman_node_count = 0;
-	memset(&cman_nodes, 0, sizeof(cman_nodes));
-	rv = cman_get_nodes(ch, MAX_NODES, &cman_node_count, cman_nodes);
-	if (rv < 0) {
-		log_print("cman_get_nodes error %d %d", rv, errno);
-		return;
-	}
-
-	/*
-	printf("cman: %d old nodes:\n", old_node_count);
-	for (i = 0; i < old_node_count; i++)
-		printf("%d:%d ", old_nodes[i].cn_nodeid,
-				 old_nodes[i].cn_member);
-	printf("\n");
-
-	printf("cman: %d new nodes:\n", cman_node_count);
-	for (i = 0; i < cman_node_count; i++)
-		printf("%d:%d ", cman_nodes[i].cn_nodeid,
-				 cman_nodes[i].cn_member);
-	printf("\n");
-	*/
-
-	if (old_quorate && !cman_quorate)
-		log_debug("cman: lost quorum");
-	if (!old_quorate && cman_quorate)
-		log_debug("cman: have quorum");
-
-	for (i = 0; i < old_node_count; i++) {
-		if (old_nodes[i].cn_member &&
-		    !is_cman_member(old_nodes[i].cn_nodeid)) {
-
-			log_debug("cman: node %d removed",
-				  old_nodes[i].cn_nodeid);
-			add_recovery_set_cman(old_nodes[i].cn_nodeid);
-		}
-	}
-
-	for (i = 0; i < cman_node_count; i++) {
-		if (cman_nodes[i].cn_member &&
-		    !is_old_member(cman_nodes[i].cn_nodeid))
-			log_debug("cman: node %d added",
-				  cman_nodes[i].cn_nodeid);
-	}
-}
-
-static void cman_callback(cman_handle_t h, void *private, int reason, int arg)
-{
-	switch (reason) {
-	case CMAN_REASON_TRY_SHUTDOWN:
-		cman_replyto_shutdown(ch, 1);
-		break;
-	case CMAN_REASON_STATECHANGE:
-		statechange();
-		break;
-	case CMAN_REASON_CONFIG_UPDATE:
-		setup_logging();
-		break;
-	}
-}
-
-void process_cman(int ci)
-{
-	int rv;
-
-	rv = cman_dispatch(ch, CMAN_DISPATCH_ALL);
-	if (rv == -1 && errno == EHOSTDOWN)
-		cluster_dead(0);
-}
-
-int setup_cman(void)
-{
-	cman_node_t node;
-	int rv, fd;
-	int init = 0, active = 0;
-
- retry_init:
-	ch = cman_init(NULL);
-	if (!ch) {
-		if (init++ < 2) {
-			sleep(1);
-			goto retry_init;
-		}
-		log_print("cman_init error %d", errno);
-		return -ENOTCONN;
-	}
-
- retry_active:
-	rv = cman_is_active(ch);
-	if (!rv) {
-		if (active++ < 2) {
-			sleep(1);
-			goto retry_active;
-		}
-		log_print("cman_is_active error %d", errno);
-		cman_finish(ch);
-		return -ENOTCONN;
-	}
-
-	ch_admin = cman_admin_init(NULL);
-	if (!ch_admin) {
-		log_print("cman_admin_init error %d", errno);
-		cman_finish(ch);
-		return -ENOTCONN;
-	}
-
-	rv = cman_start_notification(ch, cman_callback);
-	if (rv < 0) {
-		log_print("cman_start_notification error %d %d", rv, errno);
-		cman_finish(ch);
-		cman_finish(ch_admin);
-		return rv;
-	}
-
-	memset(&node, 0, sizeof(node));
-	rv = cman_get_node(ch, CMAN_NODEID_US, &node);
-	if (rv < 0) {
-		log_print("cman_get_node us error %d %d", rv, errno);
-		cman_stop_notification(ch);
-		cman_finish(ch);
-		cman_finish(ch_admin);
-		return rv;
-	}
-
-	cman_node_count = 0;
-	memset(&cman_nodes, 0, sizeof(cman_nodes));
-	rv = cman_get_nodes(ch, MAX_NODES, &cman_node_count, cman_nodes);
-	if (rv < 0) {
-		log_print("cman_get_nodes error %d %d", rv, errno);
-		cman_stop_notification(ch);
-		cman_finish(ch);
-		cman_finish(ch_admin);
-		return rv;
-	}
-
-	cman_quorate = cman_is_quorate(ch);
-
-	memset(name_buf, 0, sizeof(name_buf));
-	strncpy(name_buf, node.cn_name, CMAN_MAX_NODENAME_LEN);
-	our_name = name_buf;
-	our_nodeid = node.cn_nodeid;
-	log_debug("cman: our nodeid %d name %s quorum %d",
-		  our_nodeid, our_name, cman_quorate);
-
-	fd = cman_get_fd(ch);
-
-	return fd;
-}
-
-void close_cman(void)
-{
-	cman_finish(ch);
-	cman_finish(ch_admin);
-}
-
diff --git a/group/daemon/cpg.c b/group/daemon/cpg.c
deleted file mode 100644
index 6195d49..0000000
--- a/group/daemon/cpg.c
+++ /dev/null
@@ -1,1072 +0,0 @@
-
-/* Interface with corosync's closed-process-group (cpg) API */
-
-#include "gd_internal.h"
-
-static cpg_handle_t groupd_handle;
-static struct cpg_name groupd_name;
-static int global_id_counter = 0;
-static int groupd_joined = 0;
-static int groupd_ci;
-
-static int			got_confchg;
-static struct cpg_address	groupd_cpg_member[MAX_GROUP_MEMBERS];
-static int			groupd_cpg_member_count;
-static struct cpg_address	saved_member[MAX_GROUP_MEMBERS];
-static struct cpg_address	saved_joined[MAX_GROUP_MEMBERS];
-static struct cpg_address	saved_left[MAX_GROUP_MEMBERS];
-static int			saved_member_count;
-static int			saved_joined_count;
-static int			saved_left_count;
-static cpg_handle_t		saved_handle;
-static struct cpg_name		saved_name;
-static int			message_flow_control_on;
-static struct list_head		group_nodes;
-static uint64_t			send_version_first;
-
-#define CLUSTER2		2
-#define CLUSTER3		3
-
-struct group_version {
-	uint32_t nodeid;
-	uint16_t cluster;
-	uint16_t group_mode;
-	uint16_t groupd_compat;
-	uint16_t groupd_count;
-	uint32_t unused;
-};
-
-struct group_node {
-	uint32_t nodeid;
-	uint32_t got_from;
-	int got_version;
-	uint64_t add_time;
-	struct group_version ver;
-	struct list_head list;
-};
-
-static void block_old_nodes(void);
-
-static char *mode_str(int m)
-{
-	switch (m) {
-	case GROUP_PENDING:
-		return "PENDING";
-	case GROUP_LIBGROUP:
-		return "LIBGROUP";
-	case GROUP_LIBCPG:
-		return "LIBCPG";
-	default:
-		return "UNKNOWN";
-	}
-}
-
-static struct group_node *get_group_node(int nodeid)
-{
-	struct group_node *node;
-
-	list_for_each_entry(node, &group_nodes, list) {
-		if (node->nodeid == nodeid)
-			return node;
-	}
-	return NULL;
-}
-
-static void group_node_add(int nodeid)
-{
-	struct group_node *node;
-
-	node = get_group_node(nodeid);
-	if (node)
-		return;
-
-	node = malloc(sizeof(struct group_node));
-	if (!node)
-		return;
-	memset(node, 0, sizeof(struct group_node));
-
-	node->nodeid = nodeid;
-	node->add_time = time(NULL);
-	list_add_tail(&node->list, &group_nodes);
-}
-
-static void group_node_del(int nodeid)
-{
-	struct group_node *node;
-
-	node = get_group_node(nodeid);
-	if (!node) {
-		log_print("group_node_del %d no node", nodeid);
-		return;
-	}
-
-	list_del(&node->list);
-	free(node);
-}
-
-static void version_copy_in(struct group_version *ver)
-{
-	ver->nodeid        = le32_to_cpu(ver->nodeid);
-	ver->cluster       = le16_to_cpu(ver->cluster);
-	ver->group_mode    = le16_to_cpu(ver->group_mode);
-	ver->groupd_compat = le16_to_cpu(ver->groupd_compat);
-	ver->groupd_count  = le16_to_cpu(ver->groupd_count);
-}
-
-static void _send_version(int nodeid, int cluster, int mode, int compat)
-{
-	group_t g, *gp;
-	char *buf;
-	msg_t *msg;
-	int len;
-	int count = 0;
-	struct group_version *ver;
-
-	list_for_each_entry(gp, &gd_groups, list)
-		count++;
-
-	/* just so log_group will work */
-	memset(&g, 0, sizeof(group_t));
-	strcpy(g.name, "groupd");
-
-	len = sizeof(msg_t) + sizeof(struct group_version);
-
-	buf = malloc(len);
-	if (!buf)
-		return;
-	memset(buf, 0, len);
-
-	msg = (msg_t *)buf;
-	ver = (struct group_version *)(buf + sizeof(msg_t));
-
-	msg->ms_type = MSG_GROUP_VERSION;
-	msg_bswap_out(msg);
-
-	log_debug("send_version nodeid %d cluster %d mode %s compat %d",
-		  nodeid, cluster, mode_str(mode), compat);
-
-	ver->nodeid        = cpu_to_le32(nodeid);
-	ver->cluster       = cpu_to_le16(cluster);
-	ver->group_mode    = cpu_to_le16(mode);
-	ver->groupd_compat = cpu_to_le16(compat);
-	ver->groupd_count  = cpu_to_le16(count);
-
-	send_message_groupd(&g, buf, len, MSG_GROUP_VERSION);
-}
-
-static void send_version(void)
-{
-	_send_version(our_nodeid, CLUSTER3, group_mode, cfgd_groupd_compat);
-}
-
-static void set_group_mode(void)
-{
-	struct group_node *node;
-	int need_version, pending_count;
-
-	need_version = 0;
-	pending_count = 0;
-
-	list_for_each_entry(node, &group_nodes, list) {
-		if (!node->got_version) {
-			need_version++;
-			continue;
-		}
-		if (node->ver.group_mode == GROUP_PENDING) {
-			pending_count++;
-			continue;
-		}
-
-		/* If we receive any non-pending group mode, adopt it
-		   immediately. */
-
-		group_mode = node->ver.group_mode;
-
-		switch (group_mode) {
-		case GROUP_PENDING:
-			/* shouldn't happen */
-			log_level(LOG_INFO, "groupd compatibility mode 2 ver");
-			break;
-		case GROUP_LIBGROUP:
-			log_level(LOG_INFO, "groupd compatibility mode 1 ver");
-			break;
-		case GROUP_LIBCPG:
-			log_level(LOG_INFO, "groupd compatibility mode 0 ver");
-			break;
-		default:
-			log_level(LOG_INFO, "groupd compatibility mode %d ver",
-				  group_mode);
-			break;
-		}
-
-		log_debug("set_group_mode %s matching nodeid %d got_from %d",
-			  mode_str(group_mode), node->nodeid, node->got_from);
-		break;
-	}
-
-	if (group_mode == GROUP_LIBCPG)
-		block_old_nodes();
-}
-
-static void receive_version(int from, msg_t *msg, int len)
-{
-	struct group_node *node;
-	struct group_version *ver;
-
-	if (group_mode != GROUP_PENDING)
-		return;
-
-	ver = (struct group_version *)((char *)msg + sizeof(msg_t));
-
-	version_copy_in(ver);
-
-	node = get_group_node(ver->nodeid);
-	if (!node) {
-		log_print("receive_version from %d nodeid %d not found",
-			  from, ver->nodeid);
-		return;
-	}
-
-	/* ignore a repeat of what we've seen before */
-
-	if (node->got_version && from == node->got_from &&
-	    node->ver.group_mode == ver->group_mode)
-		return;
-
-	log_debug("receive_version from %d nodeid %d cluster %d mode %s "
-		  "compat %d", from, ver->nodeid, ver->cluster,
-		  mode_str(ver->group_mode), ver->groupd_compat);
-
-	node->got_version = 1;
-	node->got_from = from;
-	memcpy(&node->ver, ver, sizeof(struct group_version));
-
-	set_group_mode();
-}
-
-void group_mode_check_timeout(void)
-{
-	struct group_node *node;
-	int need_version, pending_count;
-	uint64_t now;
-
-	if (group_mode != GROUP_PENDING)
-		return;
-
-	if (!send_version_first)
-		return;
-
-	/* Wait for cfgd_groupd_wait seconds to receive a version message from
-	   an added node, after which we'll send a version message for it,
-	   calling it a cluster2 node; receiving this will cause everyone to
-	   immediately set mode to LIBGROUP. */
-
-	need_version = 0;
-	pending_count = 0;
-	now = time(NULL);
-
-	list_for_each_entry(node, &group_nodes, list) {
-		if (node->got_version) {
-			pending_count++;
-			continue;
-		}
-		need_version++;
-
-		if (now - node->add_time >= cfgd_groupd_wait) {
-			log_print("send version for nodeid %d times %llu %llu",
-				  node->nodeid,
-				  (unsigned long long)node->add_time,
-				  (unsigned long long)now);
-			_send_version(node->nodeid, CLUSTER2, GROUP_LIBGROUP,1);
-		}
-	}
-
-	if (need_version) {
-		log_debug("group_mode_check_timeout need %d pending %d",
-			  need_version, pending_count);
-		return;
-	}
-
-	/* we have a version from everyone, and they all are pending;
-	   wait for cfgd_groupd_mode_delay to give any old cluster2 nodes
-	   a chance to join and cause us to use LIBGROUP */
-
-	if (now - send_version_first < cfgd_groupd_mode_delay) {
-		log_debug("group_mode_check_timeout delay times %llu %llu",
-			  (unsigned long long)send_version_first,
-			  (unsigned long long)now);
-		return;
-	}
-
-	/* everyone is cluster3/pending so we can use LIBCPG; receiving
-	   this will cause everyone to immediately set mode to LIBCPG */
-
-	log_debug("send version LIBCPG all %d pending", pending_count);
-
-	_send_version(our_nodeid, CLUSTER3, GROUP_LIBCPG, cfgd_groupd_compat);
-}
-
-static node_t *find_group_node(group_t *g, int nodeid)
-{
-	node_t *node;
-
-	list_for_each_entry(node, &g->memb, list) {
-		if (node->nodeid == nodeid)
-			return node;
-	}
-	return NULL;
-}
-
-static void process_node_down(group_t *g, int nodeid)
-{
-	node_t *node;
-	event_t *ev, *ev_safe;
-	int no_rev = 0;
-
-	node = find_group_node(g, nodeid);
-	if (!node)
-		return;
-
-	log_group(g, "process_node_down %d", nodeid);
-
-	list_del(&node->list);
-	g->memb_count--;
-	free(node);
-
-	log_group(g, "cpg del node %d total %d - down",
-		  nodeid, g->memb_count);
-
-	/* purge any queued join/leave events from the dead node */
-
-	list_for_each_entry_safe(ev, ev_safe, &g->app->events, list) {
-		if (ev->nodeid != nodeid)
-			continue;
-
-		if (ev->state == EST_JOIN_BEGIN ||
-		    ev->state == EST_LEAVE_BEGIN) {
-			if (ev->state == EST_JOIN_BEGIN)
-				no_rev = 1;
-
-			log_group(g, "purge event %s from %d", ev_state_str(ev),
-			  	  nodeid);
-			del_event_nodes(ev);
-			list_del(&ev->list);
-			free(ev);
-		}
-	}
-
-	/* the failed node was never added to the app, so the app
-	   doesn't need to be recovered for it */
-	if (no_rev)
-		return;
-
-	ev = find_queued_recover_event(g);
-	if (ev)
-		extend_recover_event(g, ev, nodeid);
-	else
-		queue_app_recover(g, nodeid);
-}
-
-static void process_node_join(group_t *g, int nodeid)
-{
-	node_t *node;
-	int i;
-
-	log_group(g, "process_node_join %d", nodeid);
-
-	if (nodeid == our_nodeid) {
-		for (i = 0; i < saved_member_count; i++) {
-			node = new_node(saved_member[i].nodeid);
-			list_add_tail(&node->list, &g->memb);
-			g->memb_count++;
-			log_group(g, "cpg add node %d total %d",
-				  node->nodeid, g->memb_count);
-		}
-
-		/* if we're the first one to join (create) the group,
-		   then set its global_id */
-
-		if (saved_member_count == 1) {
-			g->global_id = (++global_id_counter << 16) |
-				       (0x0000FFFF & our_nodeid);
-			log_group(g, "create group id %x our_nodeid %d",
-				  g->global_id, our_nodeid);
-		}
-	} else {
-		node = new_node(nodeid);
-		list_add_tail(&node->list, &g->memb);
-		g->memb_count++;
-		log_group(g, "cpg add node %d total %d",
-			  node->nodeid, g->memb_count);
-	}
-
-	queue_app_join(g, nodeid);
-
-	/* if this is for our own join, then make it current immediately;
-	   other code gets confused if we're not joined and have no current
-	   event */
-	if (nodeid == our_nodeid)
-		process_app(g);
-}
-
-static void process_node_leave(group_t *g, int nodeid)
-{
-	node_t *node;
-
-	log_group(g, "process_node_leave %d", nodeid);
-
-	node = find_group_node(g, nodeid);
-	if (!node) {
-		log_error(g, "process_node_leave: no member %d", nodeid);
-		return;
-	}
-
-	list_del(&node->list);
-	g->memb_count--;
-	free(node);
-
-	log_group(g, "cpg del node %d total %d", nodeid, g->memb_count);
-
-	queue_app_leave(g, nodeid);
-}
-
-static uint32_t max_global_id(uint32_t add_nodeid)
-{
-	group_t *g;
-	uint32_t nodeid, counter, max_counter = 0, max_gid = 0;
-
-	list_for_each_entry(g, &gd_groups, list) {
-		nodeid = g->global_id & 0x0000FFFF;
-		counter = (g->global_id >> 16) & 0x0000FFFF;
-		if (nodeid != add_nodeid)
-			continue;
-		if (!max_counter || counter > max_counter) {
-			max_counter = counter;
-			max_gid = g->global_id;
-		}
-	}
-	return max_gid;
-}
-
-static int send_gid(uint32_t gid)
-{
-	group_t g;
-	msg_t msg;
-
-	/* just so log_group will work */
-	memset(&g, 0, sizeof(group_t));
-	strcpy(g.name, "groupd");
-
-	memset(&msg, 0, sizeof(msg));
-	msg.ms_type = MSG_GLOBAL_ID;
-	msg.ms_global_id = gid;
-
-	msg_bswap_out(&msg);
-
-	return send_message_groupd(&g, &msg, sizeof(msg), MSG_GLOBAL_ID);
-}
-
-void process_groupd_confchg(void)
-{
-	group_t *g;
-	struct recovery_set *rs;
-	int i, found = 0;
-	uint32_t gid;
-
-	log_debug("groupd confchg total %d left %d joined %d",
-		  saved_member_count, saved_left_count, saved_joined_count);
-
-	if (!send_version_first) {
-		for (i = 0; i < saved_member_count; i++) {
-			group_node_add(saved_member[i].nodeid);
-			log_debug("groupd init %d", saved_member[i].nodeid);
-		}
-
-		send_version_first = time(NULL);
-	} else {
-		for (i = 0; i < saved_left_count; i++) {
-			group_node_del(saved_left[i].nodeid);
-			log_debug("groupd del %d", saved_left[i].nodeid);
-		}
-		for (i = 0; i < saved_joined_count; i++) {
-			group_node_add(saved_joined[i].nodeid);
-			log_debug("groupd add %d", saved_joined[i].nodeid);
-		}
-	}
-
-	if (saved_joined_count)
-		send_version();
-
-	memcpy(&groupd_cpg_member, &saved_member, sizeof(saved_member));
-	groupd_cpg_member_count = saved_member_count;
-
-	if (group_mode != GROUP_LIBGROUP)
-		return;
-
-	for (i = 0; i < saved_member_count; i++) {
-		if (saved_member[i].nodeid == our_nodeid &&
-		    saved_member[i].pid == (uint32_t) getpid()) {
-			found = 1;
-		}
-	}
-
-	if (!groupd_joined)
-		goto next;
-
-	/* find any groups that were created in the past by a new node
-	   and send it the id it used so it can initialize global_id_counter
-	   to avoid creating a new group with a duplicate id */
-
-	for (i = 0; i < saved_joined_count; i++) {
-		gid = max_global_id(saved_joined[i].nodeid);
-		if (!gid)
-			continue;
-		log_debug("joined node %d had old max gid %x",
-			  saved_joined[i].nodeid, gid);
-		send_gid(gid);
-	}
-
- next:
-	if (found)
-		groupd_joined = 1;
-	else
-		log_print("we are not in groupd confchg: %u %u",
-			  our_nodeid, (uint32_t) getpid());
-
-	for (i = 0; i < saved_left_count; i++) {
-		if (saved_left[i].reason == CPG_REASON_LEAVE)
-			continue;
-
-		if (saved_left[i].reason == CPG_REASON_NODEDOWN) {
-			/* a nice clean failure */
-			add_recovery_set_cpg(saved_left[i].nodeid, 0);
-		} else if (saved_left[i].reason == CPG_REASON_PROCDOWN) {
-			/* groupd failed, but the node is still up; if
-			   the node was in any groups (non-NULL rs is
-			   returned), then kill the node so it'll be a
-			   real nodedown */
-			rs = add_recovery_set_cpg(saved_left[i].nodeid, 1);
-			if (rs) {
-				log_print("kill node %d - groupd PROCDOWN",
-					  saved_left[i].nodeid);
-				kill_cman(saved_left[i].nodeid);
-			}
-		}
-		groupd_down(saved_left[i].nodeid);
-	}
-
-	/* we call process_node_down from here, instead of from the other cpg
-	   confchg's because we want everyone to see the same order of
-	   confchg's with respect to messages.  see bz 258121 */
-
-	for (i = 0; i < saved_left_count; i++) {
-		if (saved_left[i].reason == CPG_REASON_NODEDOWN ||
-		    saved_left[i].reason == CPG_REASON_PROCDOWN) {
-			list_for_each_entry(g, &gd_groups, list)
-				process_node_down(g, saved_left[i].nodeid);
-		}
-	}
-}
-
-void copy_groupd_data(group_data_t *data)
-{
-	int i;
-
-	data->level = -1;
-	data->member_count = groupd_cpg_member_count;
-	for (i = 0; i < groupd_cpg_member_count; i++)
-		data->members[i] = groupd_cpg_member[i].nodeid;
-}
-
-int in_groupd_cpg(int nodeid)
-{
-	int i;
-	for (i = 0; i < groupd_cpg_member_count; i++) {
-		if (nodeid == groupd_cpg_member[i].nodeid)
-			return 1;
-	}
-	return 0;
-}
-
-group_t *find_group_by_handle(cpg_handle_t h)
-{
-	group_t *g;
-
-	list_for_each_entry(g, &gd_groups, list) {
-		if (g->cpg_handle == h)
-			return g;
-	}
-	return NULL;
-}
-
-void deliver_cb(cpg_handle_t handle, struct cpg_name *group_name,
-		uint32_t nodeid, uint32_t pid, void *data, int data_len)
-{
-	group_t *g;
-	struct save_msg *save;
-	msg_t *msg = (msg_t *) data;
-	char *buf;
-	char name[MAX_NAMELEN+1];
-	uint32_t to_nodeid, counter;
-	int len;
-
-	memset(&name, 0, sizeof(name));
-
-	msg_bswap_in(msg);
-
-	if (msg->ms_type == MSG_GROUP_VERSION) {
-		receive_version(nodeid, msg, data_len);
-		return;
-	}
-
-	if (msg->ms_type == MSG_GLOBAL_ID) {
-		to_nodeid = msg->ms_global_id & 0x0000FFFF;
-		counter = (msg->ms_global_id >> 16) & 0x0000FFFF;
-
-		if (to_nodeid == our_nodeid) {
-			log_debug("recv global_id %x from %u cur counter %u",
-			  	  msg->ms_global_id, nodeid, global_id_counter);
-			if (counter > global_id_counter)
-				global_id_counter = counter;
-		}
-		return;
-	}
-
-	if (handle == groupd_handle) {
-		memcpy(&name, &msg->ms_name, MAX_NAMELEN);
-
-		g = find_group_level(name, msg->ms_level);
-		if (!g) {
-			if (daemon_debug_verbose > 1) {
-				log_print("%d:%s RECV len %d %s from %d, "
-					  "no group",
-				  	  msg->ms_level, name, data_len,
-				  	  msg_type(msg->ms_type), nodeid);
-			}
-			return;
-		}
-	} else {
-		if (group_mode != GROUP_LIBGROUP)
-			return;
-
-		g = find_group_by_handle(handle);
-		if (!g) {
-			len = group_name->length;
-			if (len > MAX_NAMELEN)
-				len = MAX_NAMELEN;
-			memcpy(&name, &group_name->value, len);
-
-			log_print("deliver_cb no group handle %llx name %s",
-				  (unsigned long long)handle, name);
-			return;
-		}
-	}
-
-	if (daemon_debug_verbose > 1)
-		log_group(g, "RECV len %d %s from %d", data_len,
-			  msg_type(msg->ms_type), nodeid);
-
-	save = malloc(sizeof(struct save_msg));
-	// FIXME: handle failed malloc
-	memset(save, 0, sizeof(struct save_msg));
-	save->nodeid = nodeid;
-	save->msg_len = data_len;
-
-	if (data_len > sizeof(msg_t)) {
-		buf = malloc(data_len);
-		// FIXME: handle failed malloc
-		memcpy(buf, data, data_len);
-		save->msg_long = buf;
-		memcpy(&save->msg, data, sizeof(msg_t));
-	} else
-		memcpy(&save->msg, data, sizeof(msg_t));
-
-	queue_app_message(g, save);
-}
-
-void process_confchg(void)
-{
-	group_t *g;
-	int i;
-
-	if (saved_handle == groupd_handle) {
-		process_groupd_confchg();
-		return;
-	}
-
-	if (group_mode != GROUP_LIBGROUP)
-		return;
-
-	g = find_group_by_handle(saved_handle);
-	if (!g) {
-		log_debug("confchg: no group for handle %llx name %s",
-			  (unsigned long long)saved_handle,
-			  saved_name.value);
-		return;
-	}
-
-	log_group(g, "confchg left %d joined %d total %d",
-		  saved_left_count, saved_joined_count, saved_member_count);
-
-	for (i = 0; i < saved_joined_count; i++)
-		process_node_join(g, saved_joined[i].nodeid);
-
-	for (i = 0; i < saved_left_count; i++) {
-		log_group(g, "confchg removed node %d reason %d",
-			  saved_left[i].nodeid, saved_left[i].reason);
-
-		switch (saved_left[i].reason) {
-		case CPG_REASON_LEAVE:
-			process_node_leave(g, saved_left[i].nodeid);
-			break;
-		case CPG_REASON_NODEDOWN:
-		case CPG_REASON_PROCDOWN:
-			/* process_node_down(g, saved_left[i].nodeid); */
-			purge_node_messages(g, saved_left[i].nodeid);
-			break;
-		default:
-			log_error(g, "unknown leave reason %d node %d",
-				  saved_left[i].reason,
-				  saved_joined[i].nodeid);
-		}
-	}
-}
-
-void confchg_cb(cpg_handle_t handle, struct cpg_name *group_name,
-		struct cpg_address *member_list, int member_list_entries,
-		struct cpg_address *left_list, int left_list_entries,
-		struct cpg_address *joined_list, int joined_list_entries)
-{
-	group_t *g;
-	char *name = "unknown";
-	int i, level = -1;
-
-	if (handle == groupd_handle)
-		name = "groupd";
-	else {
-		g = find_group_by_handle(handle);
-		if (g) {
-			name = g->name;
-			level = g->level;
-		}
-	}
-
-	/*
-	log_debug("%d:%s confchg_cb total %d left %d joined %d", level, name,
-		  member_list_entries, left_list_entries, joined_list_entries);
-	*/
-
-	saved_handle = handle;
-
-	if (left_list_entries > MAX_GROUP_MEMBERS) {
-		log_debug("left_list_entries %d", left_list_entries);
-		left_list_entries = MAX_GROUP_MEMBERS;
-	}
-	if (joined_list_entries > MAX_GROUP_MEMBERS) {
-		log_debug("joined_list_entries %d", joined_list_entries);
-		joined_list_entries = MAX_GROUP_MEMBERS;
-	}
-	if (member_list_entries > MAX_GROUP_MEMBERS) {
-		log_debug("member_list_entries %d", joined_list_entries);
-		member_list_entries = MAX_GROUP_MEMBERS;
-	}
-
-	saved_left_count = left_list_entries;
-	saved_joined_count = joined_list_entries;
-	saved_member_count = member_list_entries;
-
-	memset(&saved_name, 0, sizeof(saved_name));
-	saved_name.length = group_name->length;
-	memcpy(&saved_name.value, &group_name->value, group_name->length);
-
-	for (i = 0; i < left_list_entries; i++)
-		saved_left[i] = left_list[i];
-
-	for (i = 0; i < joined_list_entries; i++)
-		saved_joined[i] = joined_list[i];
-
-	for (i = 0; i < member_list_entries; i++)
-		saved_member[i] = member_list[i];
-
-	got_confchg = 1;
-}
-
-cpg_callbacks_t callbacks = {
-	.cpg_deliver_fn = deliver_cb,
-	.cpg_confchg_fn = confchg_cb,
-};
-
-void process_cpg(int ci)
-{
-	group_t *g = NULL;
-	cpg_error_t error;
-	cpg_handle_t handle;
-	int found = 0;
-	cpg_flow_control_state_t flow_control_state;
-
-	if (ci == groupd_ci) {
-		handle = groupd_handle;
-		goto dispatch;
-	}
-
-	list_for_each_entry(g, &gd_groups, list) {
-		if (g->cpg_client == ci) {
-			handle = g->cpg_handle;
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
-		log_print("process_cpg: no group found for ci %d", ci);
-		sleep(1);
-		return;
-	}
-
- dispatch:
-	got_confchg = 0;
-
-	error = cpg_dispatch(handle, CPG_DISPATCH_ONE);
-	if (error != CPG_OK) {
-		log_print("cpg_dispatch error %d", error);
-		return;
-	}
-
-	error = cpg_flow_control_state_get(handle, &flow_control_state);
-	if (error != CPG_OK)
-		log_error(g, "cpg_flow_control_state_get %d", error);
-	else if (flow_control_state == CPG_FLOW_CONTROL_ENABLED) {
-		message_flow_control_on = 1;
-		log_debug("flow control on");
-	} else {
-		if (message_flow_control_on)
-			log_debug("flow control off");
-		message_flow_control_on = 0;
-	}
-
-	if (got_confchg)
-		process_confchg();
-}
-
-int setup_cpg(void)
-{
-	cpg_error_t error;
-	int fd;
-
-	INIT_LIST_HEAD(&group_nodes);
-
-	error = cpg_initialize(&groupd_handle, &callbacks);
-	if (error != CPG_OK) {
-		log_print("cpg_initialize error %d", error);
-		return error;
-	}
-
-	cpg_fd_get(groupd_handle, &fd);
-
-	groupd_ci = client_add(fd, process_cpg, NULL);
-
-	memset(&groupd_name, 0, sizeof(groupd_name));
-	strcpy(groupd_name.value, "groupd");
-	groupd_name.length = 7;
-
- retry:
-	error = cpg_join(groupd_handle, &groupd_name);
-	if (error == CPG_ERR_TRY_AGAIN) {
-		log_debug("setup_cpg cpg_join retry");
-		sleep(1);
-		goto retry;
-	}
-	if (error != CPG_OK) {
-		log_print("cpg_join error %d", error);
-		cpg_finalize(groupd_handle);
-		return error;
-	}
-
-	log_debug("setup_cpg groupd_handle %llx",
-		  (unsigned long long)groupd_handle);
-
-	return 0;
-}
-
-int do_cpg_join(group_t *g)
-{
-	cpg_error_t error;
-	cpg_handle_t h;
-	struct cpg_name name;
-	int fd, ci, i = 0;
-
-	error = cpg_initialize(&h, &callbacks);
-	if (error != CPG_OK) {
-		log_group(g, "cpg_initialize error %d", error);
-		return error;
-	}
-
-	cpg_fd_get(h, &fd);
-
-	ci = client_add(fd, process_cpg, NULL);
-
-	g->cpg_client = ci;
-	g->cpg_handle = h;
-	g->cpg_fd = fd;
-
-	memset(&name, 0, sizeof(name));
-	sprintf(name.value, "%d_%s", g->level, g->name);
-	name.length = strlen(name.value) + 1;
-
-	log_group(g, "is cpg client %d name %s handle %llx", ci, name.value,
-		  (unsigned long long)h);
-
- retry:
-	error = cpg_join(h, &name);
-	if (error == CPG_ERR_TRY_AGAIN) {
-		log_debug("cpg_join error retry");
-		sleep(1);
-		if (!(++i % 10))
-			log_error(g, "cpg_join error retrying");
-		goto retry;
-	}
-	if (error != CPG_OK) {
-		log_group(g, "cpg_join error %d", error);
-		cpg_finalize(h);
-		return error;
-	}
-
-	log_group(g, "cpg_join ok");
-	return 0;
-}
-
-int do_cpg_leave(group_t *g)
-{
-	cpg_error_t error;
-	struct cpg_name name;
-	int i = 0;
-
-	memset(&name, 0, sizeof(name));
-	sprintf(name.value, "%d_%s", g->level, g->name);
-	name.length = strlen(name.value) + 1;
-
- retry:
-	error = cpg_leave(g->cpg_handle, &name);
-	if (error == CPG_ERR_TRY_AGAIN) {
-		log_debug("cpg_leave error retry");
-		sleep(1);
-		if (!(++i % 10))
-			log_error(g, "cpg_leave error retrying");
-		goto retry;
-	}
-	if (error != CPG_OK) {
-		log_group(g, "cpg_leave error %d", error);
-		return error;
-	}
-
-	log_group(g, "cpg_leave ok");
-	return 0;
-}
-
-static int _send_message(cpg_handle_t h, group_t *g, void *buf, int len)
-{
-	struct iovec iov;
-	cpg_error_t error;
-	int retries = 0;
-
-	iov.iov_base = buf;
-	iov.iov_len = len;
-
- retry:
-	error = cpg_mcast_joined(h, CPG_TYPE_AGREED, &iov, 1);
-	if (error == CPG_ERR_TRY_AGAIN) {
-		retries++;
-		usleep(1000);
-		if (!(retries % 100))
-			log_error(g, "cpg_mcast_joined retry %d", retries);
-		goto retry;
-	} else if (error != CPG_OK)
-		log_error(g, "cpg_mcast_joined error %d handle %llx", error,
-			  (unsigned long long)h);
-
-	if (retries)
-		log_group(g, "cpg_mcast_joined retried %d", retries);
-
-	return 0;
-}
-
-int send_message_groupd(group_t *g, void *buf, int len, int type)
-{
-	if (daemon_debug_verbose > 1)
-		log_group(g, "SEND len %d %s", len, msg_type(type));
-
-	return _send_message(groupd_handle, g, buf, len);
-}
-
-int send_message(group_t *g, void *buf, int len)
-{
-	return _send_message(g->cpg_handle, g, buf, len);
-}
-
-static void block_old_group(char *name, int level)
-{
-	group_t *g;
-	app_t *a;
-	cpg_error_t error;
-	cpg_handle_t h;
-	struct cpg_name cpgname;
-	int rv, fd, ci, i = 0;
-
-	rv = create_group(name, level, &g);
-	if (rv)
-		return;
-	a = create_app(g);
-	if (!a)
-		return;
-
-	error = cpg_initialize(&h, &callbacks);
-	if (error != CPG_OK) {
-		log_print("cpg_initialize error %d", error);
-		return;
-	}
-
-	cpg_fd_get(h, &fd);
-
-	ci = client_add(fd, process_cpg, NULL);
-
-	g->cpg_client = ci;
-	g->cpg_handle = h;
-	g->cpg_fd = fd;
-	g->joining = 1;
-	a->client = ci;
-
-	memset(&cpgname, 0, sizeof(cpgname));
-	sprintf(cpgname.value, "%d_%s", level, name);
-	cpgname.length = strlen(cpgname.value) + 1;
-
- retry:
-	error = cpg_join(h, &cpgname);
-	if (error == CPG_ERR_TRY_AGAIN) {
-		log_debug("cpg_join error retry");
-		sleep(1);
-		if (!(++i % 10))
-			log_print("cpg_join error retrying");
-		goto retry;
-	}
-	if (error != CPG_OK) {
-		log_print("cpg_join error %d", error);
-		cpg_finalize(h);
-		return;
-	}
-}
-
-/* Problem: GROUP_LIBCPG is selected during version detection, then
-   an old cluster2 node starts (people aren't supposed to do this, but it may
-   happen, so it's nice to do what we can to address it).  groupd on the old
-   cluster2 node, using libgroup, will allow new groups to be formed on it.
-   Solution is a hack: when the cluster3 nodes select LIBCPG mode, they also
-   create unused/placeholder cpg's with the names of old known cluster2 groups,
-   which blocks them being fully joined by old groupd's that may come along. */
-
-static void block_old_nodes(void)
-{
-	block_old_group("default", 0);
-	block_old_group("clvmd", 1);
-	block_old_group("rgmanager", 1);
-}
-
diff --git a/group/daemon/gd_internal.h b/group/daemon/gd_internal.h
deleted file mode 100644
index 1927104..0000000
--- a/group/daemon/gd_internal.h
+++ /dev/null
@@ -1,323 +0,0 @@
-#ifndef __GD_INTERNAL_DOT_H__
-#define __GD_INTERNAL_DOT_H__
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <fcntl.h>
-#include <string.h>
-#include <strings.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <syslog.h>
-#include <time.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/poll.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <corosync/cpg.h>
-#include <liblogthread.h>
-
-#include "list.h"
-#include "linux_endian.h"
-#include "groupd.h"
-#include "libgroup.h"
-
-#define MAX_NAMELEN		32	/* should match libgroup.h */
-#define MAX_LEVELS		4
-#define MAX_NODES		128
-
-extern int daemon_debug_opt;
-extern int daemon_debug_verbose;
-extern int daemon_quit;
-extern int cman_quorate;
-extern int our_nodeid;
-extern char *our_name;
-extern char daemon_debug_buf[256];
-extern char dump_buf[GROUPD_DUMP_SIZE];
-extern int dump_point;
-extern int dump_wrap;
-extern struct list_head gd_groups;
-extern struct list_head gd_levels[MAX_LEVELS];
-extern uint32_t gd_event_nr;
-
-#define GROUP_PENDING		1
-#define GROUP_LIBGROUP          2
-#define GROUP_LIBCPG            3
-
-extern int group_mode;
-
-#define DEFAULT_GROUPD_COMPAT		2
-#define DEFAULT_GROUPD_WAIT		5
-#define DEFAULT_GROUPD_MODE_DELAY	2
-#define DEFAULT_DEBUG_LOGFILE		0
-
-extern int optd_groupd_compat;
-extern int optd_groupd_wait;
-extern int optd_groupd_mode_delay;
-extern int optd_debug_logfile;
-
-extern int cfgd_groupd_compat;
-extern int cfgd_groupd_wait;
-extern int cfgd_groupd_mode_delay;
-extern int cfgd_debug_logfile;
-
-void daemon_dump_save(void);
-
-#define log_level(lvl, fmt, args...) \
-do { \
-	snprintf(daemon_debug_buf, 255, "%ld " fmt "\n", time(NULL), ##args); \
-	daemon_dump_save(); \
-	logt_print(lvl, fmt "\n", ##args); \
-	if (daemon_debug_opt) \
-		fprintf(stderr, "%s", daemon_debug_buf); \
-} while (0)
-
-#define log_debug(fmt, args...) log_level(LOG_DEBUG, fmt, ##args)
-#define log_print(fmt, args...) log_level(LOG_ERR, fmt, ##args)
-
-#define log_group(g, fmt, args...) \
-do { \
-	snprintf(daemon_debug_buf, 255, "%ld %d:%s " fmt "\n", time(NULL), \
-		 (g)->level, (g)->name, ##args); \
-	daemon_dump_save(); \
-	logt_print(LOG_DEBUG, fmt "\n", ##args); \
-	if (daemon_debug_opt) \
-		fprintf(stderr, "%s", daemon_debug_buf); \
-} while (0)
-
-#define log_error(g, fmt, args...) \
-do { \
-	snprintf(daemon_debug_buf, 255, "%ld %d:%s " fmt "\n", time(NULL), \
-		 (g)->level, (g)->name, ##args); \
-	daemon_dump_save(); \
-	logt_print(LOG_ERR, fmt "\n", ##args); \
-	if (daemon_debug_opt) \
-		fprintf(stderr, "%s", daemon_debug_buf); \
-} while (0)
-
-#define ASSERT(x) \
-do { \
-	if (!(x)) { \
-		log_print("Assertion failed on line %d of file %s\n" \
-			  "Assertion:  \"%s\"\n", __LINE__, __FILE__, #x); \
-	} \
-} while (0)
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-struct group;
-struct app;
-struct event;
-struct node;
-struct msg;
-typedef struct group group_t;
-typedef struct app app_t;
-typedef struct event event_t;
-typedef struct node node_t;
-typedef struct msg msg_t;
-
-
-/*
- * Event - manages nodes joining/leaving/failing
- */
-
-#define EST_JOIN_BEGIN         1
-#define EST_JOIN_STOP_WAIT     2
-#define EST_JOIN_ALL_STOPPED   3
-#define EST_JOIN_START_WAIT    4
-#define EST_JOIN_ALL_STARTED   5
-#define EST_LEAVE_BEGIN        6
-#define EST_LEAVE_STOP_WAIT    7
-#define EST_LEAVE_ALL_STOPPED  8
-#define EST_LEAVE_START_WAIT   9
-#define EST_LEAVE_ALL_STARTED 10
-#define EST_FAIL_BEGIN        11
-#define EST_FAIL_STOP_WAIT    12
-#define EST_FAIL_ALL_STOPPED  13
-#define EST_FAIL_START_WAIT   14
-#define EST_FAIL_ALL_STARTED  15
-
-struct event {
-	struct list_head 	list;
-	struct list_head	memb;
-	int			event_nr;
-	int 			state;
-	int			nodeid;
-	uint64_t		id;
-	struct list_head	extended;
-	int			start_app_before_pending_rev;
-	int			fail_all_stopped;
-};
-
-/*
- * Group
- */
-
-struct group {
-	struct list_head 	list;		/* list of groups */
-	struct list_head	level_list;
-	uint16_t 		level;
-	uint32_t		global_id;
-	struct list_head 	memb;
-	int 			memb_count;
-	int 			namelen;
-	char 			name[MAX_NAMELEN+1];
-	app_t 			*app;
-	struct list_head  	messages;
-	cpg_handle_t		cpg_handle;
-	int			cpg_fd;
-	int			cpg_client;
-	int			have_set_id;
-	int			joining;
-	int			leaving;
-};
-
-struct app {
-	int			client;
-	int 			node_count;
-	struct list_head 	nodes;
-	struct list_head	events;
-	event_t			*current_event;
-	group_t			*g;
-	int			need_first_event; /* for debugging */
-};
-
-#define MSG_APP_STOPPED        1
-#define MSG_APP_STARTED        2
-#define MSG_APP_RECOVER        3
-#define MSG_APP_INTERNAL       4
-#define MSG_GLOBAL_ID          5
-#define MSG_GROUP_VERSION      6
-
-#define MSG_VER_MAJOR          1
-#define MSG_VER_MINOR          1
-#define MSG_VER_PATCH          0
-
-struct msg {
-	uint32_t		ms_version[3];
-	uint16_t 		ms_type;
-	uint16_t		ms_level;
-	uint32_t 		ms_length;
-	uint32_t 		ms_global_id;
-	uint64_t		ms_event_id;
-	char			ms_name[MAX_NAMELEN];
-};
-
-struct save_msg {
-	struct list_head	list;
-	int			nodeid;
-	int			print_ignore;
-	int			msg_len;
-	msg_t			msg;
-	char			*msg_long;
-};
-
-struct node {
-	struct list_head 	list;
-	int			nodeid;
-	int			stopped;
-	int			started;
-};
-
-struct recovery_set {
-	struct list_head	list;
-	struct list_head	entries;
-	int			nodeid;
-	int			cman_update;
-	int			cpg_update;
-};
-
-struct recovery_entry {
-	struct list_head	list;
-	group_t			*group;
-	int			recovered;
-};
-
-
-/* app.c */
-void add_recovery_set_cman(int nodeid);
-struct recovery_set *add_recovery_set_cpg(int nodeid, int procdown);
-int queue_app_recover(group_t *g, int nodeid);
-int queue_app_join(group_t *g, int nodeid);
-int queue_app_leave(group_t *g, int nodeid);
-int queue_app_message(group_t *g, struct save_msg *save);
-int do_stopdone(char *name, int level);
-int do_startdone(char *name, int level, int event_nr);
-char *ev_state_str(event_t *ev);
-event_t *find_queued_recover_event(group_t *g);
-void extend_recover_event(group_t *g, event_t *ev, int nodeid);
-int process_apps(void);
-void del_event_nodes(event_t *ev);
-void dump_group(group_t *g);
-void dump_all_groups(void);
-node_t *find_app_node(app_t *a, int nodeid);
-int event_state_stopping(app_t *a);
-int event_state_starting(app_t *a);
-void msg_bswap_out(msg_t *msg);
-void msg_bswap_in(msg_t *msg);
-struct recovery_set *get_recovery_set(int nodeid);
-void groupd_down(int nodeid);
-char *msg_type(int type);
-int process_app(group_t *g);
-int is_our_join(event_t *ev);
-void purge_node_messages(group_t *g, int nodeid);
-
-/* main.c */
-void read_ccs_name(char *path, char *name);
-void read_ccs_yesno(char *path, int *yes, int *no);
-void read_ccs_int(char *path, int *config_val);
-void app_stop(app_t *a);
-void app_setid(app_t *a);
-void app_start(app_t *a);
-void app_finish(app_t *a);
-void app_terminate(app_t *a);
-void app_deliver(app_t *a, struct save_msg *save);
-int client_add(int fd, void (*workfn)(int ci), void (*deadfn)(int ci));
-void client_dead(int ci);
-void cluster_dead(int ci);
-
-/* cman.c */
-int setup_cman(void);
-void close_cman(void);
-void process_cman(int ci);
-int kill_cman(int nodeid);
-
-/* cpg.c */
-int setup_cpg(void);
-int do_cpg_join(group_t *g);
-int do_cpg_leave(group_t *g);
-int send_message(group_t *g, void *buf, int len);
-int send_message_groupd(group_t *g, void *buf, int len, int type);
-void copy_groupd_data(group_data_t *data);
-int in_groupd_cpg(int nodeid);
-void group_mode_check_timeout(void);
-
-/* joinleave.c */
-void remove_group(group_t *g);
-int do_join(char *name, int level, int ci);
-int do_leave(char *name, int level);
-node_t *new_node(int nodeid);
-group_t *find_group_level(char *name, int level);
-int create_group(char *name, int level, group_t **g_out);
-app_t *create_app(group_t *g);
-
-/* logging.c */
-
-void init_logging(void);
-void setup_logging();
-void close_logging(void);
-
-#endif				/* __GD_INTERNAL_DOT_H__ */
-
diff --git a/group/daemon/groupd.h b/group/daemon/groupd.h
deleted file mode 100644
index 69bd1fc..0000000
--- a/group/daemon/groupd.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __GROUPD_DOT_H__
-#define __GROUPD_DOT_H__
-
-#define GROUPD_SOCK_PATH        ("groupd_socket")
-#define NODE_FAILED		(1)
-#define NODE_JOIN		(2)
-#define NODE_LEAVE		(3)
-#define GROUPD_MSGLEN		(2200) /* should be enough to permit
-					  group_send() of up to 2048 bytes
-					  of data plus header info */
-#define GROUPD_DUMP_SIZE	(1024 * 1024)
-
-#endif
diff --git a/group/daemon/joinleave.c b/group/daemon/joinleave.c
deleted file mode 100644
index 95cc444..0000000
--- a/group/daemon/joinleave.c
+++ /dev/null
@@ -1,165 +0,0 @@
-
-/* Initiate join/leave requests from apps */
-
-#include "gd_internal.h"
-
-
-group_t *find_group_level(char *name, int level)
-{
-	group_t *g;
-
-	list_for_each_entry(g, &gd_levels[level], level_list) {
-		if (!strcmp(g->name, name))
-			return g;
-	}
-	return NULL;
-}
-
-int create_group(char *name, int level, group_t **g_out)
-{
-	group_t *g;
-
-	g = malloc(sizeof(*g));
-	if (!g)
-		return -ENOMEM;
-
-	memset(g, 0, sizeof(*g));
-
-	strcpy(g->name, name);
-	g->namelen = strlen(name);
-	g->level = level;
-	INIT_LIST_HEAD(&g->memb);
-	INIT_LIST_HEAD(&g->messages);
-
-	list_add_tail(&g->list, &gd_groups);
-	list_add_tail(&g->level_list, &gd_levels[level]);
-
-	*g_out = g;
-	return 0;
-}
-
-void free_group_memb(group_t *g)
-{
-	node_t *node, *n;
-
-	list_for_each_entry_safe(node, n, &g->memb, list) {
-		list_del(&node->list);
-		free(node);
-	}
-}
-
-void remove_group(group_t *g)
-{
-	list_del(&g->list);
-	list_del(&g->level_list);
-	free_group_memb(g);
-	free(g);
-}
-
-app_t *create_app(group_t *g)
-{
-	app_t *a;
-
-	a = malloc(sizeof(app_t));
-	if (!a)
-		return NULL;
-	memset(a, 0, sizeof(app_t));
-
-	a->need_first_event = 1;
-	INIT_LIST_HEAD(&a->nodes);
-	INIT_LIST_HEAD(&a->events);
-	a->g = g;
-	g->app = a;
-
-	return a;
-}
-
-int do_join(char *name, int level, int ci)
-{
-	group_t *g;
-	app_t *a;
-	int rv;
-
-	g = find_group_level(name, level);
-	if (g) {
-		log_group(g, "%d:%s can't join existing group", level, name);
-		rv = -EEXIST;
-		goto out;
-	}
-
-	rv = create_group(name, level, &g);
-	if (rv)
-		goto out;
-
-	a = create_app(g);
-	if (!a) {
-		rv = -ENOMEM;
-		goto out;
-	}
-
-	a->client = ci;
-
-	log_debug("%d:%s got join", level, name);
-	g->joining = 1;
-	rv = do_cpg_join(g);
- out:
-	return rv;
-}
-
-int do_leave(char *name, int level)
-{
-	group_t *g;
-	event_t *ev;
-	int rv;
-
-	g = find_group_level(name, level);
-	if (!g)
-		return -ENOENT;
-
-	if (!g->app) {
-		log_group(g, "leave: no app");
-		return -EINVAL;
-	}
-
-	if (g->joining) {
-		log_error(g, "leave: still joining");
-		return -EAGAIN;
-	}
-
-	if (g->leaving) {
-		log_error(g, "leave: already leaving");
-		return -EBUSY;
-	}
-
-	ev = g->app->current_event;
-
-	if (ev && ev->nodeid == our_nodeid) {
-		log_error(g, "leave: busy event %llx state %s",
-			  (unsigned long long)ev->id,
-			  ev_state_str(ev));
-		return -EAGAIN;
-	}
-
-	list_for_each_entry(ev, &g->app->events, list) {
-		ASSERT(ev->nodeid != our_nodeid);
-		log_group(g, "do_leave: found queued event id %llx",
-			  (unsigned long long)ev->id);
-	}
-
-	log_debug("%d:%s got leave", level, name);
-	g->leaving = 1;
-	rv = do_cpg_leave(g);
-	return rv;
-}
-
-node_t *new_node(int nodeid)
-{
-	node_t *node;
-
-	node = malloc(sizeof(*node));
-	// FIXME: handle failed malloc
-	memset(node, 0, sizeof(*node));
-	node->nodeid = nodeid;
-	return node;
-}
-
diff --git a/group/daemon/logging.c b/group/daemon/logging.c
deleted file mode 100644
index e3cd636..0000000
--- a/group/daemon/logging.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "gd_internal.h"
-#include "ccs.h"
-
-extern int ccs_handle;
-
-#define DAEMON_NAME "groupd"
-#define DEFAULT_LOG_MODE LOG_MODE_OUTPUT_FILE|LOG_MODE_OUTPUT_SYSLOG
-#define DEFAULT_SYSLOG_FACILITY		SYSLOGFACILITY
-#define DEFAULT_SYSLOG_PRIORITY		SYSLOGLEVEL
-#define DEFAULT_LOGFILE_PRIORITY	LOG_INFO /* ? */
-#define DEFAULT_LOGFILE			LOGDIR "/" DAEMON_NAME ".log"
-
-static int log_mode;
-static int syslog_facility;
-static int syslog_priority;
-static int logfile_priority;
-static char logfile[PATH_MAX];
-
-void init_logging(void)
-{
-	log_mode = DEFAULT_LOG_MODE;
-	syslog_facility = DEFAULT_SYSLOG_FACILITY;
-	syslog_priority = DEFAULT_SYSLOG_PRIORITY;
-	logfile_priority = DEFAULT_LOGFILE_PRIORITY;
-	strcpy(logfile, DEFAULT_LOGFILE);
-
-	/* logfile_priority is the only one of these options that
-	   can be controlled from command line or environment variable */
-
-	if (cfgd_debug_logfile)
-		logfile_priority = LOG_DEBUG;
-
-	log_debug("logging mode %d syslog f %d p %d logfile p %d %s",
-		  log_mode, syslog_facility, syslog_priority,
-		  logfile_priority, logfile);
-
-	logt_init(DAEMON_NAME, log_mode, syslog_facility, syslog_priority,
-		  logfile_priority, logfile);
-}
-
-void setup_logging(void)
-{
-	ccs_read_logging(ccs_handle, DAEMON_NAME,
-			 &cfgd_debug_logfile, &log_mode,
-			 &syslog_facility, &syslog_priority,
-			 &logfile_priority, logfile);
-
-	log_debug("logging mode %d syslog f %d p %d logfile p %d %s",
-		  log_mode, syslog_facility, syslog_priority,
-		  logfile_priority, logfile);
-
-	logt_conf(DAEMON_NAME, log_mode, syslog_facility, syslog_priority,
-		  logfile_priority, logfile);
-}
-
-void close_logging(void)
-{
-	logt_exit();
-}
-
diff --git a/group/daemon/main.c b/group/daemon/main.c
deleted file mode 100644
index 5b07505..0000000
--- a/group/daemon/main.c
+++ /dev/null
@@ -1,1082 +0,0 @@
-#include <signal.h>
-#include <time.h>
-
-#include "gd_internal.h"
-#include "ccs.h"
-#include "copyright.cf"
-
-#define LOCKFILE_NAME	"/var/run/groupd.pid"
-#define CLIENT_NALLOC	32
-
-extern struct list_head recovery_sets;
-
-static int client_maxi;
-static int client_size = 0;
-static struct client *client = NULL;
-static struct pollfd *pollfd = NULL;
-static char last_action[16];
-int ccs_handle;
-
-struct client {
-	int fd;
-	int level;
-	char type[32];
-	void *workfn;
-	void *deadfn;
-};
-
-static int do_read(int fd, void *buf, size_t count)
-{
-	int rv, off = 0;
-
-	while (off < count) {
-		rv = read(fd, buf + off, count - off);
-		if (rv == 0)
-			return -1;
-		if (rv == -1 && errno == EINTR)
-			continue;
-		if (rv == -1)
-			return -1;
-		off += rv;
-	}
-	return 0;
-}
-
-static int do_write(int fd, void *buf, size_t count)
-{
-	int rv, off = 0;
-
- retry:
-	rv = write(fd, buf + off, count);
-	if (rv == -1 && errno == EINTR)
-		goto retry;
-	if (rv < 0) {
-		log_print("write fd %d errno %d", fd, errno);
-		return rv;
-	}
-
-	if (rv != count) {
-		count -= rv;
-		off += rv;
-		goto retry;
-	}
-	return 0;
-}
-
-void read_ccs_name(char *path, char *name)
-{
-	char *str;
-	int error;
-
-	error = ccs_get(ccs_handle, path, &str);
-	if (error || !str)
-		return;
-
-	strcpy(name, str);
-
-	free(str);
-}
-
-void read_ccs_yesno(char *path, int *yes, int *no)
-{
-	char *str;
-	int error;
-
-	*yes = 0;
-	*no = 0;
-
-	error = ccs_get(ccs_handle, path, &str);
-	if (error || !str)
-		return;
-
-	if (!strcmp(str, "yes"))
-		*yes = 1;
-
-	else if (!strcmp(str, "no"))
-		*no = 1;
-
-	free(str);
-}
-
-void read_ccs_int(char *path, int *config_val)
-{
-	char *str;
-	int val;
-	int error;
-
-	error = ccs_get(ccs_handle, path, &str);
-	if (error || !str)
-		return;
-
-	val = atoi(str);
-
-	if (val < 0) {
-		log_print("ignore invalid value %d for %s", val, path);
-		return;
-	}
-
-	*config_val = val;
-	log_debug("%s is %u", path, val);
-	free(str);
-}
-
-#define GROUPD_COMPAT_PATH "/cluster/group/@groupd_compat"
-#define GROUPD_WAIT_PATH "/cluster/group/@groupd_wait"
-#define GROUPD_MODE_DELAY_PATH "/cluster/group/@groupd_mode_delay"
-
-int setup_ccs(void)
-{
-	int cd;
-
-	cd = ccs_connect();
-	if (cd < 0) {
-		log_print("ccs_connect error %d %d", cd, errno);
-		return -1;
-	}
-	ccs_handle = cd;
-
-	/* These config values are set from cluster.conf only if they haven't
-	   already been set on the command line. */
-
-	if (!optd_groupd_compat)
-		read_ccs_int(GROUPD_COMPAT_PATH, &cfgd_groupd_compat);
-
-	if (!optd_groupd_wait)
-		read_ccs_int(GROUPD_WAIT_PATH, &cfgd_groupd_wait);
-
-	if (!optd_groupd_mode_delay)
-		read_ccs_int(GROUPD_MODE_DELAY_PATH, &cfgd_groupd_mode_delay);
-
-	return 0;
-}
-
-void close_ccs(void)
-{
-	ccs_disconnect(ccs_handle);
-}
-
-static void app_action(app_t *a, char *buf)
-{
-	int rv;
-
-	log_group(a->g, "action for app: %s", buf);
-
-	rv = do_write(client[a->client].fd, buf, GROUPD_MSGLEN);
-	if (rv < 0)
-		log_error(a->g, "app_action write error");
-}
-
-void app_deliver(app_t *a, struct save_msg *save)
-{
-	char buf[GROUPD_MSGLEN];
-	int rv;
-
-	rv = snprintf(buf, sizeof(buf), "deliver %s %d %d",
-		      a->g->name, save->nodeid,
-		      (int)(save->msg_len - sizeof(msg_t)));
-
-	log_group(a->g, "deliver to app: %s", buf);
-
-	memcpy(buf + rv + 1, save->msg_long + sizeof(msg_t),
-	       save->msg_len - sizeof(msg_t));
-
-	/*
-	log_group(a->g, "app_deliver body len %d \"%s\"",
-		  save->msg_len - sizeof(msg_t),
-		  save->msg_long + sizeof(msg_t));
-	*/
-
-	rv = do_write(client[a->client].fd, buf, GROUPD_MSGLEN);
-	if (rv < 0)
-		log_error(a->g, "app_deliver write error");
-}
-
-void app_terminate(app_t *a)
-{
-	char buf[GROUPD_MSGLEN];
-	snprintf(buf, sizeof(buf), "terminate %s", a->g->name);
-	app_action(a, buf);
-}
-
-void app_stop(app_t *a)
-{
-	char buf[GROUPD_MSGLEN];
-	snprintf(buf, sizeof(buf), "stop %s", a->g->name);
-	app_action(a, buf);
-}
-
-void app_setid(app_t *a)
-{
-	char buf[GROUPD_MSGLEN];
-	snprintf(buf, sizeof(buf), "setid %s %u", a->g->name, a->g->global_id);
-	app_action(a, buf);
-}
-
-void app_start(app_t *a)
-{
-	char buf[GROUPD_MSGLEN];
-	int len = 0, type, count = 0;
-	node_t *node;
-
-	if (a->current_event->state == EST_JOIN_START_WAIT)
-		type = NODE_JOIN;
-	else if (a->current_event->state == EST_LEAVE_START_WAIT)
-		type = NODE_LEAVE;
-	else if (a->current_event->state == EST_FAIL_START_WAIT)
-		type = NODE_FAILED;
-	else {
-		/* report error */
-		type = -1;
-	}
-
-	/* start <name> <event_nr> <type> <count> <memb0> <memb1>... */
-
-	list_for_each_entry(node, &a->nodes, list)
-		count++;
-
-	len = snprintf(buf, sizeof(buf), "start %s %d %d %d",
-		       a->g->name, a->current_event->event_nr, type, count);
-
-	list_for_each_entry(node, &a->nodes, list)
-		len += sprintf(buf+len, " %d", node->nodeid);
-
-	app_action(a, buf);
-}
-
-void app_finish(app_t *a)
-{
-	char buf[GROUPD_MSGLEN];
-	snprintf(buf, sizeof(buf), "finish %s %d",
-		 a->g->name, a->current_event->event_nr);
-	app_action(a, buf);
-}
-
-#define MAXARGS 16
-
-static char *get_args(char *buf, int *argc, char **argv, char sep, int want)
-{
-	char *p = buf, *rp = NULL;
-	int i;
-
-	argv[0] = p;
-
-	for (i = 1; i < MAXARGS; i++) {
-		p = strchr(buf, sep);
-		if (!p)
-			break;
-		*p = '\0';
-
-		if (want == i) {
-			rp = p + 1;
-			break;
-		}
-
-		argv[i] = p + 1;
-		buf = p + 1;
-	}
-	*argc = i;
-
-	/* we ended by hitting \0, return the point following that */
-	if (!rp)
-		rp = strchr(buf, '\0') + 1;
-
-	return rp;
-}
-
-enum {
-	DO_SETUP = 1,
-	DO_JOIN,
-	DO_LEAVE,
-	DO_STOP_DONE,
-	DO_START_DONE,
-	DO_SEND,
-	DO_GET_GROUPS,
-	DO_GET_GROUP,
-	DO_DUMP,
-	DO_LOG,
-	DO_GET_VERSION,
-};
-
-int get_action(char *buf)
-{
-	char act[16];
-	int i;
-
-	memset(act, 0, 16);
-
-	for (i = 0; i < 16; i++) {
-		if (isalnum(buf[i]) || ispunct(buf[i]))
-			act[i] = buf[i];
-		else
-			break;
-	}
-
-	/* for debug message */
-	memset(&last_action, 0, 16);
-	memcpy(last_action, act, 16);
-
-	if (!strncmp(act, "setup", 16))
-		return DO_SETUP;
-
-	if (!strncmp(act, "join", 16))
-		return DO_JOIN;
-
-	if (!strncmp(act, "leave", 16))
-		return DO_LEAVE;
-
-	if (!strncmp(act, "stop_done", 16))
-		return DO_STOP_DONE;
-
-	if (!strncmp(act, "start_done", 16))
-		return DO_START_DONE;
-
-	if (!strncmp(act, "send", 16))
-		return DO_SEND;
-
-	if (!strncmp(act, "get_groups", 16))
-		return DO_GET_GROUPS;
-
-	if (!strncmp(act, "get_group", 16))
-		return DO_GET_GROUP;
-
-	if (!strncmp(act, "get_version", 16))
-		return DO_GET_VERSION;
-
-	if (!strncmp(act, "dump", 16))
-		return DO_DUMP;
-
-	if (!strncmp(act, "log", 16))
-		return DO_LOG;
-
-	return -1;
-}
-
-static void client_alloc(void)
-{
-	int i;
-
-	if (!client) {
-		client = malloc(CLIENT_NALLOC * sizeof(struct client));
-		pollfd = malloc(CLIENT_NALLOC * sizeof(struct pollfd));
-	} else {
-		client = realloc(client, (client_size + CLIENT_NALLOC) *
-					 sizeof(struct client));
-		pollfd = realloc(pollfd, (client_size + CLIENT_NALLOC) *
-					 sizeof(struct pollfd));
-		if (!pollfd)
-			log_print("can't alloc for pollfd");
-	}
-	if (!client || !pollfd)
-		log_print("can't alloc for client array");
-
-	for (i = client_size; i < client_size + CLIENT_NALLOC; i++) {
-		client[i].workfn = NULL;
-		client[i].deadfn = NULL;
-		client[i].fd = -1;
-		client[i].level = -1;
-		memset(client[i].type, 0, sizeof(client[i].type));
-		pollfd[i].fd = -1;
-		pollfd[i].revents = 0;
-	}
-	client_size += CLIENT_NALLOC;
-}
-
-void client_dead(int ci)
-{
-	close(client[ci].fd);
-	client[ci].workfn = NULL;
-	client[ci].fd = -1;
-	pollfd[ci].fd = -1;
-}
-
-int client_add(int fd, void (*workfn)(int ci), void (*deadfn)(int ci))
-{
-	int i;
-
-	if (!client)
-		client_alloc();
- again:
-	for (i = 0; i < client_size; i++) {
-		if (client[i].fd == -1) {
-			client[i].workfn = workfn;
-			if (deadfn)
-				client[i].deadfn = deadfn;
-			else
-				client[i].deadfn = client_dead;
-			client[i].fd = fd;
-			pollfd[i].fd = fd;
-			pollfd[i].events = POLLIN;
-			if (i > client_maxi)
-				client_maxi = i;
-			return i;
-		}
-	}
-
-	client_alloc();
-	goto again;
-}
-
-static void sigterm_handler(int sig)
-{
-	daemon_quit = 1;
-}
-
-static void do_setup(int ci, int argc, char **argv)
-{
-	log_debug("setup %s %s", argv[1], argv[2]);
-
-	strcpy(client[ci].type, argv[1]);
-	client[ci].level = atoi(argv[2]);
-}
-
-static void copy_group_data(group_t *g, group_data_t *data)
-{
-	node_t *node;
-	event_t *ev;
-	int i = 0;
-
-	strncpy(data->client_name, client[g->app->client].type, 32);
-	strncpy(data->name, g->name, MAX_GROUP_NAME_LEN);
-	data->level = g->level;
-	data->id = g->global_id;
-
-	if (g->app && g->app->current_event) {
-		event_t *ev = g->app->current_event;
-		data->event_state = ev->state;
-		data->event_nodeid = ev->nodeid;
-		data->event_id = ev->id;
-		data->event_local_status = -2;
-
-		node = find_app_node(g->app, our_nodeid);
-		if (node) {
-			if (event_state_stopping(g->app))
-				data->event_local_status = node->stopped;
-			else if (event_state_starting(g->app))
-				data->event_local_status = node->started;
-			else
-				data->event_local_status = -1;
-		}
-	}
-
-	data->member_count = g->app->node_count;
-	list_for_each_entry(node, &g->app->nodes, list) {
-		data->members[i] = node->nodeid;
-		i++;
-
-		if (node->nodeid == our_nodeid)
-			data->member = 1;
-	}
-
-	/* we're in the member list but are still joining */
-	if (data->member) {
-		ev = g->app->current_event;
-		if (ev && is_our_join(ev) &&
-		    (ev->state <= EST_JOIN_ALL_STARTED))
-			data->member = 0;
-	}
-}
-
-static int do_get_groups(int ci, int argc, char **argv)
-{
-	group_t *g;
-	group_data_t *data;
-	int rv, count = 0, max = atoi(argv[1]);
-
-	data = malloc(sizeof(group_data_t));
-	// FIXME: handle failed malloc
-	count = 0;
-
-	list_for_each_entry(g, &gd_groups, list) {
-		memset(data, 0, sizeof(group_data_t));
-		copy_group_data(g, data);
-		rv = do_write(client[ci].fd, data, sizeof(group_data_t));
-		if (rv < 0) {
-			log_print("do_get_groups write error");
-			break;
-		}
-		count++;
-		if (count >= max)
-			break;
-	}
-	/* Now write an empty one indicating there aren't anymore: */
-	memset(data, 0, sizeof(group_data_t));
-	rv = do_write(client[ci].fd, data, sizeof(group_data_t));
-	free(data);
-	return 0;
-}
-
-static int do_get_group(int ci, int argc, char **argv)
-{
-	group_t *g;
-	group_data_t data;
-	int rv;
-
-	memset(&data, 0, sizeof(data));
-
-	/* special case to get members of groupd cpg */
-	if (atoi(argv[1]) == -1 && !strncmp(argv[2], "groupd", 6)) {
-		copy_groupd_data(&data);
-		goto out;
-	}
-
-	g = find_group_level(argv[2], atoi(argv[1]));
-	if (!g)
-		goto out;
-
-	copy_group_data(g, &data);
- out:
-	rv = do_write(client[ci].fd, &data, sizeof(data));
-	if (rv < 0)
-		log_print("do_get_group write error");
-
-	return 0;
-}
-
-static int do_get_version(int ci)
-{
-	int mode;
-	int rv;
-
-	if (group_mode == GROUP_PENDING)
-		mode = -EAGAIN;
-	else
-		mode = group_mode;
-
-	rv = do_write(client[ci].fd, &mode, sizeof(mode));
-	if (rv < 0)
-		log_print("do_get_version write error");
-
-	return 0;
-}
-
-static int do_dump(int fd)
-{
-	int len;
-
-	if (dump_wrap) {
-		len = GROUPD_DUMP_SIZE - dump_point;
-		do_write(fd, dump_buf + dump_point, len);
-		len = dump_point;
-	} else
-		len = dump_point;
-
-	/* NUL terminate the debug string */
-	dump_buf[dump_point] = '\0';
-
-	do_write(fd, dump_buf, len);
-
-	return 0;
-}
-
-static int do_log(int fd, const char *comment)
-{
-	log_print("%s", comment);
-	return 0;
-}
-
-static void do_send(char *name, int level, int len, char *data)
-{
-	group_t *g;
-	msg_t *msg;
-	char *buf;
-	int total;
-
-	g = find_group_level(name, level);
-	if (!g)
-		return;
-
-	total = sizeof(msg_t) + len;
-	buf = malloc(total);
-	// FIXME: handle failed malloc
-	memset(buf, 0, total);
-
-	memcpy(buf + sizeof(msg_t), data, len);
-
-	msg = (msg_t *) buf;
-	msg->ms_type = MSG_APP_INTERNAL;
-	msg->ms_global_id = g->global_id;
-
-	log_debug("%d:%s do_send %d bytes", level, name, total);
-
-	send_message(g, msg, total);
-
-	free(buf);
-}
-
-static void process_connection(int ci)
-{
-	char buf[GROUPD_MSGLEN], *argv[MAXARGS], *p;
-	int argc = 0, rv, act;
-
-	memset(buf, 0, sizeof(buf));
-	memset(argv, 0, sizeof(char *) * MAXARGS);
-
-	rv = do_read(client[ci].fd, buf, GROUPD_MSGLEN);
-	if (rv < 0) {
-		client_dead(ci);
-		return;
-	}
-
-	act = get_action(buf);
-
-	log_debug("got client %d %s", ci, last_action);
-
-	switch (act) {
-
-	case DO_SETUP:
-		get_args(buf, &argc, argv, ' ', 3);
-		do_setup(ci, argc, argv);
-		break;
-
-	case DO_JOIN:
-		get_args(buf, &argc, argv, ' ', 2);
-		do_join(argv[1], client[ci].level, ci);
-		break;
-
-	case DO_LEAVE:
-		get_args(buf, &argc, argv, ' ', 2);
-		do_leave(argv[1], client[ci].level);
-		break;
-
-	case DO_STOP_DONE:
-		get_args(buf, &argc, argv, ' ', 2);
-		do_stopdone(argv[1], client[ci].level);
-		break;
-
-	case DO_START_DONE:
-		get_args(buf, &argc, argv, ' ', 3);
-		do_startdone(argv[1], client[ci].level, atoi(argv[2]));
-		break;
-
-	case DO_SEND:
-		p = get_args(buf, &argc, argv, ' ', 3);
-		do_send(argv[1], client[ci].level, atoi(argv[2]), p);
-		break;
-
-	case DO_GET_GROUPS:
-		get_args(buf, &argc, argv, ' ', 2);
-		do_get_groups(ci, argc, argv);
-		break;
-
-	case DO_GET_GROUP:
-		get_args(buf, &argc, argv, ' ', 3);
-		do_get_group(ci, argc, argv);
-		break;
-
-	case DO_GET_VERSION:
-		do_get_version(ci);
-		break;
-
-	case DO_DUMP:
-		do_dump(client[ci].fd);
-		close(client[ci].fd);
-		break;
-
-	case DO_LOG:
-		do_log(client[ci].fd, &buf[4]);
-		break;
-
-	default:
-		log_print("unknown action %d client %d", act, ci);
-		log_print("invalid message: \"%s\"", buf);
-	}
-}
-
-static void process_listener(int ci)
-{
-	int fd, i;
-
-	fd = accept(client[ci].fd, NULL, NULL);
-	if (fd < 0) {
-		log_print("process_listener: accept error %d %d", fd, errno);
-		return;
-	}
-	
-	i = client_add(fd, process_connection, NULL);
-
-	log_debug("client connection %d fd %d", i, fd);
-}
-
-static int setup_listener(char *sock_path)
-{
-	struct sockaddr_un addr;
-	socklen_t addrlen;
-	int rv, s;
-
-	/* we listen for new client connections on socket s */
-
-	s = socket(AF_LOCAL, SOCK_STREAM, 0);
-	if (s < 0) {
-		log_print("socket error %d %d", s, errno);
-		return s;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = AF_LOCAL;
-	strcpy(&addr.sun_path[1], sock_path);
-	addrlen = sizeof(sa_family_t) + strlen(addr.sun_path+1) + 1;
-
-	rv = bind(s, (struct sockaddr *) &addr, addrlen);
-	if (rv < 0) {
-		log_print("bind error %d %d", rv, errno);
-		close(s);
-		return rv;
-	}
-
-	rv = listen(s, 5);
-	if (rv < 0) {
-		log_print("listen error %d %d", rv, errno);
-		close(s);
-		return rv;
-	}
-	return s;
-}
-
-void cluster_dead(int ci)
-{
-	log_print("cluster is down, exiting");
-	daemon_quit = 1;
-}
-
-#define min(x, y) ({                            \
-	typeof(x) _min1 = (x);                  \
-	typeof(y) _min2 = (y);                  \
-	(void) (&_min1 == &_min2);              \
-	_min1 < _min2 ? _min1 : _min2; })
-
-static void loop(void)
-{
-	int poll_timeout = -1;	
-	int rv, i;
-	void (*workfn) (int ci);
-	void (*deadfn) (int ci);
-
-	rv = setup_listener(GROUPD_SOCK_PATH);
-	if (rv < 0)
-		goto out;
-	client_add(rv, process_listener, NULL);
-
-	rv = setup_cman();
-	if (rv < 0)
-		goto out;
-	client_add(rv, process_cman, cluster_dead);
-
-	rv = setup_ccs();
-	if (rv < 0)
-		goto out;
-
-	setup_logging();
-
-	if (cfgd_groupd_compat == 0) {
-		group_mode = GROUP_LIBCPG;
-		log_level(LOG_INFO, "groupd compatibility mode 0 cfg");
-	} else if (cfgd_groupd_compat == 1) {
-		group_mode = GROUP_LIBGROUP;
-		log_level(LOG_INFO, "groupd compatibility mode 1 cfg");
-	} else if (cfgd_groupd_compat == 2) {
-		group_mode = GROUP_PENDING;
-		/* report the mode in set_group_mode() */
-	}
-
-	rv = setup_cpg();
-	if (rv < 0)
-		goto out;
-
-	for (;;) {
-		rv = poll(pollfd, client_maxi + 1, poll_timeout);
-		if (rv == -1 && errno == EINTR) {
-			if (daemon_quit && (group_mode == GROUP_LIBCPG ||
-					    list_empty(&gd_groups)))
-				goto out;
-			daemon_quit = 0;
-			continue;
-		}
-		if (rv < 0) {
-			log_print("poll errno %d", errno);
-			goto out;
-		}
-
-		for (i = 0; i <= client_maxi; i++) {
-			if (client[i].fd < 0)
-				continue;
-			if (pollfd[i].revents & POLLIN) {
-				workfn = client[i].workfn;
-				workfn(i);
-			}
-			if (pollfd[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
-				deadfn = client[i].deadfn;
-				deadfn(i);
-			}
-		}
-
-		if (daemon_quit)
-			break;
-
-		/* process_apps() returns non-zero if there may be
-		   more work to do */
-
-		do {
-			rv = 0;
-			rv += process_apps();
-		} while (rv);
-
-		poll_timeout = -1;
-
-		if (group_mode == GROUP_PENDING) {
-			group_mode_check_timeout();
-			poll_timeout = 1000 * min(cfgd_groupd_wait, cfgd_groupd_mode_delay);
-		}
-	}
- out:
-	close_ccs();
-	close_cman();
-
-	/* in LIBCPG mode, gd_groups is not empty because of the groups we
-	   add to "block" old versions of groupd */
-	if ((group_mode == GROUP_LIBGROUP) && !list_empty(&gd_groups))
-		log_print("groups abandoned");
-}
-
-static void lockfile(void)
-{
-	int fd, error;
-	struct flock lock;
-	char buf[33];
-
-	memset(buf, 0, 33);
-
-	fd = open(LOCKFILE_NAME, O_CREAT|O_WRONLY,
-		  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
-	if (fd < 0) {
-		fprintf(stderr, "cannot open/create lock file %s\n",
-			LOCKFILE_NAME);
-		exit(EXIT_FAILURE);
-	}
-
-	lock.l_type = F_WRLCK;
-	lock.l_start = 0;
-	lock.l_whence = SEEK_SET;
-	lock.l_len = 0;
-
-	error = fcntl(fd, F_SETLK, &lock);
-	if (error) {
-		fprintf(stderr, "groupd is already running\n");
-		exit(EXIT_FAILURE);
-	}
-
-	error = ftruncate(fd, 0);
-	if (error) {
-		fprintf(stderr, "cannot clear lock file %s\n", LOCKFILE_NAME);
-		exit(EXIT_FAILURE);
-	}
-
-	sprintf(buf, "%d\n", getpid());
-
-	error = write(fd, buf, strlen(buf));
-	if (error <= 0) {
-		fprintf(stderr, "cannot write lock file %s\n", LOCKFILE_NAME);
-		exit(EXIT_FAILURE);
-	}
-}
-
-static void print_usage(void)
-{
-	printf("Usage:\n");
-	printf("\n");
-	printf("groupd [options]\n");
-	printf("\n");
-	printf("Options:\n");
-	printf("\n");
-	printf("  -D	       Enable debugging to stderr and don't fork\n");
-	printf("  -L           Enable debugging to log file\n");
-	printf("  -g <num>     group compatibility mode, 0 off, 1 on, 2 detect\n");
-	printf("               0: use libcpg, no backward compat, best performance\n");
-	printf("               1: use libgroup for compat with cluster2/rhel5\n");
-	printf("               2: detect old, or mode 1, nodes that require compat,\n"
-	       "               use libcpg if none found\n");
-	printf("               Default is %d\n", DEFAULT_GROUPD_COMPAT);
-	printf("  -w <secs>    seconds to wait for a node's version message before\n"
-	       "               assuming an old version requiring compat mode\n");
-	printf("               Default is %d\n", DEFAULT_GROUPD_WAIT);
-	printf("  -d <secs>    seconds to delay the mode selection to give time\n"
-	       "               for an old version to join and force compat mode\n");
-	printf("               Default is %d\n", DEFAULT_GROUPD_MODE_DELAY);
-	printf("  -h	       Print this help, then exit\n");
-	printf("  -V	       Print program version information, then exit\n");
-}
-
-#define OPTION_STRING "LDg:w:d:hVv"
-
-static void read_arguments(int argc, char **argv)
-{
-	int cont = 1;
-	int optchar;
-
-	while (cont) {
-		optchar = getopt(argc, argv, OPTION_STRING);
-
-		switch (optchar) {
-
-		case 'D':
-			daemon_debug_opt = 1;
-			break;
-
-		case 'L':
-			optd_debug_logfile = 1;
-			cfgd_debug_logfile = 1;
-			break;
-
-		case 'g':
-			optd_groupd_compat = 1;
-			cfgd_groupd_compat = atoi(optarg);
-			break;
-
-		case 'w':
-			optd_groupd_wait = 1;
-			cfgd_groupd_wait = atoi(optarg);
-			break;
-
-		case 'd':
-			optd_groupd_mode_delay = 1;
-			cfgd_groupd_mode_delay = atoi(optarg);
-			break;
-
-		case 'h':
-			print_usage();
-			exit(EXIT_SUCCESS);
-			break;
-
-		case 'v':
-			daemon_debug_verbose++;
-			break;
-
-		case 'V':
-			printf("groupd %s (built %s %s)\n",
-				RELEASE_VERSION, __DATE__, __TIME__);
-			printf("%s\n", REDHAT_COPYRIGHT);
-			exit(EXIT_SUCCESS);
-			break;
-
-		case ':':
-		case '?':
-			fprintf(stderr, "Please use '-h' for usage.\n");
-			exit(EXIT_FAILURE);
-			break;
-
-		case EOF:
-			cont = FALSE;
-			break;
-
-		default:
-			fprintf(stderr, "unknown option: %c\n", optchar);
-			exit(EXIT_FAILURE);
-			break;
-		};
-	}
-
-	if (getenv("GROUPD_DEBUG")) {
-		optd_debug_logfile = 1;
-		cfgd_debug_logfile = 1;
-	}
-}
-
-static void set_oom_adj(int val)
-{
-	FILE *fp;
-
-	fp = fopen("/proc/self/oom_adj", "w");
-	if (!fp)
-		return;
-
-	fprintf(fp, "%i", val);
-	fclose(fp);
-}
-
-static void set_scheduler(void)
-{
-	struct sched_param sched_param;
-	int rv;
-
-	rv = sched_get_priority_max(SCHED_RR);
-	if (rv != -1) {
-		sched_param.sched_priority = rv;
-		rv = sched_setscheduler(0, SCHED_RR, &sched_param);
-		if (rv == -1)
-			log_print("could not set SCHED_RR priority %d err %d",
-				   sched_param.sched_priority, errno);
-	} else {
-		log_print("could not get maximum scheduler priority err %d",
-			  errno);
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	int i;
-
-	INIT_LIST_HEAD(&recovery_sets);
-	INIT_LIST_HEAD(&gd_groups);
-	for (i = 0; i < MAX_LEVELS; i++)
-		INIT_LIST_HEAD(&gd_levels[i]);
-
-	read_arguments(argc, argv);
-	lockfile();
-
-	if (!daemon_debug_opt) {
-		if (daemon(0, 0) < 0) {
-			perror("daemon error");
-			exit(EXIT_FAILURE);
-		}
-	}
-	init_logging();
-	log_level(LOG_INFO, "groupd %s", RELEASE_VERSION);
-	signal(SIGTERM, sigterm_handler);
-	set_scheduler();
-	set_oom_adj(-16);
-
-	loop();
-
-	return 0;
-}
-
-void daemon_dump_save(void)
-{
-	int len, i;
-
-	len = strlen(daemon_debug_buf);
-
-	for (i = 0; i < len; i++) {
-		dump_buf[dump_point++] = daemon_debug_buf[i];
-
-		if (dump_point == GROUPD_DUMP_SIZE) {
-			dump_point = 0;
-			dump_wrap = 1;
-		}
-	}
-}
-
-int daemon_debug_opt;
-int daemon_debug_verbose;
-int daemon_quit;
-int cman_quorate;
-int our_nodeid;
-char *our_name;
-char daemon_debug_buf[256];
-char dump_buf[GROUPD_DUMP_SIZE];
-int dump_point;
-int dump_wrap;
-struct list_head gd_groups;
-struct list_head gd_levels[MAX_LEVELS];
-uint32_t gd_event_nr;
-int group_mode;
-
-int optd_groupd_compat;
-int optd_groupd_wait;
-int optd_groupd_mode_delay;
-int optd_debug_logfile;
-
-int cfgd_groupd_compat     = DEFAULT_GROUPD_COMPAT;
-int cfgd_groupd_wait       = DEFAULT_GROUPD_WAIT;
-int cfgd_groupd_mode_delay = DEFAULT_GROUPD_MODE_DELAY;
-int cfgd_debug_logfile     = DEFAULT_DEBUG_LOGFILE;
-
diff --git a/group/lib/Makefile b/group/lib/Makefile
deleted file mode 100644
index abd4336..0000000
--- a/group/lib/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-TARGET=libgroup
-
-MAKESTATICLIB = 1
-
-LIBDIRT=$(TARGET).a
-INCDIRT=$(TARGET).h
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/libs.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-include $(OBJDIR)/make/install.mk
-include $(OBJDIR)/make/uninstall.mk
-
-CFLAGS += -fPIC
-CFLAGS += -I$(S) -I$(S)/../daemon
-CFLAGS += -I${incdir}
diff --git a/group/lib/libgroup.c b/group/lib/libgroup.c
deleted file mode 100644
index c86ac25..0000000
--- a/group/lib/libgroup.c
+++ /dev/null
@@ -1,524 +0,0 @@
-#include <sys/types.h>
-#include <sys/un.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "groupd.h"
-#include "libgroup.h"
-
-#define LIBGROUP_MAGIC	0x67727570
-#define MAXARGS		100  /* FIXME */
-
-#define VALIDATE_HANDLE(h) \
-do { \
-	if (!(h) || (h)->magic != LIBGROUP_MAGIC) { \
-		errno = EINVAL; \
-		return -1; \
-	} \
-} while (0)
-
-enum {
-	DO_STOP = 1,
-	DO_START = 2,
-	DO_FINISH = 3,
-	DO_TERMINATE = 4,
-	DO_SET_ID = 5,
-	DO_DELIVER = 6,
-};
-
-
-/* if there's more data beyond the number of args we want, the return value
-   points to it */
-
-static char *get_args(char *buf, int *argc, char **argv, char sep, int want)
-{
-	char *p = buf, *rp = NULL;
-	int i;
-
-	argv[0] = p;
-
-	for (i = 1; i < MAXARGS; i++) {
-		p = strchr(buf, sep);
-		if (!p)
-			break;
-		*p = '\0';
-
-		if (want == i) {
-			rp = p + 1;
-			break;
-		}
-
-		argv[i] = p + 1;
-		buf = p + 1;
-	}
-	*argc = i;
-
-	/* we ended by hitting \0, return the point following that */
-	if (!rp)
-		rp = strchr(buf, '\0') + 1;
-
-	return rp;
-}
-
-static void get_nodeids(char *buf, int memb_count, int *nodeids)
-{
-	char *p;
-	int i, count = 0;
-
-	for (i = 0; ; i++) {
-		if (isdigit(buf[i]))
-			break;
-	}
-
-	buf = &buf[i];
-
-	for (i = 0; i < memb_count; i++) {
-
-		nodeids[count++] = atoi(buf);
-
-		p = strchr(buf, ' ');
-		if (!p)
-			break;
-
-		buf = p + 1;
-	}
-}
-
-static int get_action(char *buf)
-{
-	char act[16];
-	int i;
-
-	memset(act, 0, 16);
-
-	for (i = 0; i < 16; i++) {
-		if (isalnum(buf[i]))
-			act[i] = buf[i];
-		else
-			break;
-	}
-
-	if (!strncmp(act, "stop", 16))
-		return DO_STOP;
-
-	if (!strncmp(act, "start", 16))
-		return DO_START;
-
-	if (!strncmp(act, "finish", 16))
-		return DO_FINISH;
-
-	if (!strncmp(act, "terminate", 16))
-		return DO_TERMINATE;
-
-	if (!strncmp(act, "setid", 16))
-		return DO_SET_ID;
-
-	if (!strncmp(act, "deliver", 16))
-		return DO_DELIVER;
-
-	return -1;
-}
-
-static int do_write(int fd, void *buf, size_t count)
-{
-	int rv, off = 0;
-
- retry:
-	rv = write(fd, buf + off, count);
-	if (rv == -1 && errno == EINTR)
-		goto retry;
-	if (rv < 0)
-		return rv;
-
-	if (rv != count) {
-		count -= rv;
-		off += rv;
-		goto retry;
-	}
-	return 0;
-}
-
-static int do_read(int fd, void *buf, size_t count)
-{
-	int rv, off = 0;
-
-	while (off < count) {
-		rv = read(fd, buf + off, count - off);
-		if (rv == 0)
-			return -1;
-		if (rv == -1 && errno == EINTR)
-			continue;
-		if (rv == -1)
-			return -1;
-		off += rv;
-	}
-	return 0;
-}
-
-struct group_handle
-{
-	int magic;
-	int fd;
-	int level;
-	void *private;
-	group_callbacks_t cbs;
-	char prog_name[32];
-};
-
-static int _joinleave(group_handle_t handle, char *name, char *cmd)
-{
-	char buf[GROUPD_MSGLEN];
-	struct group_handle *h = (struct group_handle *) handle;
-	VALIDATE_HANDLE(h);
-
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "%s %s", cmd, name);
-
-	return do_write(h->fd, buf, GROUPD_MSGLEN);
-}
-
-int group_join(group_handle_t handle, char *name)
-{
-	return _joinleave(handle, name, "join");
-}
-
-int group_leave(group_handle_t handle, char *name)
-{
-	return _joinleave(handle, name, "leave");
-}
-
-int group_stop_done(group_handle_t handle, char *name)
-{
-	char buf[GROUPD_MSGLEN];
-	struct group_handle *h = (struct group_handle *) handle;
-	VALIDATE_HANDLE(h);
-
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "stop_done %s", name);
-
-	return do_write(h->fd, buf, GROUPD_MSGLEN);
-}
-
-int group_start_done(group_handle_t handle, char *name, int event_nr)
-{
-	char buf[GROUPD_MSGLEN];
-	struct group_handle *h = (struct group_handle *) handle;
-	VALIDATE_HANDLE(h);
-
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "start_done %s %d", name, event_nr);
-
-	return do_write(h->fd, buf, GROUPD_MSGLEN);
-}
-
-int group_send(group_handle_t handle, char *name, int len, char *data)
-{
-	char buf[GROUPD_MSGLEN];
-	int rv;
-	struct group_handle *h = (struct group_handle *) handle;
-	VALIDATE_HANDLE(h);
-
-	if (len > 2048 || len <= 0)
-		return -EINVAL;
-
-	memset(buf, 0, sizeof(buf));
-	rv = snprintf(buf, sizeof(buf), "send %s %d", name, len);
-	memcpy(buf + rv + 1, data, len);
-
-	return do_write(h->fd, buf, GROUPD_MSGLEN);
-}
-
-static int connect_groupd(void)
-{
-	struct sockaddr_un sun;
-	socklen_t addrlen;
-	int rv, fd;
-
-	fd = socket(PF_UNIX, SOCK_STREAM, 0);
-	if (fd < 0)
-		goto out;
-
-	memset(&sun, 0, sizeof(sun));
-	sun.sun_family = AF_UNIX;
-	strcpy(&sun.sun_path[1], GROUPD_SOCK_PATH);
-	addrlen = sizeof(sa_family_t) + strlen(sun.sun_path+1) + 1;
-
-	rv = connect(fd, (struct sockaddr *) &sun, addrlen);
-	if (rv < 0) {
-		close(fd);
-		fd = rv;
-	}
- out:
-	return fd;
-}
-
-group_handle_t group_init(void *private, char *prog_name, int level,
-			  group_callbacks_t *cbs, int timeout)
-{
-	struct group_handle *h;
-	char buf[GROUPD_MSGLEN];
-	int rv, saved_errno, i;
-
-	h = malloc(sizeof(struct group_handle));
-	if (!h)
-		return NULL;
-
-	h->magic = LIBGROUP_MAGIC;
-	h->private = private;
-	h->cbs = *cbs;
-	h->level = level;
-	strncpy(h->prog_name, prog_name, 32);
-
-	for (i = 0; !timeout || i < timeout * 2; i++) {
-		h->fd = connect_groupd();
-		if (h->fd > 0 || !timeout)
-			break;
-		usleep(500000);
-	}
-
-	if (h->fd <= 0)
-		goto fail;
-
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "setup %s %d", prog_name, level);
-
-	rv = do_write(h->fd, &buf, GROUPD_MSGLEN);
-	if (rv < 0)
-		goto fail;
-
-	return (group_handle_t) h;
-
- fail:
-	saved_errno = errno;
-	close(h->fd);
-	free(h);
-	h = NULL;
-	errno = saved_errno;
-	return NULL;
-}
-
-int group_exit(group_handle_t handle)
-{
-	struct group_handle *h = (struct group_handle *) handle;
-	VALIDATE_HANDLE(h);
-	h->magic = 0;
-	close(h->fd);
-	free(h);
-	return 0;
-}
-
-int group_get_fd(group_handle_t handle)
-{
-	struct group_handle *h = (struct group_handle *) handle;
-	VALIDATE_HANDLE(h);
-	return h->fd;
-}
-
-/* Format of string messages we receive from groupd:
-
-   "stop <name>"
-   
-      name = the name of the group (same for rest)
-
-   "start <name> <event_nr> <type> <memb_count> <memb0> <memb1>..."
-
-      event_nr = used to later match finish/terminate
-      type = 1/GROUP_NODE_FAILED, 2/GROUP_NODE_JOIN, 3/GROUP_NODE_LEAVE
-      memb_count = the number of group members
-      memb0... = the nodeids of the group members
-
-   "finish <name> <event_nr>"
-   
-      event_nr = matches the start event that's finishing
-
-   "terminate <name> <event_nr>"
-
-      event_nr = matches the start event that's being canceled
-
-   "setid <name> <id>"
-
-      id = the global id of the group
-
-   "deliver <name> <nodeid> <len>"<data>
-
-      nodeid = who sent the message
-      len = length of the message
-      data = the message
-*/
-
-int group_dispatch(group_handle_t handle)
-{
-	char buf[GROUPD_MSGLEN], *argv[MAXARGS];
-	char *p;
-	int act, argc, rv, count, *nodeids;
-	struct group_handle *h = (struct group_handle *) handle;
-	VALIDATE_HANDLE(h);
-
-	memset(buf, 0, sizeof(buf));
-
-	rv = do_read(h->fd, &buf, GROUPD_MSGLEN);
-	if (rv < 0)
-		goto out;
-
-	act = get_action(buf);
-
-	switch (act) {
-
-	case DO_STOP:
-		get_args(buf, &argc, argv, ' ', 2);
-
-		h->cbs.stop(h, h->private, argv[1]);
-		break;
-
-	case DO_START:
-		p = get_args(buf, &argc, argv, ' ', 5);
-
-		count = atoi(argv[4]);
-		nodeids = malloc(count * sizeof(int));
-		if (!nodeids) {
-			rv = -ENOMEM;
-			goto out;
-		}
-		get_nodeids(p, count, nodeids);
-
-		h->cbs.start(h, h->private, argv[1], atoi(argv[2]),
-			     atoi(argv[3]), count, nodeids);
-
-		free(nodeids);
-		break;
-
-	case DO_FINISH:
-		get_args(buf, &argc, argv, ' ', 3);
-
-		h->cbs.finish(h, h->private, argv[1], atoi(argv[2]));
-		break;
-
-	case DO_TERMINATE:
-		get_args(buf, &argc, argv, ' ', 3);
-
-		/* FIXME: why aren't we passing event_nr, argv[2], through? */
-
-		h->cbs.terminate(h, h->private, argv[1]);
-		break;
-
-	case DO_SET_ID:
-		get_args(buf, &argc, argv, ' ', 3);
-
-		h->cbs.set_id(h, h->private, argv[1],
-			      (unsigned int) strtoul(argv[2], NULL, 10));
-		break;
-
-	case DO_DELIVER:
-		p = get_args(buf, &argc, argv, ' ', 4);
-
-		h->cbs.deliver(h, h->private, argv[1], atoi(argv[2]),
-			       atoi(argv[3]), p);
-		break;
-	}
-
-	rv = 0;
- out:
-	return rv;
-}
-
-int group_get_groups(int max, int *count, group_data_t *data)
-{
-	char buf[GROUPD_MSGLEN];
-	group_data_t dbuf, empty;
-	int fd, rv;
-
-	*count = 0;
-
-	fd = connect_groupd();
-	if (fd < 0)
-		return fd;
-
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "get_groups %d", max);
-
-	rv = do_write(fd, &buf, GROUPD_MSGLEN);
-	if (rv < 0)
-		goto out;
-
-	memset(&empty, 0, sizeof(empty));
-
-	while (1) {
-		memset(&dbuf, 0, sizeof(dbuf));
-
-		rv = do_read(fd, &dbuf, sizeof(group_data_t));
-		if (rv < 0)
-			break;
-
-		if (!memcmp(&dbuf, &empty, sizeof(group_data_t))) {
-			rv = 0;
-			break;
-		} else {
-			memcpy(&data[*count], &dbuf, sizeof(group_data_t));
-			(*count)++;
-		}
-	}
- out:
-	close(fd);
-	return rv;
-}
-
-int group_get_group(int level, const char *name, group_data_t *data)
-{
-	char buf[GROUPD_MSGLEN];
-	char data_buf[sizeof(group_data_t)];
-	int fd, rv;
-
-	fd = connect_groupd();
-	if (fd < 0)
-		 return fd;
-
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "get_group %d %s", level, name);
-
-	rv = do_write(fd, &buf, GROUPD_MSGLEN);
-	if (rv < 0)
-		 goto out;
-
-	rv = do_read(fd, &data_buf, sizeof(data_buf));
-	if (rv < 0)
-		 goto out;
-
-	memcpy(data, data_buf, sizeof(group_data_t));
-	rv = 0;
- out:
-	close(fd);
-	return rv;
-}
-
-int group_get_version(int *version)
-{
-	char buf[GROUPD_MSGLEN];
-	int fd, rv;
-
-	fd = connect_groupd();
-	if (fd < 0)
-		 return fd;
-
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "get_version");
-
-	rv = do_write(fd, &buf, GROUPD_MSGLEN);
-	if (rv < 0)
-		 goto out;
-
-	rv = do_read(fd, version, sizeof(int));
-	if (rv < 0)
-		 goto out;
-	rv = 0;
- out:
-	close(fd);
-	return rv;
-}
-
diff --git a/group/lib/libgroup.h b/group/lib/libgroup.h
deleted file mode 100644
index 82ef7e1..0000000
--- a/group/lib/libgroup.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef _LIBGROUP_H_
-#define _LIBGROUP_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MAX_GROUP_MEMBERS	256
-#define MAX_GROUP_NAME_LEN	32
-
-/* these need to match what's in groupd.h */
-#define GROUP_NODE_FAILED	1
-#define GROUP_NODE_JOIN		2
-#define GROUP_NODE_LEAVE	3
-
-typedef void *group_handle_t;
-
-typedef void (*group_stop_t)(group_handle_t h, void *priv, char *name);
-typedef void (*group_start_t)(group_handle_t h, void *priv, char *name,
-			      int event_nr, int type, int member_count,
-			      int *members);
-typedef void (*group_finish_t)(group_handle_t h, void *priv, char *name,
-			       int event_nr);
-typedef void (*group_terminate_t)(group_handle_t h, void *priv, char *name);
-typedef void (*group_set_id_t)(group_handle_t h, void *priv, char *name,
-			       unsigned int id);
-typedef void (*group_deliver_t)(group_handle_t h, void *priv, char *name,
-			        int nodeid, int len, char *buf);
-
-typedef struct {
-	group_stop_t stop;
-	group_start_t start;
-	group_finish_t finish;
-	group_terminate_t terminate;
-	group_set_id_t set_id;
-	group_deliver_t deliver;
-} group_callbacks_t;
-
-group_handle_t group_init(void *priv, char *prog_name, int level, group_callbacks_t *cbs, int timeout);
-int group_exit(group_handle_t handle);
-
-int group_join(group_handle_t handle, char *name);
-int group_leave(group_handle_t handle, char *name);
-int group_stop_done(group_handle_t handle, char *name);
-int group_start_done(group_handle_t handle, char *name, int event_nr);
-int group_get_fd(group_handle_t handle);
-int group_dispatch(group_handle_t handle);
-int group_send(group_handle_t handle, char *name, int len, char *buf);
-
-
-/*
- * Querying for group information
- */
-
-typedef struct group_data {
-	char client_name[32+1];
-	char name[MAX_GROUP_NAME_LEN+1];
-	int level;
-	unsigned int id;
-	int member;
-	int member_count;
-	int members[MAX_GROUP_MEMBERS];
-	int event_state;
-	int event_nodeid;
-	int event_local_status;
-	uint64_t event_id;
-} group_data_t;
-
-/* These routines create their own temporary connection to groupd so they
-   don't interfere with dispatchable callback messages. */
-
-int group_get_groups(int max, int *count, group_data_t *data);
-int group_get_group(int level, const char *name, group_data_t *data);
-
-int group_get_version(int *version);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/group/man/groupd.8 b/group/man/groupd.8
deleted file mode 100644
index 634d0a0..0000000
--- a/group/man/groupd.8
+++ /dev/null
@@ -1,43 +0,0 @@
-.TH groupd 8
-
-.SH NAME
-groupd - the group manager for fenced, dlm_controld and gfs_controld
-
-.SH SYNOPSIS
-.B
-groupd
-[\fIOPTION\fR]...
-
-.SH DESCRIPTION
-
-The group daemon, groupd, provides a compatibility layer between the
-openais closed process group (CPG) service and the fenced, dlm_controld
-and gfs_controld daemons.  groupd and its associated libgroup interface
-will go away in the future as the fencing, dlm and gfs daemons are ported
-to use the libcpg interfaces directly.  groupd translates and buffers cpg
-events between openais's cpg service and the fence/dlm/gfs systems that
-use it.  CPG's are used to represent the membership of the fence domain,
-dlm lockspaces and gfs mount groups.
-
-groupd is also a convenient place to query the status of the fence, dlm
-and gfs groups.  This is done by the group_tool program.
-
-
-.SH OPTIONS
-.TP
-\fB-D\fP
-Run the daemon in the foreground and print debug statements to stdout.
-.TP
-\fB-V\fP
-Print the version information and exit.
-.TP
-\fB-h\fP 
-Print out a help message describing available options, then exit.
-
-.SH DEBUGGING
-The groupd daemon keeps a circular buffer of debug messages that can be
-dumped with the 'group_tool dump' command.
-
-.SH SEE ALSO
-group_tool(8)
-
diff --git a/group/test/Makefile b/group/test/Makefile
deleted file mode 100644
index 3a91013..0000000
--- a/group/test/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-TARGETS= client clientd
-
-all: $(TARGETS)
-
-include ../../make/defines.mk
-include $(OBJDIR)/make/cobj.mk
-include $(OBJDIR)/make/clean.mk
-
-CFLAGS += -I${incdir}
-
-LDFLAGS += -L${libdir}
-
-%: %.o
-	$(CC) -o $@ $^ $(LDFLAGS)
-
-clean: generalclean
diff --git a/group/test/client.c b/group/test/client.c
deleted file mode 100644
index a9a3930..0000000
--- a/group/test/client.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-
-
-#define COMMAND_SOCK_PATH "command_socket"
-
-
-int main(int argc, char *argv[])
-{
-	int s, i, rv;
-	struct sockaddr_un addr;
-	socklen_t addrlen;
-	char buf[256];
-
-	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
-	if (s < 0) {
-		printf("socket error %d errno %d\n", s, errno);
-		exit(-1);
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = AF_LOCAL;
-	strcpy(&addr.sun_path[1], COMMAND_SOCK_PATH);
-	addrlen = sizeof(sa_family_t) + strlen(addr.sun_path+1) + 1;
-
-	memset(buf, 0, 256);
-
-	for (i = 1; i < argc; i++) {
-		if (i != 1)
-			strcat(buf, " ");
-		strcat(buf, argv[i]);
-	}
-
-
-	rv = sendto(s, buf, strlen(buf), 0, (struct sockaddr *)&addr, addrlen);
-
-	printf("send %d \"%s\"\n", rv, buf);
-	return 0;
-}
-
diff --git a/group/test/clientd.c b/group/test/clientd.c
deleted file mode 100644
index 9f344f4..0000000
--- a/group/test/clientd.c
+++ /dev/null
@@ -1,179 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <asm/types.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include <sys/un.h>
-#include <linux/netlink.h> 
-
-#define GROUPD_SOCK_PATH "groupd_socket"
-#define COMMAND_SOCK_PATH "command_socket"
-
-#define MAXLINE 256
-#define MAXCON  4
-
-#define log_error(fmt, args...) fprintf(stderr, fmt "\n", ##args)
-
-int groupd_fd;
-int command_fd;
-struct sockaddr_un sun;
-struct sockaddr_un addr;
-socklen_t addrlen;
-
-
-void process_groupd(void)
-{
-	char buf[MAXLINE];
-	int rv;
-
-	memset(buf, 0, sizeof(buf));
-
-	rv = read(groupd_fd, &buf, sizeof(buf));
-	if (rv < 0) {
-		log_error("read error %d errno %d", rv, errno);
-		return;
-	}
-
-	printf("I: groupd read:   %s\n", buf);
-}
-
-void process_command(void)
-{
-	char buf[MAXLINE];
-	int rv;
-
-	memset(buf, 0, sizeof(buf));
-
-	rv = recvfrom(command_fd, buf, MAXLINE, 0, (struct sockaddr *) &addr,
-		      &addrlen);
-
-	printf("I: command recv:  %s\n", buf);
-
-	rv = write(groupd_fd, buf, strlen(buf));
-	if (rv < 0)
-		log_error("groupd write error");
-
-	printf("O: command write: %s\n", buf);
-}
-
-void process_input(int fd)
-{
-	if (fd == groupd_fd)
-		process_groupd();
-	else if (fd == command_fd)
-		process_command();
-}
-
-void process_hup(int fd)
-{
-	if (fd == groupd_fd)
-		close(groupd_fd);
-	else if (fd == command_fd)
-		close(command_fd);
-}
-
-int setup_groupd(void)
-{
-	char buf[] = "setup test 1";
-	int rv;
-
-	rv = write(groupd_fd, &buf, strlen(buf));
-	if (rv < 0) {
-		log_error("write error %d errno %d %s", rv, errno, buf);
-		return -1;
-	}
-	return 0;
-}
-
-int loop(void)
-{
-	struct pollfd *pollfd;
-	int s, rv, i, maxi;
-
-
-	pollfd = malloc(MAXCON * sizeof(struct pollfd));
-	if (!pollfd)
-		return -1;
-
-
-	/* connect to the groupd server */
-
-	s = socket(AF_LOCAL, SOCK_STREAM, 0);
-	if (s < 0) {
-		log_error("socket");
-		exit(1);
-	}
-
-	memset(&sun, 0, sizeof(sun));
-	sun.sun_family = AF_LOCAL;
-	strcpy(&sun.sun_path[1], GROUPD_SOCK_PATH);
-	addrlen = sizeof(sa_family_t) + strlen(sun.sun_path+1) + 1;
-
-	rv = connect(s, (struct sockaddr *) &sun, addrlen);
-	if (rv < 0) {
-		log_error("groupd connect error %d errno %d", rv, errno);
-		exit(1);
-	}
-
-	groupd_fd = s;
-	pollfd[0].fd = s;
-	pollfd[0].events = POLLIN;
-
-
-	/* get commands via another local socket */
-
-	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
-	if (s < 0) {
-		log_error("socket");
-		exit(1);
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = AF_LOCAL;
-	strcpy(&addr.sun_path[1], COMMAND_SOCK_PATH);
-	addrlen = sizeof(sa_family_t) + strlen(addr.sun_path+1) + 1;
-
-	rv = bind(s, (struct sockaddr *) &addr, addrlen);
-	if (rv < 0) {
-		log_error("bind error");
-		exit(1);
-	}
-
-	command_fd = s;
-	pollfd[1].fd = s;
-	pollfd[1].events = POLLIN;
-
-	maxi = 1;
-
-	rv = setup_groupd();
-	if (rv < 0) {
-		log_error("setup_groupd");
-		exit(1);
-	}
-
-	for (;;) {
-		rv = poll(pollfd, maxi + 1, -1);
-		if (rv < 0)
-			log_error("poll");
-
-		for (i = 0; i <= maxi; i++) {
-			if (pollfd[i].revents & (POLLHUP | POLLERR | POLLNVAL)) {
-				process_hup(pollfd[i].fd);
-			} else if (pollfd[i].revents & POLLIN) {
-				process_input(pollfd[i].fd);
-			}
-		}
-	}
-
-	free(pollfd);
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	return loop();
-}
-
diff --git a/group/tool/Makefile b/group/tool/Makefile
index ba5d960..191e4cc 100644
--- a/group/tool/Makefile
+++ b/group/tool/Makefile
@@ -2,7 +2,7 @@ TARGET= group_tool
 
 SBINDIRT=$(TARGET)
 
-all: depends ${TARGET}
+all: ${TARGET}
 
 include ../../make/defines.mk
 include $(OBJDIR)/make/cobj.mk
@@ -12,27 +12,12 @@ include $(OBJDIR)/make/uninstall.mk
 
 OBJS=	main.o
 
-CFLAGS += -I$(S) -I$(S)/../daemon/ -I$(S)/../lib/
-CFLAGS += -I${dlmcontrolincdir}
-CFLAGS += -I$(S)/../../fence/libfenced
-CFLAGS += -I$(S)/../libgfscontrol
+CFLAGS += -I$(S)
 CFLAGS += -I${incdir}
-CFLAGS += -I${KERNEL_SRC}/include/
 
-LDFLAGS += -L${dlmcontrollibdir} -ldlmcontrol
-LDFLAGS += -L../lib -lgroup
-LDFLAGS += -L../../fence/libfenced -lfenced
-LDFLAGS += -L../libgfscontrol -lgfscontrol
 LDFLAGS += -L${libdir}
 
-LDDEPS += ../lib/libgroup.a
-LDDEPS += ../libgfscontrol/libgfscontrol.a
-LDDEPS += ../../fence/libfenced/libfenced.a
-
-${TARGET}: ${OBJS} ${LDDEPS}
+${TARGET}: ${OBJS}
 	$(CC) -o $@ $^ $(LDFLAGS)
 
-depends:
-	$(MAKE) -C ../lib all
-
 clean: generalclean
diff --git a/group/tool/main.c b/group/tool/main.c
index e1d911c..351e1b6 100644
--- a/group/tool/main.c
+++ b/group/tool/main.c
@@ -11,71 +11,17 @@
 #include <errno.h>
 #include <limits.h>
 #include <netinet/in.h>
-#include <linux/dlmconstants.h>
 
-#include "libgroup.h"
-#include "groupd.h"
-#include "libfenced.h"
-#include "libdlmcontrol.h"
-#include "libgfscontrol.h"
 #include "copyright.cf"
 
-#define GROUP_LIBGROUP			2
-#define GROUP_LIBCPG			3
-
-#define MAX_NODES			128
-#define MAX_LS				128
-#define MAX_MG				128
-#define MAX_GROUPS			128
-
 #define OP_LIST				1
 #define OP_DUMP				2
-#define OP_LOG				3
 
 static char *prog_name;
 static int operation;
 static int opt_ind;
 static int verbose;
-static int all_daemons;
 static int ls_all_nodes;
-static int print_header_done;
-
-
-static int do_write(int fd, void *buf, size_t count)
-{
-	int rv, off = 0;
-
- retry:
-	rv = write(fd, buf + off, count);
-	if (rv == -1 && errno == EINTR)
-		goto retry;
-	if (rv < 0)
-		return rv;
-
-	if (rv != count) {
-		count -= rv;
-		off += rv;
-		goto retry;
-	}
-	return 0;
-}
-
-static int do_read(int fd, void *buf, size_t count)
-{
-	int rv, off = 0;
-
-	while (off < count) {
-		rv = read(fd, buf + off, count - off);
-		if (rv == 0)
-			return -1;
-		if (rv == -1 && errno == EINTR)
-			continue;
-		if (rv == -1)
-			return -1;
-		off += rv;
-	}
-	return 0;
-}
 
 static void print_usage(void)
 {
@@ -84,29 +30,19 @@ static void print_usage(void)
 	printf("%s [options] [ls|dump]\n", prog_name);
 	printf("\n");
 	printf("Options:\n");
-	printf("  -v               Verbose output, extra event information\n");
-	printf("  -a               fence_tool ls; dlm_tool ls; gfs_control ls\n");
-	printf("  -n               Show all node information with -a\n");
+	printf("  -v               Verbose output, extra information\n");
+	printf("  -n               Show all node information\n");
 	printf("  -h               Print this help, then exit\n");
 	printf("  -V               Print program version information, then exit\n");
 	printf("\n");
-	printf("Display group information from groupd\n");
-	printf("ls                 Show information for all groups\n");
-	printf("ls <level> <name>  Show information one group.  If\n");
-	printf("                   we are not a member of the group,\n");
-	printf("                   return 1.\n");
-	printf("\n");
 	printf("Display debugging information\n");
-	printf("dump               Show debug log from groupd\n");
 	printf("dump fence         Show debug log from fenced\n");
+	printf("dump dlm           Show debug log from dlm_controld\n");
 	printf("dump gfs           Show debug log from gfs_controld\n");
-	printf("dump plocks <name> Show posix locks for gfs with given name\n");
-	printf("\n");
-	printf("log <comments>     Add information to the groupd log.\n");
 	printf("\n");
 }
 
-#define OPTION_STRING "ahVvn"
+#define OPTION_STRING "hVvn"
 
 static void decode_arguments(int argc, char **argv)
 {
@@ -117,10 +53,6 @@ static void decode_arguments(int argc, char **argv)
 		optchar = getopt(argc, argv, OPTION_STRING);
 
 		switch (optchar) {
-		case 'a':
-			all_daemons = 1;
-			break;
-
 		case 'n':
 			ls_all_nodes = 1;
 			break;
@@ -168,10 +100,6 @@ static void decode_arguments(int argc, char **argv)
 			operation = OP_LIST;
 			opt_ind = optind + 1;
 			break;
-		} else if (strcmp(argv[optind], "log") == 0) {
-			operation = OP_LOG;
-			opt_ind = optind + 1;
-			break;
 		}
 		optind++;
 	}
@@ -180,565 +108,36 @@ static void decode_arguments(int argc, char **argv)
 		operation = OP_LIST;
 }
 
-/* copied from grouip/daemon/gd_internal.h, must keep in sync */
-
-#define EST_JOIN_BEGIN         1
-#define EST_JOIN_STOP_WAIT     2
-#define EST_JOIN_ALL_STOPPED   3
-#define EST_JOIN_START_WAIT    4
-#define EST_JOIN_ALL_STARTED   5
-#define EST_LEAVE_BEGIN        6
-#define EST_LEAVE_STOP_WAIT    7
-#define EST_LEAVE_ALL_STOPPED  8
-#define EST_LEAVE_START_WAIT   9
-#define EST_LEAVE_ALL_STARTED 10
-#define EST_FAIL_BEGIN        11
-#define EST_FAIL_STOP_WAIT    12
-#define EST_FAIL_ALL_STOPPED  13
-#define EST_FAIL_START_WAIT   14
-#define EST_FAIL_ALL_STARTED  15
-
-char *ev_state_str(state)
-{
-	switch (state) {
-	case EST_JOIN_BEGIN:
-		return "JOIN_BEGIN";
-	case EST_JOIN_STOP_WAIT:
-		return "JOIN_STOP_WAIT";
-	case EST_JOIN_ALL_STOPPED:
-		return "JOIN_ALL_STOPPED";
-	case EST_JOIN_START_WAIT:
-		return "JOIN_START_WAIT";
-	case EST_JOIN_ALL_STARTED:
-		return "JOIN_ALL_STARTED";
-	case EST_LEAVE_BEGIN:
-		return "LEAVE_BEGIN";
-	case EST_LEAVE_STOP_WAIT:
-		return "LEAVE_STOP_WAIT";
-	case EST_LEAVE_ALL_STOPPED:
-		return "LEAVE_ALL_STOPPED";
-	case EST_LEAVE_START_WAIT:
-		return "LEAVE_START_WAIT";
-	case EST_LEAVE_ALL_STARTED:
-		return "LEAVE_ALL_STARTED";
-	case EST_FAIL_BEGIN:
-		return "FAIL_BEGIN";
-	case EST_FAIL_STOP_WAIT:
-		return "FAIL_STOP_WAIT";
-	case EST_FAIL_ALL_STOPPED:
-		return "FAIL_ALL_STOPPED";
-	case EST_FAIL_START_WAIT:
-		return "FAIL_START_WAIT";
-	case EST_FAIL_ALL_STARTED:
-		return "FAIL_ALL_STARTED";
-	default:
-		return "unknown";
-	}
-}
-
-char *state_str(group_data_t *data)
-{
-	static char buf[128];
-	
-	memset(buf, 0, sizeof(buf));
-
-	if (!data->event_state && !data->event_nodeid)
-		sprintf(buf, "none");
-	else if (verbose)
-		snprintf(buf, 127, "%s %d %llx %d",
-			 ev_state_str(data->event_state),
-			 data->event_nodeid,
-			 (unsigned long long)data->event_id,
-			 data->event_local_status);
-	else
-		snprintf(buf, 127, "%s", ev_state_str(data->event_state));
-
-	return buf;
-}
-
-static int data_compare(const void *va, const void *vb)
-{
-	const group_data_t *a = va;
-	const group_data_t *b = vb;
-	return a->level - b->level;
-}
-
-static int member_compare(const void *va, const void *vb)
-{
-	const int *a = va;
-	const int *b = vb;
-	return *a - *b;
-}
-
-static int groupd_list(int argc, char **argv)
-{
-	group_data_t data[MAX_GROUPS];
-	int i, j, rv, count = 0, level, ret = 0;
-	char *name, *state_header;
-	int type_width = 16;
-	int level_width = 5;
-	int name_width = 32;
-	int id_width = 8;
-	int state_width = 12;
-	int len, max_name = 4;
-
-	memset(&data, 0, sizeof(data));
-
-	if (opt_ind && opt_ind < argc) {
-		level = atoi(argv[opt_ind++]);
-		name = argv[opt_ind];
-
-		rv = group_get_group(level, name, data);
-		count = 1;
-
-		/* don't output if there's no group at all */
-		if (data[0].id == 0) {
-			fprintf(stderr, "groupd has no information about "
-			        "the specified group\n");
-			return 1;
-		}
-		/* If we wanted a specific group but we are not
-		   joined, print it out - but return failure to
-		   the caller */
-		if (data[0].member != 1)
-			ret = 1;
-	} else
-		rv = group_get_groups(MAX_GROUPS, &count, data);
-
-	if (rv < 0)
-		return rv;
-
-	if (!count)
-		return 0;
-
-	for (i = 0; i < count; i++) {
-		len = strlen(data[i].name);
-		if (len > max_name)
-			max_name = len;
-	}
-	name_width = max_name + 1;
-
-	if (verbose)
-		state_header = "state node id local_done";
-	else
-		state_header = "state";
-			
-	qsort(&data, count, sizeof(group_data_t), data_compare);
-
-	for (i = 0; i < count; i++) {
-		if (!i)
-			printf("%-*s %-*s %-*s %-*s %-*s\n",
-			       type_width, "type",
-			       level_width, "level",
-			       name_width, "name",
-			       id_width, "id",
-			       state_width, state_header);
-
-		printf("%-*s %-*d %-*s %0*x %-*s\n",
-			type_width, data[i].client_name,
-			level_width, data[i].level,
-			name_width, data[i].name,
-			id_width, data[i].id,
-			state_width, state_str(&data[i]));
-
-		qsort(&data[i].members, data[i].member_count,
-		      sizeof(int), member_compare);
-
-		printf("[");
-		for (j = 0; j < data[i].member_count; j++) {
-			if (j != 0)
-				printf(" ");
-			printf("%d", data[i].members[j]);
-		}
-		printf("]\n");
-	}
-	return ret;
-}
-
-static int fenced_node_compare(const void *va, const void *vb)
-{
-	const struct fenced_node *a = va;
-	const struct fenced_node *b = vb;
-
-	return a->nodeid - b->nodeid;
-}
-
-static void print_header(void)
-{
-	if (print_header_done)
-		return;
-	print_header_done = 1;
-
-	printf("type         level name             id       state\n");
-}
-
-static void fenced_list(void)
-{
-	struct fenced_domain d;
-	struct fenced_node nodes[MAX_NODES];
-	struct fenced_node *np;
-	int node_count;
-	int rv, j;
-
-	rv = fenced_domain_info(&d);
-	if (rv < 0)
-		return;
-
-	print_header();
-
-	printf("fence        0     %-*s %08x %d\n",
-	       16, "default", 0, d.state);
-
-	node_count = 0;
-	memset(&nodes, 0, sizeof(nodes));
-
-	rv = fenced_domain_nodes(FENCED_NODES_MEMBERS, MAX_NODES,
-				 &node_count, nodes);
-	if (rv < 0 || !node_count)
-		goto do_nodeids;
-
-	qsort(&nodes, node_count, sizeof(struct fenced_node),
-	      fenced_node_compare);
-
- do_nodeids:
-	printf("[");
-	np = nodes;
-	for (j = 0; j < node_count; j++) {
-		if (j)
-			printf(" ");
-		printf("%d", np->nodeid);
-		np++;
-	}
-	printf("]\n");
-}
-
-static int dlmc_node_compare(const void *va, const void *vb)
-{
-	const struct dlmc_node *a = va;
-	const struct dlmc_node *b = vb;
-
-	return a->nodeid - b->nodeid;
-}
-
-static void dlm_controld_list(void)
-{
-	struct dlmc_lockspace lss[MAX_LS];
-	struct dlmc_node nodes[MAX_NODES];
-	struct dlmc_node *np;
-	struct dlmc_lockspace *ls;
-	char *name = NULL;
-	int node_count;
-	int ls_count;
-	int rv;
-	int i, j;
-
-	memset(lss, 0, sizeof(lss));
-
-	if (name) {
-		rv = dlmc_lockspace_info(name, lss);
-		if (rv < 0)
-			return;
-		ls_count = 1;
-	} else {
-		rv = dlmc_lockspaces(MAX_LS, &ls_count, lss);
-		if (rv < 0)
-			return;
-	}
-
-	for (i = 0; i < ls_count; i++) {
-		ls = &lss[i];
-
-		if (!i)
-			print_header();
-
-		printf("dlm          1     %-*s %08x %x\n",
-			16, ls->name, ls->global_id, ls->flags);
-
-		node_count = 0;
-		memset(&nodes, 0, sizeof(nodes));
-
-		rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_MEMBERS,
-					  MAX_NODES, &node_count, nodes);
-		if (rv < 0 || !node_count)
-			goto do_nodeids;
-
-		qsort(nodes, node_count, sizeof(struct dlmc_node),
-		      dlmc_node_compare);
-
- do_nodeids:
-		printf("[");
-		np = nodes;
-		for (j = 0; j < node_count; j++) {
-			if (j)
-				printf(" ");
-			printf("%d", np->nodeid);
-			np++;
-		}
-		printf("]\n");
-	}
-}
-
-static int gfsc_node_compare(const void *va, const void *vb)
-{
-	const struct gfsc_node *a = va;
-	const struct gfsc_node *b = vb;
-
-	return a->nodeid - b->nodeid;
-}
-
-static void gfs_controld_list(void)
-{
-	struct gfsc_mountgroup mgs[MAX_MG];
-	struct gfsc_node nodes[MAX_NODES];
-	struct gfsc_node *np;
-	struct gfsc_mountgroup *mg;
-	char *name = NULL;
-	int node_count;
-	int mg_count;
-	int rv;
-	int i, j;
-
-	memset(mgs, 0, sizeof(mgs));
-
-	if (name) {
-		rv = gfsc_mountgroup_info(name, mgs);
-		if (rv < 0)
-			return;
-		mg_count = 1;
-	} else {
-		rv = gfsc_mountgroups(MAX_MG, &mg_count, mgs);
-		if (rv < 0)
-			return;
-	}
-
-	for (i = 0; i < mg_count; i++) {
-		mg = &mgs[i];
-
-		if (!i)
-			print_header();
-
-		printf("gfs          2     %-*s %08x %x\n",
-			16, mg->name, mg->global_id, mg->flags);
-
-		node_count = 0;
-		memset(&nodes, 0, sizeof(nodes));
-
-		rv = gfsc_mountgroup_nodes(mg->name, GFSC_NODES_MEMBERS,
-					   MAX_NODES, &node_count, nodes);
-		if (rv < 0 || !node_count)
-			goto do_nodeids;
-
-		qsort(nodes, node_count, sizeof(struct gfsc_node),
-		      gfsc_node_compare);
-
- do_nodeids:
-		printf("[");
-		np = nodes;
-		for (j = 0; j < node_count; j++) {
-			if (j)
-				printf(" ");
-			printf("%d", np->nodeid);
-			np++;
-		}
-		printf("]\n");
-	}
-}
-
-static int connect_daemon(char *path)
-{
-	struct sockaddr_un sun;
-	socklen_t addrlen;
-	int rv, fd;
-
-	fd = socket(PF_UNIX, SOCK_STREAM, 0);
-	if (fd < 0)
-		goto out;
-
-	memset(&sun, 0, sizeof(sun));
-	sun.sun_family = AF_UNIX;
-	strcpy(&sun.sun_path[1], path);
-	addrlen = sizeof(sa_family_t) + strlen(sun.sun_path+1) + 1;
-
-	rv = connect(fd, (struct sockaddr *) &sun, addrlen);
-	if (rv < 0) {
-		close(fd);
-		fd = rv;
-	}
- out:
-	return fd;
-}
-
-static void groupd_dump_debug(int argc, char **argv, char *inbuf)
-{
-	char outbuf[GROUPD_MSGLEN];
-	int rv, fd;
-
-	fd = connect_daemon(GROUPD_SOCK_PATH);
-	if (fd < 0)
-		return;
-
-	memset(outbuf, 0, sizeof(outbuf));
-	sprintf(outbuf, "dump");
-
-	rv = do_write(fd, outbuf, sizeof(outbuf));
-	if (rv < 0) {
-		printf("dump write error %d errno %d\n", rv, errno);
-		return;
-	}
-
-	do_read(fd, inbuf, GROUPD_DUMP_SIZE);
-
-	close(fd);
-}
-
-static int do_log(char *comment)
-{
-	char buf[GROUPD_MSGLEN];
-	int fd, rv;
-
-	fd = connect_daemon(GROUPD_SOCK_PATH);
-	if (fd < 0)
-		return fd;
-	memset(buf, 0, sizeof(buf));
-	snprintf(buf, sizeof(buf), "log %s", comment);
-	rv = write(fd, &buf, GROUPD_MSGLEN);
-	close(fd);
-	return rv;
-}
-
 int main(int argc, char **argv)
 {
-	int rv, version = 0; 
-
 	prog_name = argv[0];
 	decode_arguments(argc, argv);
 
 	switch (operation) {
 	case OP_LIST:
-
-		rv = group_get_version(&version);
-		if (rv < 0)
-			version = -1;
-
-		switch (version) {
-		case -1:
-			printf("groupd not running\n");
-			break;
-		case -EAGAIN:
-			printf("groupd compatibility mode 2 (pending)\n");
-			break;
-		case GROUP_LIBGROUP:
-			printf("groupd compatibility mode 1\n");
-			break;
-		case GROUP_LIBCPG:
-			printf("groupd compatibility mode 0\n");
-			break;
-		default:
-			printf("groupd compatibility mode %d\n", version);
-			break;
-		}
-
-		if (all_daemons) {
-			/* show the new cluster3 data (from daemons) in
-			   the new daemon-specific format */
-
-			if (verbose || ls_all_nodes) {
-				system("fence_tool ls -n");
-				system("dlm_tool ls -n");
-				system("gfs_control ls -n");
-			} else {
-				system("fence_tool ls");
-				system("dlm_tool ls");
-				system("gfs_control ls");
-			}
-
-			if (version == GROUP_LIBGROUP)
-				printf("Run 'group_tool ls' for groupd information.\n");
-
+		if (verbose || ls_all_nodes) {
+			system("fence_tool ls -n");
+			system("dlm_tool ls -n");
+			system("gfs_control ls -n");
 		} else {
-			if (version == GROUP_LIBGROUP) {
-				/* show the same old cluster2 data (from groupd)
-				   in the same old format as cluster2 */
-
-				groupd_list(argc, argv);
-
-			} else if (version == GROUP_LIBCPG || version == -1) {
-				/* show the new cluster3 data (from daemons)
-				   in the (nearly) same old format as cluster2 */
-
-				fenced_list();
-				dlm_controld_list();
-				gfs_controld_list();
-
-				printf("Run 'group_tool ls -a' for daemon information.\n");
-			}
+			system("fence_tool ls");
+			system("dlm_tool ls");
+			system("gfs_control ls");
 		}
 		break;
 
 	case OP_DUMP:
 		if (opt_ind && opt_ind < argc) {
-			if (!strncmp(argv[opt_ind], "gfs", 3)) {
-				char gbuf[GFSC_DUMP_SIZE];
-
-				memset(gbuf, 0, sizeof(gbuf));
+			if (!strncmp(argv[opt_ind], "gfs", 3))
+				system("gfs_control dump");
 
-				printf("dump gfs\n");
-				gfsc_dump_debug(gbuf);
+			if (!strncmp(argv[opt_ind], "dlm", 3))
+				system("dlm_tool dump");
 
-				do_write(STDOUT_FILENO, gbuf, strlen(gbuf));
-			}
-
-			if (!strncmp(argv[opt_ind], "dlm", 3)) {
-				char dbuf[DLMC_DUMP_SIZE];
-
-				memset(dbuf, 0, sizeof(dbuf));
-
-				printf("dump dlm\n");
-				dlmc_dump_debug(dbuf);
-
-				do_write(STDOUT_FILENO, dbuf, strlen(dbuf));
-			}
-
-			if (!strncmp(argv[opt_ind], "fence", 5)) {
-				char fbuf[FENCED_DUMP_SIZE];
-
-				memset(fbuf, 0, sizeof(fbuf));
-
-				fenced_dump_debug(fbuf);
-
-				do_write(STDOUT_FILENO, fbuf, strlen(fbuf));
-			}
-
-			if (!strncmp(argv[opt_ind], "plocks", 6)) {
-				char pbuf[DLMC_DUMP_SIZE];
-
-				if (opt_ind + 1 >= argc) {
-					printf("plock dump requires name\n");
-					return -1;
-				}
-
-				memset(pbuf, 0, sizeof(pbuf));
-
-				dlmc_dump_plocks(argv[opt_ind + 1], pbuf);
-
-				do_write(STDOUT_FILENO, pbuf, strlen(pbuf));
-			}
-		} else {
-			char rbuf[GROUPD_DUMP_SIZE];
-
-			memset(rbuf, 0, sizeof(rbuf));
-
-			groupd_dump_debug(argc, argv, rbuf);
-
-			do_write(STDOUT_FILENO, rbuf, strlen(rbuf));
+			if (!strncmp(argv[opt_ind], "fence", 5))
+				system("fence_tool dump");
 		}
-
 		break;
-
-	case OP_LOG:
-		if (opt_ind && opt_ind < argc) {
-			return do_log(argv[opt_ind]);
-		}
 	}
 
 	return 0;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]