[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] conga ./clustermon.spec.in.in luci/site/luci/E ...



CVSROOT:	/cvs/cluster
Module name:	conga
Branch: 	RHEL4
Changes by:	rmccabe sourceware org	2007-10-10 18:10:38

Modified files:
	.              : clustermon.spec.in.in 
	luci/site/luci/Extensions: LuciClusterActions.py 
	make           : version.in 
	ricci/modules/cluster/clumon/init.d: modclusterd 
	ricci/modules/cluster/clumon/src/cim-provider: Makefile 
	ricci/modules/cluster/clumon/src/common: Cluster.cpp 
	                                         ClusterMonitor.cpp 
	                                         Node.cpp Service.cpp 
	ricci/modules/cluster/clumon/src/daemon: Communicator.cpp 
	                                         Communicator.h Makefile 
	                                         Monitor.cpp Monitor.h 
	                                         Peer.cpp Peer.h 
	                                         main.cpp 
	ricci/modules/cluster/clumon/src/include: Cluster.h 
	                                          ClusterMonitor.h 
	                                          clumond_globals.h 
	ricci/modules/cluster/clumon/src/snmp-agent: Makefile 

Log message:
	Fix bz326571: Conga displays quorum status incorrectly when qdisk is used

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/clustermon.spec.in.in.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.25.2.7&r2=1.25.2.8
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciClusterActions.py.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.4.2.2&r2=1.4.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/make/version.in.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.28.2.6&r2=1.28.2.7
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/init.d/modclusterd.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.2&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/cim-provider/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.4&r2=1.4.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/common/Cluster.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.6&r2=1.6.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/common/ClusterMonitor.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.2&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/common/Node.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.4&r2=1.4.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/common/Service.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.3&r2=1.3.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Communicator.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.4&r2=1.4.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Communicator.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.3&r2=1.3.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.6&r2=1.6.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.13.2.1&r2=1.13.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.5.4.1&r2=1.5.4.2
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Peer.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.3&r2=1.3.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Peer.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.2&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/main.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.4&r2=1.4.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/include/Cluster.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.6&r2=1.6.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/include/ClusterMonitor.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.2&r2=1.2.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/include/clumond_globals.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.1&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/snmp-agent/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.3.4.1&r2=1.3.4.2

--- conga/clustermon.spec.in.in	2007/08/09 22:34:58	1.25.2.7
+++ conga/clustermon.spec.in.in	2007/10/10 18:10:36	1.25.2.8
@@ -29,10 +29,11 @@
 Source0: %{name}-%{version}.tar.gz
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
-ExcludeArch: ppc64
+ExcludeArch: ppc s390 s390x
 BuildRequires: glibc-devel gcc-c++ libxml2-devel
 BuildRequires: openssl-devel dbus-devel pam-devel pkgconfig
 BuildRequires: net-snmp-devel tog-pegasus-devel
+BuildRequires: cman-devel
 
 %description
 This package contains Red Hat Enterprise Linux Cluster Suite
@@ -193,8 +194,11 @@
 ###  changelog ###
 
 
-
 %changelog
+* Thu Oct 10 2007 Ryan McCabe <rmccabe redhat com> 0.11.0-2
+- Fix bz326571: Conga displays quorum status incorrectly when qdisk is used
+- Resolves: bz326571
+
 * Thu Aug 09 2007 Ryan McCabe <rmccabe redhat com> 0.11.0-1
 - Merge in fixes from the RHEL5 code base.
 - Fix bz241417 (Conga tries to configurage cluster snaps, though they are not available.)
--- conga/luci/site/luci/Extensions/LuciClusterActions.py	2007/08/20 16:27:21	1.4.2.2
+++ conga/luci/site/luci/Extensions/LuciClusterActions.py	2007/10/10 18:10:36	1.4.2.3
@@ -601,10 +601,10 @@
 	if rc is None:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('FNF0: no ricci to fence %s for cluster %s' \
-				% (nodename_resolved, clustername))
+				% (nodename, clustername))
 		return None
 			
-	batch_number, result = rq.nodeFence(rc, nodename_resolved)
+	batch_number, result = rq.nodeFence(rc, nodename)
 	if batch_number is None or result is None:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('FNF1: batch_number and/or result is None')
@@ -614,7 +614,7 @@
 		set_node_flag(self, clustername, rc.hostname(),
 			str(batch_number), NODE_FENCE,
 			'Node "%s" is being fenced by node "%s"' \
-				% (nodename_resolved, rc.hostname()))
+				% (nodename, rc.hostname()))
 	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('FNF2: failed to set flags: %r %s' \
--- conga/make/version.in	2007/08/09 22:02:21	1.28.2.6
+++ conga/make/version.in	2007/10/10 18:10:37	1.28.2.7
@@ -1,5 +1,5 @@
 VERSION=0.11.0
-RELEASE=1
+RELEASE=2
 # Remove "_UNRELEASED" at release time.
 # Put release num at the beggining, 
 # so that after it gets released, it has 
--- conga/ricci/modules/cluster/clumon/init.d/modclusterd	2006/10/14 18:52:23	1.2
+++ conga/ricci/modules/cluster/clumon/init.d/modclusterd	2007/10/10 18:10:37	1.2.4.1
@@ -1,8 +1,8 @@
 #!/bin/sh
 #
-# Copyright (C) 2005 Red Hat, Inc.
+# Copyright (C) 2005-2007 Red Hat, Inc.
 #
-# This program is Free Software.  You may modify and/or redistribute it under
+# This program is Free Software. You may modify and/or redistribute it under
 # the terms of the GNU General Public License version 2, or (at your option)
 # any later version.
 #
@@ -31,12 +31,12 @@
 #
 # Only root wants to run this...
 #
-[ `id -u` = 0 ] || exit 0
+[ `id -u` = 0 ] || exit 4
 
 #
 # If we're not configured, then don't start anything.
 #
-[ "${NETWORKING}" = "yes" ] || exit 0
+[ "${NETWORKING}" = "yes" ] || exit 1
 #[ -f "$CFG_FILE" ] || exit 0
 
 
@@ -46,57 +46,57 @@
 		daemon $MODCLUSTERD
 		rtrn=$?
 		if [ $rtrn -eq 0 ]; then
-		    touch $LOCKFILE
-		    /usr/bin/logger -t $MODCLUSTERD "startup succeeded"
+			touch $LOCKFILE
+			/usr/bin/logger -t $MODCLUSTERD "startup succeeded"
 		else
-		    /usr/bin/logger -t $MODCLUSTERD "startup failed"
+			/usr/bin/logger -t $MODCLUSTERD "startup failed"
+			rtrn=1
 		fi
 		echo
-		;;
+	;;
 
 	restart)
 		$0 stop
 		sleep 8
-		$0 start 
+		$0 start
 		rtrn=$?
-		;;
+	;;
 
 	status)
 		status $MODCLUSTERD
 		rtrn=$?
-		;;
+	;;
 
 	stop)
 		echo -n "Shutting down $ID: "
 		killproc $MODCLUSTERD SIGTERM
 		rtrn=$?
 		if [ $rtrn -eq 0 ]; then
-		    rm -f $PIDFILE
-		    rm -f $LOCKFILE
-		    /usr/bin/logger -t $MODCLUSTERD "shutdown succeeded"
+			rm -f $PIDFILE
+			rm -f $LOCKFILE
+			/usr/bin/logger -t $MODCLUSTERD "shutdown succeeded"
 		else
-		    /usr/bin/logger -t $MODCLUSTERD "shutdown failed"
+			/usr/bin/logger -t $MODCLUSTERD "shutdown failed"
+			rtrn=1
 		fi
-		rtrn=0
 		echo
-		;;
+	;;
 
-        condrestart)
-               if [ -f ${PIDFILE} ] ; then
-		   $0 restart
-		   rtrn=$?
-	       fi
-	       ;;
-
-        reload)
-               rtrn=0
-	       ;;
+	condrestart)
+		if [ -f ${PIDFILE} ] ; then
+			$0 restart
+			rtrn=$?
+		fi
+	;;
+
+	reload)
+		rtrn=3
+	;;
 
 	*)
 		echo $"Usage: $0 {start|stop|reload|restart|status}"
-		rtrn=1
-		;;
-
+		rtrn=3
+	;;
 esac
 
 exit $rtrn
--- conga/ricci/modules/cluster/clumon/src/cim-provider/Makefile	2006/06/30 22:26:12	1.4
+++ conga/ricci/modules/cluster/clumon/src/cim-provider/Makefile	2007/10/10 18:10:37	1.4.4.1
@@ -54,7 +54,7 @@
 
 INCLUDE      += -I ../include 
 CXXFLAGS     += $(PEGASUS_CXXFLAGS)
-LDFLAGS      += -shared -ldl -lcrypt ../common/*.o
+LDFLAGS      += -shared ../common/*.o -ldl -lcrypt -lcman
 
 
 OBJECTS = ClusterProviderMain.o ClusterProvider.o
@@ -82,7 +82,7 @@
 
 
 $(TARGET): $(OBJECTS)
-	$(CXX) $(LDFLAGS) -o $@ $(OBJECTS)
+	$(CXX) -o $@ $(OBJECTS) $(LDFLAGS)
 
 $(TARGET_TEST): clusterCIM_test.*
-	$(CXX) $(CXXFLAGS) -lpegcommon -lpegclient -lpthread -lcrypt -o $@ $  cpp 
+	$(CXX) $(CXXFLAGS) -lpegcommon -lpegclient -lpthread -lcrypt -lcman -o $@ $  cpp 
--- conga/ricci/modules/cluster/clumon/src/common/Cluster.cpp	2006/08/15 00:12:32	1.6
+++ conga/ricci/modules/cluster/clumon/src/common/Cluster.cpp	2007/10/10 18:10:37	1.6.4.1
@@ -1,388 +1,486 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include "Cluster.h"
 
 #include <stdio.h>
 
+extern "C" {
+#	include <libcman.h>
+}
+
 using namespace std;
 using namespace ClusterMonitoring;
 
 
-Cluster::Cluster(const String &name, 
-		 const String &alias, 
-		 const String &cluster_version, 
-		 unsigned int minQuorum) : 
-  _name(name), 
-  _alias(alias), 
-  _cl_version(cluster_version),
-  _minQuorum(minQuorum)
+Cluster::Cluster(	const String &name,
+					const String &alias,
+					const String &cluster_version,
+					unsigned int minQuorum) :
+	_name(name),
+	_alias(alias),
+	_cl_version(cluster_version),
+	_minQuorum(minQuorum)
 {
-  // add no-node node
-  addNode("", 0, false, false, "");
+	// add no-node node
+	addNode("", 0, false, false, "");
 }
 
 Cluster::~Cluster(void)
 {}
 
-
-
-String 
+String
 Cluster::name()
 {
-  return _name;
+	return _name;
 }
 
-String 
+String
 Cluster::alias()
 {
-  return _alias;
+	return _alias;
 }
 
 String
 Cluster::version()
 {
-  return _cl_version;
+	return _cl_version;
 }
 
-unsigned int 
+unsigned int
 Cluster::votes()
 {
-  unsigned int votes = 0;
-  for (map<String, counting_auto_ptr<Node> >::iterator iter = _nodes.begin();
-       iter != _nodes.end();
-       iter++) {
-    Node& node = *(iter->second);
-    if (node.clustered())
-      votes += node.votes();
-  }
-  return votes;
+	cman_handle_t ch = cman_init(NULL);
+	if (ch != NULL) {
+		cman_node_t this_node;
+		int ret;
+
+		ret = cman_get_node(ch, CMAN_NODEID_US, &this_node);
+		cman_finish(ch);
+		if (ret == 0) {
+			FILE *fp = fopen("/proc/cluster/nodes", "r");
+			if (fp != NULL) {
+				char buf[4096];
+				while (fgets(buf, sizeof(buf), fp) != NULL) {
+					int nodeid = -1;
+					int votes = -1;
+				
+					if (!strncmp("Node", buf, 4)) {
+						/* header */
+						continue;
+					}
+					ret = sscanf(buf, "%d %d %*d %*c %*s\n", &nodeid, &votes);
+					if (ret != 2)
+						continue;
+					if (nodeid == this_node.cn_nodeid) {
+						fclose(fp);
+						return (votes);
+					}
+				}
+				fclose(fp);
+			}
+		}
+	}
+
+	unsigned int votes = 0;
+	for (map<String, counting_auto_ptr<Node> >::iterator
+			iter = _nodes.begin() ;
+			iter != _nodes.end() ;
+			iter++)
+	{
+		Node& node = *(iter->second);
+		if (node.clustered())
+			votes += node.votes();
+	}
+	return votes;
 }
 
-unsigned int 
+unsigned int
 Cluster::minQuorum()
 {
-  if (_minQuorum != 0)
-    return _minQuorum;
-  else {
-    unsigned int votes = 0;
-    list<counting_auto_ptr<Node> > nodes = this->nodes();
-    for (list<counting_auto_ptr<Node> >::iterator iter = nodes.begin();
-	 iter != nodes.end();
-	 iter++)
-      votes += (*iter)->votes();
-    return votes/2 + 1;
-  }
-}
-
-bool 
-Cluster::quorate()
-{
-  return votes() >= minQuorum();
-}
+	FILE *fp;
 
+	fp = fopen("/proc/cluster/status", "r");
+	if (fp != NULL) {
+		char buf[4096];
+		int quorum = -1;
+
+		while (fgets(buf, sizeof(buf), fp) != NULL) {
+			if (sscanf(buf, "Quorum: %d\n", &quorum) == 1) {
+				fclose(fp);
+				return (quorum);
+			}
+		}
+		fclose(fp);
+	}
+
+	if (_minQuorum != 0)
+		return _minQuorum;
+	else {
+		unsigned int votes = 0;
+		list<counting_auto_ptr<Node> > nodes = this->nodes();
+		for (list<counting_auto_ptr<Node> >::iterator
+				iter = nodes.begin() ;
+				iter != nodes.end() ;
+				iter++)
+		{
+			votes += (*iter)->votes();
+		}
 
-counting_auto_ptr<Node> 
-Cluster::addNode(const String& name, 
-		 unsigned int votes, 
-		 bool online, 
-		 bool clustered,
-		 const String& uptime)
-{
-  counting_auto_ptr<Node> node(new Node(name, _name, votes, online, clustered, uptime));
-  if (_nodes.insert(pair<String, counting_auto_ptr<Node> >(name, node)).second)
-    return node;
-  else
-    // already present
-    return _nodes[name];
+		return votes / 2 + 1;
+	}
 }
 
-counting_auto_ptr<Service> 
-Cluster::addService(const String& name, 
-		    const String& nodeName, 
-		    bool failed, 
-		    bool autostart,
-		    const String& time_since_transition)
+bool
+Cluster::quorate()
 {
-  map<String, counting_auto_ptr<Node> >::iterator iter = _nodes.find(nodeName);
-  if (iter == _nodes.end())
-    throw String("Cluster::addService(): add node first");
-  return iter->second->addService(name, failed, autostart, time_since_transition);
+	cman_handle_t ch = cman_init(NULL);
+	if (ch != NULL) {
+		int quorate = cman_is_quorate(ch);
+		cman_finish(ch);
+		return quorate;
+	}
+
+	return votes() >= minQuorum();
+}
+
+counting_auto_ptr<Node>
+Cluster::addNode(	const String& name,
+					unsigned int votes,
+					bool online,
+					bool clustered,
+					const String& uptime)
+{
+	counting_auto_ptr<Node> node(new Node(name, _name, votes, online, clustered, uptime));
+	if (_nodes.insert(pair<String, counting_auto_ptr<Node> >(name, node)).second)
+		return node;
+	else {
+		// already present
+		return _nodes[name];
+	}
+}
+
+counting_auto_ptr<Service>
+Cluster::addService(const String& name,
+					const String& nodeName,
+					bool failed,
+					bool autostart,
+					const String& time_since_transition)
+{
+	map<String, counting_auto_ptr<Node> >::iterator iter = _nodes.find(nodeName);
+	if (iter == _nodes.end())
+		throw String("Cluster::addService(): add node first");
+	return iter->second->addService(name, failed, autostart, time_since_transition);
 }
 
-
-list<counting_auto_ptr<Node> > 
+list<counting_auto_ptr<Node> >
 Cluster::nodes()
 {
-  list<counting_auto_ptr<Node> > ret;
-  
-  for (map<String, counting_auto_ptr<Node> >::iterator iter = _nodes.begin();
-       iter != _nodes.end();
-       iter++) {
-    counting_auto_ptr<Node>& node = iter->second;
-    if (!node->name().empty())
-      ret.push_back(node);
-  }
-  return ret;
+	list<counting_auto_ptr<Node> > ret;
+
+	for (map<String, counting_auto_ptr<Node> >::iterator
+			iter = _nodes.begin() ;
+			iter != _nodes.end() ;
+			iter++)
+	{
+		counting_auto_ptr<Node>& node = iter->second;
+		if (!node->name().empty())
+			ret.push_back(node);
+	}
+	return ret;
 }
 
-std::list<counting_auto_ptr<Node> > 
+std::list<counting_auto_ptr<Node> >
 Cluster::clusteredNodes()
 {
-  list<counting_auto_ptr<Node> > ret;
-  
-  for (map<String, counting_auto_ptr<Node> >::iterator iter = _nodes.begin();
-       iter != _nodes.end();
-       iter++) {
-    counting_auto_ptr<Node>& node = iter->second;
-    if (node->name().size() && node->clustered())
-      ret.push_back(node);
-  }
-  return ret;
+	list<counting_auto_ptr<Node> > ret;
+
+	for (map<String, counting_auto_ptr<Node> >::iterator
+			iter = _nodes.begin() ;
+			iter != _nodes.end() ;
+			iter++)
+	{
+		counting_auto_ptr<Node>& node = iter->second;
+		if (node->name().size() && node->clustered())
+			ret.push_back(node);
+	}
+	return ret;
 }
 
-list<counting_auto_ptr<Node> > 
+list<counting_auto_ptr<Node> >
 Cluster::unclusteredNodes()
 {
-  list<counting_auto_ptr<Node> > ret;
-  
-  for (map<String, counting_auto_ptr<Node> >::iterator iter = _nodes.begin();
-       iter != _nodes.end();
-       iter++) {
-    counting_auto_ptr<Node>& node = iter->second;
-    if (node->name().size() && !node->clustered())
-      ret.push_back(node);
-  }
-  return ret;
-}
+	list<counting_auto_ptr<Node> > ret;
 
+	for (map<String, counting_auto_ptr<Node> >::iterator
+			iter = _nodes.begin() ;
+			iter != _nodes.end() ;
+			iter++)
+	{
+		counting_auto_ptr<Node>& node = iter->second;
+		if (node->name().size() && !node->clustered())
+			ret.push_back(node);
+	}
+	return ret;
+}
 
-list<counting_auto_ptr<Service> > 
+list<counting_auto_ptr<Service> >
 Cluster::services()
 {
-  list<counting_auto_ptr<Service> > ret;
-  
-  for (map<String, counting_auto_ptr<Node> >::iterator iter = _nodes.begin();
-       iter != _nodes.end();
-       iter++) {
-    list<counting_auto_ptr<Service> > services = iter->second->services();
-    ret.insert(ret.end(), services.begin(), services.end());
-  }
-  return ret;
+	list<counting_auto_ptr<Service> > ret;
+
+	for (map<String, counting_auto_ptr<Node> >::iterator
+		iter = _nodes.begin() ;
+		iter != _nodes.end() ;
+		iter++)
+	{
+		list<counting_auto_ptr<Service> > services = iter->second->services();
+		ret.insert(ret.end(), services.begin(), services.end());
+	}
+	return ret;
 }
 
-list<counting_auto_ptr<Service> > 
+list<counting_auto_ptr<Service> >
 Cluster::runningServices()
 {
-  list<counting_auto_ptr<Service> > ret;
-  
-  list<counting_auto_ptr<Node> > nodes = this->nodes();
-  for (list<counting_auto_ptr<Node> >::iterator iter = nodes.begin();
-       iter != nodes.end();
-       iter++) {
-    counting_auto_ptr<Node>& node = *iter;
-    list<counting_auto_ptr<Service> > services = node->services();
-    if (node->name().size())
-      ret.insert(ret.end(), services.begin(), services.end());
-  }
-  return ret;
+	list<counting_auto_ptr<Service> > ret;
+
+	list<counting_auto_ptr<Node> > nodes = this->nodes();
+	for (list<counting_auto_ptr<Node> >::iterator
+			iter = nodes.begin() ;
+			iter != nodes.end() ;
+			iter++)
+	{
+		counting_auto_ptr<Node>& node = *iter;
+		list<counting_auto_ptr<Service> > services = node->services();
+		if (node->name().size())
+			ret.insert(ret.end(), services.begin(), services.end());
+	}
+	return ret;
 }
 
-std::list<counting_auto_ptr<Service> > 
+std::list<counting_auto_ptr<Service> >
 Cluster::stoppedServices()
 {
-  list<counting_auto_ptr<Service> > ret;
-  list<counting_auto_ptr<Service> > services = _nodes.find("")->second->services();
-  for (list<counting_auto_ptr<Service> >::iterator iter = services.begin();
-       iter != services.end();
-       iter++) {
-    counting_auto_ptr<Service>& service = *iter;
-    if (!service->running() && !service->failed())
-      ret.push_back(service);
-  }
-  return ret;
+	list<counting_auto_ptr<Service> > ret;
+	list<counting_auto_ptr<Service> > services =
+		_nodes.find("")->second->services();
+
+	for (list<counting_auto_ptr<Service> >::iterator
+			iter = services.begin() ;
+			iter != services.end() ;
+			iter++)
+	{
+		counting_auto_ptr<Service>& service = *iter;
+		if (!service->running() && !service->failed())
+			ret.push_back(service);
+	}
+	return ret;
 }
 
-std::list<counting_auto_ptr<Service> > 
+std::list<counting_auto_ptr<Service> >
 Cluster::failedServices()
 {
-  list<counting_auto_ptr<Service> > ret;
-  list<counting_auto_ptr<Service> > services = _nodes.find("")->second->services();
-  for (list<counting_auto_ptr<Service> >::iterator iter = services.begin();
-       iter != services.end();
-       iter++) {
-    counting_auto_ptr<Service>& service = *iter;
-    if (service->failed())
-      ret.push_back(service);
-  }
-  return ret;
+	list<counting_auto_ptr<Service> > ret;
+	list<counting_auto_ptr<Service> > services =
+		_nodes.find("")->second->services();
+
+	for (list<counting_auto_ptr<Service> >::iterator
+			iter = services.begin() ;
+			iter != services.end() ;
+			iter++)
+	{
+		counting_auto_ptr<Service>& service = *iter;
+		if (service->failed())
+			ret.push_back(service);
+	}
+	return ret;
 }
 
-
-
-
-String 
+String
 ClusterMonitoring::cluster2xml(Cluster& cluster)
 {
-  char buff[1024];
-  
-  // cluster
-  XMLObject clu("cluster");
-  clu.set_attr("name", cluster.name());
-  clu.set_attr("alias", cluster.alias());
-  clu.set_attr("cluster_version", cluster.version());
-  sprintf(buff, "%u", cluster.votes());
-  clu.set_attr("votes", buff);
-  sprintf(buff, "%u", cluster.minQuorum());
-  clu.set_attr("minQuorum", buff);
-  clu.set_attr("quorate", (cluster.quorate()) ? "true" : "false");
-  
-  // nodes
-  std::list<counting_auto_ptr<Node> > nodes = cluster.nodes();
-  for (std::list<counting_auto_ptr<Node> >::iterator iter = nodes.begin();
-       iter != nodes.end();
-       iter++) {
-    Node& node = **iter;
-    XMLObject n("node");
-    n.set_attr("name", node.name());
-    sprintf(buff, "%u", node.votes());
-    n.set_attr("votes", buff);
-    n.set_attr("online", (node.online()) ? "true" : "false");
-    n.set_attr("clustered", (node.clustered()) ? "true" : "false");
-    n.set_attr("uptime", node.uptime());
-    clu.add_child(n);
-  }
-  
-  // services
-  std::list<counting_auto_ptr<Service> > services = cluster.services();
-  for (std::list<counting_auto_ptr<Service> >::iterator iter = services.begin();
-       iter != services.end();
-       iter++) {
-    Service& service = **iter;
-    XMLObject s("service");
-    s.set_attr("name", service.name());
-    s.set_attr("running", (service.running()) ? "true" : "false");
-    if (service.running())
-      s.set_attr("nodename", service.nodename());
-    else
-      s.set_attr("nodename", "");
-    s.set_attr("failed", (service.failed()) ? "true" : "false");
-    s.set_attr("autostart", (service.autostart()) ? "true" : "false");
-    s.set_attr("time_since_transition", service.time_since_transition());
-    clu.add_child(s);
-  }
-  
-  return generateXML(clu);
+	char buff[64];
+
+	// cluster
+	XMLObject clu("cluster");
+	clu.set_attr("name", cluster.name());
+	clu.set_attr("alias", cluster.alias());
+	clu.set_attr("cluster_version", cluster.version());
+
+	snprintf(buff, sizeof(buff), "%u", cluster.votes());
+	clu.set_attr("votes", buff);
+
+	snprintf(buff, sizeof(buff), "%u", cluster.minQuorum());
+	clu.set_attr("minQuorum", buff);
+
+	clu.set_attr("quorate", (cluster.quorate()) ? "true" : "false");
+
+	// nodes
+	std::list<counting_auto_ptr<Node> > nodes = cluster.nodes();
+	for (std::list<counting_auto_ptr<Node> >::iterator
+		iter = nodes.begin() ;
+		iter != nodes.end() ;
+		iter++)
+	{
+		Node& node = **iter;
+		XMLObject n("node");
+		n.set_attr("name", node.name());
+
+		snprintf(buff, sizeof(buff), "%u", node.votes());
+		n.set_attr("votes", buff);
+
+		n.set_attr("online", (node.online()) ? "true" : "false");
+		n.set_attr("clustered", (node.clustered()) ? "true" : "false");
+		n.set_attr("uptime", node.uptime());
+		clu.add_child(n);
+	}
+
+	// services
+	std::list<counting_auto_ptr<Service> > services = cluster.services();
+	for (std::list<counting_auto_ptr<Service> >::iterator
+			iter = services.begin() ;
+			iter != services.end() ;
+			iter++)
+	{
+		Service& service = **iter;
+		XMLObject s("service");
+		s.set_attr("name", service.name());
+		s.set_attr("running", (service.running()) ? "true" : "false");
+		if (service.running())
+			s.set_attr("nodename", service.nodename());
+		else
+			s.set_attr("nodename", "");
+		s.set_attr("failed", (service.failed()) ? "true" : "false");
+		s.set_attr("autostart", (service.autostart()) ? "true" : "false");
+		s.set_attr("time_since_transition", service.time_since_transition());
+		clu.add_child(s);
+	}
+
+	return generateXML(clu);
 }
 
-counting_auto_ptr<Cluster> 
+counting_auto_ptr<Cluster>
 ClusterMonitoring::xml2cluster(const String& xml)
 {
-  XMLObject clu = parseXML(xml);
-  if (clu.tag() != "cluster")
-    throw String("xml2cluster(): invalid xml");
-  
-  // cluster
-  String name = clu.get_attr("name");
-  if (name.empty())
-    throw String("xml2cluster(): missing cluster name");
-  unsigned int minQuorum = 0;
-  if (sscanf(clu.get_attr("minQuorum").c_str(), "%u", &minQuorum) != 1)
-    throw String("xml2cluster(): invalid value for cluster's minQuorum");
-  String alias = clu.get_attr("alias");
-  String cl_version = clu.get_attr("cluster_version");
-  counting_auto_ptr<Cluster> cluster(new Cluster(name, 
-						 alias, 
-						 cl_version, 
-						 minQuorum));
-  
-  // nodes
-  for (list<XMLObject>::const_iterator iter = clu.children().begin();
-       iter != clu.children().end();
-       iter++) {
-    const XMLObject& obj = *iter;
-    if (obj.tag() == "node") {
-      // name
-      String node_name = obj.get_attr("name");
-      if (node_name.empty())
-	throw String("xml2cluster(): node missing 'name' attr");
-      // votes
-      unsigned int votes;
-      if (sscanf(obj.get_attr("votes").c_str(), "%u", &votes) != 1)
-	throw String("xml2cluster(): invalid value for node's votes");
-      // online
-      String online_str = obj.get_attr("online");
-      bool online = online_str == "true";
-      if (online_str.empty())
-	throw String("xml2cluster(): node missing 'online' attr");
-      // clustered
-      String clustered_str = obj.get_attr("clustered");
-      bool clustered = clustered_str == "true";
-      if (clustered_str.empty())
-	throw String("xml2cluster(): node missing 'clustered' attr");
-      // uptime
-      String uptime = obj.get_attr("uptime");
-      // add node to cluster
-      cluster->addNode(node_name, votes, online, clustered, uptime);
-    }
-  }
-  
-  // services
-  for (list<XMLObject>::const_iterator iter = clu.children().begin();
-       iter != clu.children().end();
-       iter++) {
-    const XMLObject& obj = *iter;
-    if (obj.tag() == "service") {
-      // name
-      String service_name = obj.get_attr("name");
-      if (service_name.empty())
-	throw String("xml2cluster(): service missing 'name' attr");
-      // running
-      String running_str = obj.get_attr("running");
-      bool running = running_str == "true";
-      if (running_str.empty())
-	throw String("xml2cluster(): service missing 'running' attr");
-      // nodename
-      String nodename = obj.get_attr("nodename");
-      if (running)
-	if (nodename.empty())
-	  throw String("xml2cluster(): running service missing 'nodename' attr");
-      // failed
-      String failed_str = obj.get_attr("failed");
-      bool failed = failed_str == "true";
-      if (failed_str.empty())
-	throw String("xml2cluster(): service missing 'failed' attr");
-      // autostart
-      String autostart_str = obj.get_attr("autostart");
-      bool autostart = autostart_str == "true";
-      if (autostart_str.empty())
-	throw String("xml2cluster(): service missing 'autostart' attr");
-      // time since last transition
-      String time_since_transition = obj.get_attr("time_since_transition");
-      // add service to cluster
-      cluster->addService(service_name, nodename, failed, autostart, time_since_transition);
-    }
-  }
-  
-  return cluster;
+	XMLObject clu = parseXML(xml);
+	if (clu.tag() != "cluster")
+		throw String("xml2cluster(): invalid xml");
+
+	// cluster
+	String name = clu.get_attr("name");
+	if (name.empty())
+		throw String("xml2cluster(): missing cluster name");
+
+	unsigned int minQuorum = 0;
+	if (sscanf(clu.get_attr("minQuorum").c_str(), "%u", &minQuorum) != 1)
+		throw String("xml2cluster(): invalid value for cluster's minQuorum");
+
+	String alias = clu.get_attr("alias");
+	String cl_version = clu.get_attr("cluster_version");
+
+	counting_auto_ptr<Cluster> cluster(new Cluster(name, alias, cl_version, minQuorum));
+
+	// nodes
+	for (list<XMLObject>::const_iterator
+			iter = clu.children().begin() ;
+			iter != clu.children().end() ;
+			iter++)
+	{
+		const XMLObject& obj = *iter;
+		if (obj.tag() == "node") {
+			// name
+			String node_name = obj.get_attr("name");
+			if (node_name.empty())
+				throw String("xml2cluster(): node missing 'name' attr");
+
+			// votes
+			unsigned int votes;
+			if (sscanf(obj.get_attr("votes").c_str(), "%u", &votes) != 1)
+				throw String("xml2cluster(): invalid value for node's votes");
+
+			// online
+			String online_str = obj.get_attr("online");
+			bool online = online_str == "true";
+			if (online_str.empty())
+				throw String("xml2cluster(): node missing 'online' attr");
+
+			// clustered
+			String clustered_str = obj.get_attr("clustered");
+			bool clustered = clustered_str == "true";
+			if (clustered_str.empty())
+				throw String("xml2cluster(): node missing 'clustered' attr");
+
+			// uptime
+			String uptime = obj.get_attr("uptime");
+
+			// add node to cluster
+			cluster->addNode(node_name, votes, online, clustered, uptime);
+		}
+	}
+
+	// services
+	for (list<XMLObject>::const_iterator
+			iter = clu.children().begin() ;
+			iter != clu.children().end() ;
+			iter++)
+	{
+		const XMLObject& obj = *iter;
+		if (obj.tag() == "service") {
+			// name
+			String service_name = obj.get_attr("name");
+			if (service_name.empty())
+				throw String("xml2cluster(): service missing 'name' attr");
+
+			// running
+			String running_str = obj.get_attr("running");
+			bool running = running_str == "true";
+			if (running_str.empty())
+				throw String("xml2cluster(): service missing 'running' attr");
+
+			// nodename
+			String nodename = obj.get_attr("nodename");
+			if (running && nodename.empty())
+				throw String("xml2cluster(): service missing 'nodename' attr");
+
+			// failed
+			String failed_str = obj.get_attr("failed");
+			bool failed = failed_str == "true";
+			if (failed_str.empty())
+				throw String("xml2cluster(): service missing 'failed' attr");
+
+			// autostart
+			String autostart_str = obj.get_attr("autostart");
+			bool autostart = autostart_str == "true";
+			if (autostart_str.empty())
+				throw String("xml2cluster(): service missing 'autostart' attr");
+
+			// time since last transition
+			String tst = obj.get_attr("time_since_transition");
+
+			// add service to cluster
+			cluster->addService(service_name, nodename, failed, autostart, tst);
+		}
+	}
+
+	return cluster;
 }
--- conga/ricci/modules/cluster/clumon/src/common/ClusterMonitor.cpp	2006/08/10 22:53:08	1.2
+++ conga/ricci/modules/cluster/clumon/src/common/ClusterMonitor.cpp	2007/10/10 18:10:37	1.2.4.1
@@ -1,84 +1,86 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge,
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include "ClusterMonitor.h"
 #include "Socket.h"
 #include "Time.h"
 
-#include <sys/poll.h>
 #include <errno.h>
-
+#include <sys/poll.h>
 
 using namespace ClusterMonitoring;
 
-
-ClusterMonitor::ClusterMonitor(const String& socket_path) : 
-  _sock_path(socket_path)
+ClusterMonitor::ClusterMonitor(const String& socket_path) :
+	_sock_path(socket_path)
 {}
 
 ClusterMonitor::~ClusterMonitor()
 {}
 
-
 counting_auto_ptr<Cluster>
 ClusterMonitor::get_cluster()
 {
-  try {
-    ClientSocket sock(_sock_path);
-    
-    if(sock.send("GET").size())
-      throw int();
-    
-    String xml;
-    unsigned int timeout = 1000;
-    while (timeout > 0) {
-      struct pollfd poll_data;
-      poll_data.fd = sock.get_sock();
-      poll_data.events = POLLIN;
-      poll_data.revents = 0;
-      
-      unsigned int time_start = time_mil();
-      int ret = poll(&poll_data, 1, timeout);
-      timeout -= (time_mil() - time_start);
-      if (ret == 0)
-	continue;
-      else if (ret == -1) {
-	if (errno == EINTR)
-	  continue;
-	else
-	  throw String("get_cluster(): poll() error");
-      }
-      if (poll_data.revents & POLLIN) {
-	xml += sock.recv();
-	if (xml.find("\n\n") != xml.npos)
-	  break;
-	continue;
-      }
-      if (poll_data.revents & (POLLERR | POLLHUP | POLLNVAL))
-	throw String("get_cluster(): socket error");
-    }
-    return xml2cluster(xml);
-  } catch ( ... ) {
-    return counting_auto_ptr<Cluster>();
-  }
+	try {
+		ClientSocket sock(_sock_path);
+
+		if(sock.send("GET").size())
+			throw int();
+
+		String xml;
+		unsigned int timeout = 1000;
+		while (timeout > 0) {
+			struct pollfd poll_data;
+			poll_data.fd = sock.get_sock();
+			poll_data.events = POLLIN;
+			poll_data.revents = 0;
+
+			unsigned int time_start = time_mil();
+
+			int ret = poll(&poll_data, 1, timeout);
+			int err = errno;
+			timeout -= (time_mil() - time_start);
+			if (ret == 0)
+				continue;
+			else if (ret == -1) {
+				if (errno == EINTR)
+					continue;
+				else {
+					throw String("get_cluster(): poll() error")
+							+ String(strerror(err));
+				}
+			}
+
+			if (poll_data.revents & POLLIN) {
+				xml += sock.recv();
+				if (xml.find("\n\n") != xml.npos)
+					break;
+				continue;
+			}
+
+			if (poll_data.revents & (POLLERR | POLLHUP | POLLNVAL))
+				throw String("get_cluster(): socket error");
+		}
+		return xml2cluster(xml);
+	} catch ( ... ) {
+		return counting_auto_ptr<Cluster>();
+	}
 }
--- conga/ricci/modules/cluster/clumon/src/common/Node.cpp	2006/08/10 22:53:08	1.4
+++ conga/ricci/modules/cluster/clumon/src/common/Node.cpp	2007/10/10 18:10:37	1.4.4.1
@@ -1,106 +1,107 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include "Cluster.h"
 
 using namespace std;
 using namespace ClusterMonitoring;
 
-
-Node::Node(const String& name, 
-	   const String& clustername, 
-	   unsigned int votes,
-	   bool online,
-	   bool clustered,
-	   const String& uptime) : 
-  _name(name),
-  _clustername(clustername),
-  _votes(votes),
-  _online(online),
-  _clustered(clustered),
-  _uptime(uptime)
+Node::Node(	const String& name,
+			const String& clustername,
+			unsigned int votes,
+			bool online,
+			bool clustered,
+			const String& uptime) :
+	_name(name),
+	_clustername(clustername),
+	_votes(votes),
+	_online(online),
+	_clustered(clustered),
+	_uptime(uptime)
 {}
 
 Node::~Node(void)
 {}
 
 
-String 
+String
 Node::name() const
 {
-  return _name;
+	return _name;
 }
 
-String 
+String
 Node::clustername() const
 {
-  return _clustername;
+	return _clustername;
 }
 
-unsigned int 
+unsigned int
 Node::votes() const
 {
-  return _votes;
+	return _votes;
 }
 
-bool 
+bool
 Node::online() const
 {
-  return _online;
+	return _online;
 }
 
-bool 
+bool
 Node::clustered() const
 {
-  return _clustered;
+	return _clustered;
 }
 
 String
 Node::uptime() const
 {
-  return _uptime;
+	return _uptime;
 }
 
 
 counting_auto_ptr<Service>
-Node::addService(const String& name,
-		 bool failed,
-		 bool autostart,
-		 const String& time_since_transition)
-{
-  counting_auto_ptr<Service> service(new Service(name, _clustername, *this, failed, autostart, time_since_transition));
-  _services.insert(pair<String, counting_auto_ptr<Service> >(name, service));
-  return service;
+Node::addService(	const String& name,
+					bool failed,
+					bool autostart,
+					const String& time_since_transition)
+{
+	counting_auto_ptr<Service> service(new Service(name, _clustername, *this, failed, autostart, time_since_transition));
+	_services.insert(pair<String, counting_auto_ptr<Service> >(name, service));
+	return service;
 }
 
 list<counting_auto_ptr<Service> >
 Node::services()
 {
-  list<counting_auto_ptr<Service> > ret;
-  
-  for (map<String, counting_auto_ptr<Service> >::iterator iter = _services.begin();
-       iter != _services.end();
-       iter++)
-    ret.push_back(iter->second);
-  return ret;
+	list<counting_auto_ptr<Service> > ret;
+
+	for (map<String, counting_auto_ptr<Service> >::iterator
+			iter = _services.begin() ;
+			iter != _services.end() ;
+			iter++)
+	{
+		ret.push_back(iter->second);
+	}
+	return ret;
 }
--- conga/ricci/modules/cluster/clumon/src/common/Service.cpp	2006/08/10 22:53:08	1.3
+++ conga/ricci/modules/cluster/clumon/src/common/Service.cpp	2007/10/10 18:10:37	1.3.4.1
@@ -1,89 +1,85 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include "Cluster.h"
 
-
 using namespace ClusterMonitoring;
 using namespace std;
 
-
 Service::Service(const String& name,
 		 const String& clustername,
 		 const Node& node,
 		 bool failed,
 		 bool autostart,
-		 const String& time_since_transition) : 
-  _name(name),
-  _clustername(clustername),
-  _nodename(node.name()),
-  _autostart(autostart),
-  _failed(failed),
-  _time_since_transition(time_since_transition)
+		 const String& time_since_transition) :
+	_name(name),
+	_clustername(clustername),
+	_nodename(node.name()),
+	_autostart(autostart),
+	_failed(failed),
+	_time_since_transition(time_since_transition)
 {}
 
 Service::~Service(void)
 {}
 
-
 String
 Service::name() const
 {
-  return _name;
+	return _name;
 }
 
 String
 Service::clustername() const
 {
-  return _clustername;
+	return _clustername;
 }
 
-bool 
+bool
 Service::running() const
 {
-  return _nodename.size();
+	return _nodename.size();
 }
 
 String
 Service::nodename() const
 {
-  return _nodename;
+	return _nodename;
 }
 
-bool 
+bool
 Service::failed() const
 {
-  return _failed;
+	return _failed;
 }
 
-bool 
+bool
 Service::autostart() const
 {
-  return _autostart;
+	return _autostart;
 }
 
 String
 Service::time_since_transition() const
 {
-  return _time_since_transition;
+	return _time_since_transition;
 }
--- conga/ricci/modules/cluster/clumon/src/daemon/Communicator.cpp	2006/10/14 18:00:02	1.4
+++ conga/ricci/modules/cluster/clumon/src/daemon/Communicator.cpp	2007/10/10 18:10:37	1.4.4.1
@@ -1,26 +1,25 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include "Communicator.h"
 #include "array_auto_ptr.h"
 #include "Logger.h"
@@ -35,224 +34,256 @@
 #include <map>
 #include <algorithm>
 
-
 using namespace ClusterMonitoring;
 using namespace std;
 
-
-
 CommDP::CommDP()
 {}
 
 CommDP::~CommDP()
 {}
 
-
-
-Communicator::Communicator(unsigned short port, 
-			   CommDP& delivery_point) :
-  _port(port), 
-  _serv_sock(_port),
-  _delivery_point(delivery_point)
+Communicator::Communicator(unsigned short port, CommDP& delivery_point) :
+	_port(port),
+	_serv_sock(_port),
+	_delivery_point(delivery_point)
 {
-  _serv_sock.nonblocking(true);
-  _connect_time = time_sec();
-  _rand_state = time_mil();
-  log(String("Communicator created, port ") + _port, LogCommunicator);
+	_serv_sock.nonblocking(true);
+	_connect_time = time_sec();
+	_rand_state = time_mil();
+	log(String("Communicator created, port ") + _port, LogCommunicator);
 }
 
 Communicator::~Communicator()
 {
-  stop();
-  log("Communicator deleted", LogCommunicator);
+	stop();
+	log("Communicator deleted", LogCommunicator);
 }
-  
-void 
+
+void
 Communicator::send(const String& msg)
 {
-  MutexLocker l(_mutex);
-  _out_q.push_back(msg);
+	MutexLocker l(_mutex);
+	_out_q.push_back(msg);
 }
 
-void 
-Communicator::update_peers(const String& self, 
-			   const std::vector<String>& hosts)
+void
+Communicator::update_peers(const String& self, const std::vector<String>& hosts)
 {
-  MutexLocker l(_mutex);
-  _my_hostname = self;
-  _peer_hostnames.clear();
-  for (unsigned int i=0; i<hosts.size(); i++)
-    _peer_hostnames.push_back(hosts[i]);
+	MutexLocker l(_mutex);
+	_my_hostname = self;
+	_peer_hostnames.clear();
+
+	for (unsigned int i = 0 ; i < hosts.size() ; i++)
+		_peer_hostnames.push_back(hosts[i]);
 }
 
 void
 Communicator::run()
 {
-  while (!shouldStop()) {
-    vector<String> names;
-    vector<String> que;
-    String my_hostname;
-    {
-      MutexLocker l(_mutex);
-      my_hostname = _my_hostname;
-      for (unsigned int i=0; i<_peer_hostnames.size(); i++)
-	names.push_back(_peer_hostnames[i]);
-      for (unsigned int i=0; i<_out_q.size(); i++)
-	que.push_back(_out_q[i]);
-      _out_q.clear();
-    }
-    
-    // remove non-peers
-    vector<String> remove_us;
-    for (map<String, Peer>::iterator iter = _peers.begin(); 
-	 iter != _peers.end(); 
-	 iter++) {
-      const String& name = iter->first;
-      if (find(names.begin(), names.end(), name) == names.end())
-	remove_us.push_back(name);
-    }
-    for (vector<String>::iterator iter = remove_us.begin();
-	 iter != remove_us.end();
-	 iter++) {
-      log("dropping connection with " + *iter, LogCommunicator);
-      _peers.erase(*iter);
-    }
-    
-    // connect to peers
-    if (time_to_connect()) {
-      for (vector<String>::iterator iter = names.begin();
-	   iter != names.end();
-	   iter ++) {
-	const String& name = *iter;
-	if (_peers.find(name) == _peers.end())
-	  try {
-	    _peers.insert(pair<String, Peer>(name, Peer(name, _port)));
-	    log("connected to " + name + ", socket " + _peers[name].get_sock_fd(), LogCommunicator);
-	  } catch ( ... ) {}
-      }
-    }
-    
-    // buffer msgs
-    for (vector<String>::iterator iter_q = que.begin(); 
-	 iter_q != que.end(); 
-	 iter_q++) {
-      String& msg = *iter_q;
-      _delivery_point.msg_arrived(my_hostname, msg);
-      for (map<String, Peer>::iterator iter_p = _peers.begin(); 
-	   iter_p != _peers.end(); 
-	   iter_p++)
-	iter_p->second.append(msg);
-    }
-    
-    serve_sockets(names);
-    
-  }  // while(!shouldStop())
+	while (!shouldStop()) {
+		vector<String> names;
+		vector<String> que;
+		String my_hostname;
+
+		{
+			MutexLocker l(_mutex);
+			my_hostname = _my_hostname;
+
+			for (unsigned int i = 0 ; i < _peer_hostnames.size() ; i++)
+				names.push_back(_peer_hostnames[i]);
+
+			for (unsigned int i = 0 ; i < _out_q.size() ; i++)
+				que.push_back(_out_q[i]);
+			_out_q.clear();
+		}
+
+		// remove non-peers
+		vector<String> remove_us;
+		for (map<String, Peer>::iterator
+				iter = _peers.begin() ;
+				iter != _peers.end() ;
+				iter++)
+		{
+			const String& name = iter->first;
+			if (find(names.begin(), names.end(), name) == names.end())
+				remove_us.push_back(name);
+		}
+
+		for (vector<String>::iterator
+				iter = remove_us.begin() ;
+				iter != remove_us.end() ;
+				iter++)
+		{
+			log("dropping connection with " + *iter, LogCommunicator);
+			_peers.erase(*iter);
+		}
+
+		// connect to peers
+		if (time_to_connect()) {
+			for (vector<String>::iterator
+					iter = names.begin() ;
+					iter != names.end() ;
+					iter++)
+			{
+				const String& name = *iter;
+				if (_peers.find(name) == _peers.end()) {
+					try {
+						_peers.insert(pair<String, Peer>(name, Peer(name, _port)));
+						log("connected to " + name + ", socket "
+							+ _peers[name].get_sock_fd(), LogCommunicator);
+					} catch ( ... ) {}
+				}
+			}
+		}
+
+		// buffer msgs
+		for (vector<String>::iterator iter_q = que.begin();
+				iter_q != que.end();
+				iter_q++)
+		{
+			String& msg = *iter_q;
+			_delivery_point.msg_arrived(my_hostname, msg);
+			for (map<String, Peer>::iterator iter_p = _peers.begin();
+					iter_p != _peers.end();
+					iter_p++)
+			{
+				iter_p->second.append(msg);
+			}
+		}
+
+		serve_sockets(names);
+	}
 }
 
-void 
+void
 Communicator::serve_sockets(vector<String>& names)
 {
-  map<int, Peer> fd_peer;
-  for (map<String, Peer>::iterator iter = _peers.begin();
-       iter != _peers.end();
-       iter++) {
-    Peer& peer = iter->second;
-    fd_peer.insert(pair<int, Peer>(peer.get_sock_fd(), peer));
-  }
-  unsigned int socks_num = fd_peer.size() + 1;
-  
-  // prepare poll structs
-  array_auto_ptr<poll_fd> poll_data(new poll_fd[socks_num]);
-  poll_data[0].fd = _serv_sock.get_sock();
-  poll_data[0].events = POLLIN;
-  poll_data[0].revents = 0;
-  map<int, Peer>::iterator iter = fd_peer.begin();
-  for (unsigned int i=1; i<socks_num; i++, iter++) {
-    poll_data[i].fd = iter->first;
-    poll_data[i].events = POLLIN;
-    if ( ! iter->second.outq_empty())
-      poll_data[i].events = POLLOUT;
-    poll_data[i].revents = 0;
-  }
-  
-  // wait for events
-  int ret = poll(poll_data.get(), socks_num, 500);
-  if (ret == 0)
-    return;
-  else if (ret == -1) {
-    if (errno == EINTR)
-      return;
-    else
-      throw String("Communicator::run(): poll() error");
-  }
-  
-  // process events
-  for (unsigned int i=0; i<socks_num && !shouldStop(); i++) {
-    poll_fd& poll_info = poll_data[i];
-    
-    // server socket
-    if (poll_info.fd == _serv_sock.get_sock()) {
-      if (poll_info.revents & POLLIN) {
-	try {
-	  ClientSocket sock = _serv_sock.accept();
-	  sock.nonblocking(true);
-	  String hostname;
-	  for (vector<String>::iterator iter = names.begin();
-	       iter != names.end();
-	       iter++) {
-	    String& name = *iter;
-	    if (sock.connected_to(name))
-	      hostname = name;
-	  }
-	  if (hostname.size()) {
-	    _peers.insert(pair<String, Peer>(hostname, Peer(hostname, sock)));
-	    log("accepted connection from " + hostname + ", socket " + sock.get_sock(), LogCommunicator);
-	  }
-	} catch ( ... ) {}
-      }
-      if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL))
-	throw String("Communicator::run(): server socket error????");
-    }
-    
-    // client socket
-    else {
-      Peer& peer = fd_peer[poll_info.fd];
-      if (poll_info.revents & POLLIN) {
-	vector<String> msgs;
-	try {
-	  msgs = peer.receive();
-	} catch ( ... ) {
-	  log("error receiving data from " + peer.hostname(), LogCommunicator);
-	  _peers.erase(peer.hostname());
-	  continue;
+	map<int, Peer> fd_peer;
+	for (map<String, Peer>::iterator
+		iter = _peers.begin();
+		iter != _peers.end();
+		iter++)
+	{
+		Peer& peer = iter->second;
+		fd_peer.insert(pair<int, Peer>(peer.get_sock_fd(), peer));
 	}
-	for (unsigned int i=0; i<msgs.size(); i++)
-	  _delivery_point.msg_arrived(peer.hostname(), msgs[i]);
-	continue;
-      }
-      if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL)) {
-	_peers.erase(peer.hostname());
-	continue;
-      }
-      if (poll_info.revents & POLLOUT) {
-	try {
-	  peer.send();
-	} catch ( ... ) {
-	  log("error sending data to " + peer.hostname(), LogCommunicator);
-	  _peers.erase(peer.hostname());
-	  continue;
+
+	unsigned int socks_num = fd_peer.size() + 1;
+
+	// prepare poll structs
+	array_auto_ptr<poll_fd> poll_data(new poll_fd[socks_num]);
+	poll_data[0].fd = _serv_sock.get_sock();
+	poll_data[0].events = POLLIN;
+	poll_data[0].revents = 0;
+	map<int, Peer>::iterator iter = fd_peer.begin();
+
+	for (unsigned int i = 1 ; i < socks_num ; i++, iter++) {
+		poll_data[i].fd = iter->first;
+		poll_data[i].events = POLLIN;
+		if (!iter->second.outq_empty())
+			poll_data[i].events = POLLOUT;
+		poll_data[i].revents = 0;
+	}
+
+	// wait for events
+	int ret = poll(poll_data.get(), socks_num, 500);
+	if (ret == 0)
+		return;
+	else if (ret == -1) {
+		if (errno == EINTR)
+			return;
+		else {
+			throw String("Communicator::run(): poll() error: ")
+					+ String(strerror(errno));
+		}
+	}
+
+	// process events
+	for (unsigned int i = 0 ; i < socks_num && !shouldStop() ; i++) {
+		poll_fd& poll_info = poll_data[i];
+
+		// server socket
+		if (poll_info.fd == _serv_sock.get_sock()) {
+			if (poll_info.revents & POLLIN) {
+				try {
+					ClientSocket sock = _serv_sock.accept();
+					sock.nonblocking(true);
+					String hostname;
+
+					for (vector<String>::iterator
+							iter = names.begin() ;
+							iter != names.end() ;
+							iter++)
+					{
+						String& name = *iter;
+						if (sock.connected_to(name))
+							hostname = name;
+					}
+
+					if (hostname.size()) {
+						_peers.insert(pair<String, Peer>(hostname, Peer(hostname, sock)));
+						log("accepted connection from " + hostname + ", socket "
+							+ sock.get_sock(), LogCommunicator);
+					}
+				} catch ( ... ) {}
+			}
+			if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL))
+				throw String("Communicator::run(): server socket error");
+		} else {
+			// client socket
+			Peer& peer = fd_peer[poll_info.fd];
+			if (poll_info.revents & POLLIN) {
+				vector<String> msgs;
+				try {
+					msgs = peer.receive();
+				} catch (String e) {
+					log("error receiving data from "
+							+ peer.hostname() + ": " + e,
+						LogCommunicator);
+					_peers.erase(peer.hostname());
+					continue;
+				} catch ( ... ) {
+					log("error receiving data from " + peer.hostname(),
+						LogCommunicator);
+					_peers.erase(peer.hostname());
+					continue;
+				}
+
+				for (unsigned int i = 0 ; i < msgs.size() ; i++)
+					_delivery_point.msg_arrived(peer.hostname(), msgs[i]);
+				continue;
+			}
+			if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+				_peers.erase(peer.hostname());
+				continue;
+			}
+			if (poll_info.revents & POLLOUT) {
+				try {
+					peer.send();
+				} catch (String e) {
+					log("error sending data to "
+							+ peer.hostname() + " : " + e,
+						LogCommunicator);
+					_peers.erase(peer.hostname());
+					continue;
+				} catch ( ... ) {
+					log("error sending data to " + peer.hostname(),
+						LogCommunicator);
+					_peers.erase(peer.hostname());
+					continue;
+				}
+			}
+		}
 	}
-      }
-    }  // client socket
-  }  // process events
 }
 
 bool
 Communicator::time_to_connect()
 {
-  if (time_sec() > _connect_time) {
-    _connect_time = time_sec() + rand_r(&_rand_state) % 15;
-    return true;
-  }
-  return false;
+	if (time_sec() > _connect_time) {
+		_connect_time = time_sec() + rand_r(&_rand_state) % 15;
+		return true;
+	}
+	return false;
 }
--- conga/ricci/modules/cluster/clumon/src/daemon/Communicator.h	2006/08/10 22:53:08	1.3
+++ conga/ricci/modules/cluster/clumon/src/daemon/Communicator.h	2007/10/10 18:10:37	1.3.4.1
@@ -1,28 +1,27 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
-#ifndef Communicator_h
-#define Communicator_h
+#ifndef __CONGA_MODCLUSTERD_COMMUNICATOR_H
+#define __CONGA_MODCLUSTERD_COMMUNICATOR_H
 
 #include "Thread.h"
 #include "Mutex.h"
@@ -33,60 +32,53 @@
 #include <vector>
 #include <map>
 
-
-namespace ClusterMonitoring 
+namespace ClusterMonitoring
 {
 
 
 class CommDP
 {
- public:
-  CommDP();
-  virtual ~CommDP();
-  
-  virtual void msg_arrived(const String& host,
-			   const String& msg) = 0;
+	public:
+		CommDP();
+		virtual ~CommDP();
+
+		virtual void msg_arrived(const String& host, const String& msg) = 0;
 };
 
 
 class Communicator : public Thread
 {
- public:
-  Communicator(unsigned short port, CommDP& delivery_point);
-  virtual ~Communicator();
-  
-  void send(const String& msg);
-  void update_peers(const String& self, const std::vector<String>& peers);
-  
- private:
-  unsigned short _port;
-  ServerSocket _serv_sock;
-  
-  CommDP& _delivery_point;
-  
-  std::map<String, Peer> _peers;
-  
-  Mutex _mutex;
-  String _my_hostname;
-  std::vector<String> _out_q;
-  std::vector<String> _peer_hostnames;
-  
-  void serve_sockets(std::vector<String>&hostnames);
-  
-  bool time_to_connect();
-  unsigned int _connect_time;
-  unsigned int _rand_state;
-  
-  
-  void run();
-  
-  Communicator(const Communicator&);
-  Communicator& operator= (const Communicator&);
+	public:
+		Communicator(unsigned short port, CommDP& delivery_point);
+		virtual ~Communicator();
+
+		void send(const String& msg);
+		void update_peers(const String& self, const std::vector<String>& peers);
 
-};  // class Communicator
+	private:
+		unsigned short _port;
+		ServerSocket _serv_sock;
 
+		CommDP& _delivery_point;
 
-};  // namespace ClusterMonitoring 
+		std::map<String, Peer> _peers;
 
+		Mutex _mutex;
+		String _my_hostname;
+		std::vector<String> _out_q;
+		std::vector<String> _peer_hostnames;
+
+		void serve_sockets(std::vector<String>&hostnames);
+		bool time_to_connect();
+		unsigned int _connect_time;
+		unsigned int _rand_state;
+
+		void run();
+
+		Communicator(const Communicator&);
+		Communicator& operator= (const Communicator&);
+};
+
+};
 
-#endif  // Communicator_h
+#endif
--- conga/ricci/modules/cluster/clumon/src/daemon/Makefile	2006/08/15 00:12:33	1.6
+++ conga/ricci/modules/cluster/clumon/src/daemon/Makefile	2007/10/10 18:10:37	1.6.4.1
@@ -21,7 +21,7 @@
 
 INCLUDE     += -I ../include 
 CXXFLAGS    += 
-LDFLAGS     += ../common/*.o
+LDFLAGS     += ../common/*.o -lcman
 
 
 all: ${TARGET}
@@ -43,4 +43,4 @@
 *.o: *.h
 
 $(TARGET): $(OBJECTS)
-	$(CXX) -o $@ $(LDFLAGS) $(OBJECTS)
+	$(CXX) -o $@ $(OBJECTS) $(LDFLAGS)
--- conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp	2007/03/27 02:06:27	1.13.2.1
+++ conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp	2007/10/10 18:10:37	1.13.2.2
@@ -1,824 +1,961 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include "Monitor.h"
 #include "executils.h"
 #include "Logger.h"
 #include "Time.h"
 #include "utils.h"
-#include "Network.h"
 
 #include <sys/poll.h>
 #include <sys/sysinfo.h>
 
 #include <algorithm>
 
-
 using namespace ClusterMonitoring;
 using namespace std;
 
-
-
-#define RG_STATE_STOPPED                110     /** Resource group is stopped */
-#define RG_STATE_STARTING               111     /** Resource is starting */
-#define RG_STATE_STARTED                112     /** Resource is started */
-#define RG_STATE_STOPPING               113     /** Resource is stopping */
-#define RG_STATE_FAILED                 114     /** Resource has failed */
-#define RG_STATE_UNINITIALIZED          115     /** Thread not running yet */
-#define RG_STATE_CHECK                  116     /** Checking status */
-#define RG_STATE_ERROR                  117     /** Recoverable error */
-#define RG_STATE_RECOVER                118     /** Pending recovery */
-#define RG_STATE_DISABLED               119     /** Resource not allowd to run */
-
-
-
-#define EXECUTE_TIMEOUT                 3000
-
-#define CCS_TOOL_PATH                   "/sbin/ccs_tool"
-
-
-static XMLObject 
-merge_xmls(const XMLObject& what, const XMLObject& with);
-static String
-cluster_version();
-static String
-get_cman_tool_path();
-
-
-
-Monitor::Monitor(unsigned short port) :
-  _comm(port, *this),
-  _cl_version(cluster_version()), 
-  _cman_tool_path(get_cman_tool_path()),
-  _cman_locking(_cl_version == "5")
+#define RG_STATE_STOPPED			110		/** Resource group is stopped */
+#define RG_STATE_STARTING			111		/** Resource is starting */
+#define RG_STATE_STARTED			112		/** Resource is started */
+#define RG_STATE_STOPPING			113		/** Resource is stopping */
+#define RG_STATE_FAILED				114		/** Resource has failed */
+#define RG_STATE_UNINITIALIZED		115		/** Thread not running yet */
+#define RG_STATE_CHECK				116		/** Checking status */
+#define RG_STATE_ERROR				117		/** Recoverable error */
+#define RG_STATE_RECOVER			118		/** Pending recovery */
+#define RG_STATE_DISABLED			119		/** Resource not allowd to run */
+#define RG_STATE_MIGRATE			120		/** Resource migrating */
+
+#define EXECUTE_TIMEOUT				3000
+#define CCS_TOOL_PATH				"/sbin/ccs_tool"
+
+static XMLObject merge_xmls(const XMLObject& what, const XMLObject& with);
+static String cluster_version();
+static String get_cman_tool_path();
+
+Monitor::Monitor(unsigned short port, const String& ver) :
+	_comm(port, *this),
+	_cl_version(ver.size() ? ver : cluster_version()),
+	_cman_tool_path(get_cman_tool_path()),
+	_cman_locking(_cl_version == "5")
 {
-  log("Monitor created", LogMonitor);
+	log("Monitor created", LogMonitor);
 }
 
 Monitor::~Monitor()
 {
-  log("Stopping monitoring", LogMonitor);
-  stop();
-  log("Monitoring stopped", LogMonitor);
-  log("Monitor deleted", LogMonitor);
+	log("Stopping monitoring", LogMonitor);
+	stop();
+	log("Monitoring stopped", LogMonitor);
+	log("Monitor deleted", LogMonitor);
 }
 
-
-void 
+void
 Monitor::update_now()
 {
-  try {
-    MutexLocker l(_mutex);
-    String my_nodename, clustername, msg;
-    vector<String> nodenames = get_local_info(my_nodename,
-					      clustername,
-					      msg);
-    msg_arrived(my_nodename, msg);
-    _cluster = merge_data(clustername);
-  } catch ( ... ) {}
+	try {
+		MutexLocker l(_mutex);
+		String my_nodename, clustername, msg;
+		vector<String> nodenames=get_local_info(my_nodename, clustername, msg);
+		msg_arrived(my_nodename, msg);
+		_cluster = merge_data(clustername);
+	} catch (String e) {
+		log(__LINE__ + ": caught exception: " + e, LogCommunicator);
+	} catch ( ... ) {}
 }
 
 void
 Monitor::run()
 {
-  log("Starting communicator", LogCommunicator);
-  _comm.start();
-  while (!shouldStop()) {
-    
-    unsigned int time_beg = time_sec();
-    
-    try {
-      // get local info
-      String my_nodename, clustername, msg;
-      vector<String> nodenames = get_local_info(my_nodename,
-						clustername,
-						msg);
-      
-      // publish it
-      _comm.update_peers(my_nodename, nodenames);
-      _comm.send(msg + '\n');
-      
-      // merge data from all nodes (removing stale entries) and update _cluster
-      {
-	MutexLocker l(_mutex);
-	_cluster = merge_data(clustername);
-      }
-    } catch ( ... ) {
-      MutexLocker l(_mutex);
-      _cluster = counting_auto_ptr<Cluster>();
-    }
-    
-    String msg = String("monitoring iteration took ") + (time_sec() - time_beg) + " seconds";
-    log(msg, LogTime);
-    
-    // wait some time
-    for (int i=0; i<10; i++) {
-      if (shouldStop())
-	break;
-      struct pollfd nothing;
-      poll(&nothing, 0, 500);
-    }
-  }
-  log("Stopping communicator", LogCommunicator);
-  _comm.stop();
-  log("Communicator stopped", LogCommunicator);
-}
+	log("Starting communicator", LogCommunicator);
+	_comm.start();
 
+	while (!shouldStop()) {
+		unsigned int time_beg = time_sec();
+
+		try {
+			// get local info
+			String my_nodename, clustername, msg;
+			vector<String> nodenames = get_local_info(my_nodename,
+											clustername, msg);
+
+			// publish it
+			_comm.update_peers(my_nodename, nodenames);
+			_comm.send(msg + '\n');
+
+			// merge data from all nodes (removing stale entries)
+			// and update _cluster
+			{
+				MutexLocker l(_mutex);
+				_cluster = merge_data(clustername);
+			}
+		} catch (String e) {
+			log(__LINE__ + ": caught exception: " + e, LogCommunicator);
+			MutexLocker l(_mutex);
+			_cluster = counting_auto_ptr<Cluster>();
+		} catch ( ... ) {
+			MutexLocker l(_mutex);
+			_cluster = counting_auto_ptr<Cluster>();
+		}
+
+		String msg = String("monitoring iteration took ")
+						+ (time_sec() - time_beg) + " seconds";
+		log(msg, LogTime);
+
+		// wait some time
+		for (int i = 0 ; i < 10 ; i++) {
+			if (shouldStop())
+				break;
+			struct pollfd nothing;
+			poll(&nothing, 0, 500);
+		}
+	}
+	log("Stopping communicator", LogCommunicator);
+	_comm.stop();
+	log("Communicator stopped", LogCommunicator);
+}
 
 String
 Monitor::request(const String& msg)
 {
-  MutexLocker l(_mutex);
-  if (msg == "GET") {
-    XMLObject def_xml("cluster");
-    def_xml.set_attr("cluster_version", _cl_version);
-    String def(generateXML(def_xml) + "\n");
-    if (_cluster.get() == NULL) 
-      update_now();
-    if (_cluster.get() == NULL) 
-      return def;
-    try {
-      return cluster2xml(*_cluster) + "\n";
-    } catch ( ... ) {
-      return def;
-    }
-  }
-  throw String("invalid request");
+	MutexLocker l(_mutex);
+
+	if (msg == "GET") {
+		XMLObject def_xml("cluster");
+		def_xml.set_attr("cluster_version", _cl_version);
+		String def(generateXML(def_xml) + "\n");
+
+		if (_cluster.get() == NULL)
+			update_now();
+		if (_cluster.get() == NULL)
+			return def;
+
+		try {
+			return cluster2xml(*_cluster) + "\n";
+		} catch (String e) {
+			log(__LINE__ + ": caught exception: " + e, LogCommunicator);
+			return def;
+		} catch ( ... ) {
+			return def;
+		}
+	}
+	throw String("invalid request");
 }
 
-void 
+void
 Monitor::msg_arrived(const String& hostname, const String& msg_in)
 {
-  String msg(msg_in);
-  // strip \n from the beggining
-  while (msg.size())
-    if (msg[0] == '\n')
-      msg = msg.substr(1);
-    else
-      break;
-  
-  try {
-    XMLObject obj = parseXML(msg);
-    if (obj.tag() == "clumond") {
-      String type = obj.get_attr("type");
-      if (type == "clusterupdate")
-	if (obj.children().size() == 1) {
-	  const XMLObject& cluster = *(obj.children().begin());
-	  if (cluster.tag() == "cluster") {
-	    MutexLocker l(_mutex);
-	    pair<unsigned int, XMLObject> data(time_sec(), cluster);
-	    _cache[hostname] = data;
-	  }
-	}
-      // TODO: other msgs
-    }
-  } catch ( ... ) {}
-}
-
-vector<String> 
-Monitor::get_local_info(String& nodename,
-			String& clustername,
-			String& msg)
-{
-  XMLObject cluster(parse_cluster_conf());
-  
-  // nodes
-  vector<String> nodes;
-  for (list<XMLObject>::const_iterator iter = cluster.children().begin();
-       iter != cluster.children().end();
-       iter++)
-    if (iter->tag() == "node")
-      nodes.push_back(iter->get_attr("name"));
-  
-  // clustername
-  clustername = cluster.get_attr("name");
-  
-  // nodename
-  nodename = this->nodename(nodes);
-  
-  try {
-    cluster.set_attr("minQuorum", probe_quorum());
-  } catch ( ... ) {}
-  
-  cluster.set_attr("cluster_version", _cl_version);
-  
-  // insert current node info
-  const vector<String> clustered_nodes = this->clustered_nodes();
-  for (list<XMLObject>::const_iterator iter = cluster.children().begin();
-       iter != cluster.children().end();
-       iter++) {
-    XMLObject& kid = (XMLObject&) *iter;
-    if (kid.tag() == "node") {
-      String name(kid.get_attr("name"));
-      if (name == nodename) {
-	// insert info about this node -> self
-	kid.set_attr("uptime", uptime());
-      }
-      if (find(clustered_nodes.begin(), clustered_nodes.end(), name) != clustered_nodes.end()) {
-	kid.set_attr("online", "true");
-	kid.set_attr("clustered", "true");
-      }
-    }
-  }
-  
-  // insert current service info
-  const vector<XMLObject> services_info = this->services_info();
-  for (vector<XMLObject>::const_iterator iter_i = services_info.begin();
-       iter_i != services_info.end();
-       iter_i++) {
-    const XMLObject& service = *iter_i;
-    for (list<XMLObject>::const_iterator iter_c = cluster.children().begin();
-	 iter_c != cluster.children().end();
-	 iter_c++) {
-      XMLObject& kid = (XMLObject&) *iter_c;
-      if (kid.tag() == "service")
-	if (kid.get_attr("name") == service.get_attr("name")) {
-	  for (map<String, String>::const_iterator iter = service.attrs().begin();
-	       iter != service.attrs().end();
-	       iter++)
-	    kid.set_attr(iter->first, iter->second);
-	}
-    }
-  }
-  
-  // ** return values **
-  
-  // msg
-  XMLObject msg_xml("clumond");
-  msg_xml.set_attr("type", "clusterupdate");
-  msg_xml.add_child(cluster);
-  msg = generateXML(msg_xml);
-  
-  // return nodes - nodename
-  vector<String>::iterator iter = find(nodes.begin(), nodes.end(), nodename);
-  if (iter != nodes.end())
-    nodes.erase(iter);
-  return nodes;
+	String msg(msg_in);
+	// strip \n from the beggining
+
+	while (msg.size()) {
+		if (msg[0] == '\n')
+			msg = msg.substr(1);
+		else
+			break;
+	}
+
+	try {
+		XMLObject obj = parseXML(msg);
+		if (obj.tag() == "clumond") {
+			String type = obj.get_attr("type");
+			if (type == "clusterupdate") {
+				if (obj.children().size() == 1) {
+					const XMLObject& cluster = *(obj.children().begin());
+					if (cluster.tag() == "cluster") {
+						MutexLocker l(_mutex);
+						pair<unsigned int, XMLObject> data(time_sec(), cluster);
+						_cache[hostname] = data;
+					}
+				}
+				// TODO: other msgs
+			}
+		}
+	} catch (String e) {
+		log(__LINE__ + ": caught exception: " + e, LogCommunicator);
+	} catch ( ... ) {}
+}
+
+vector<String>
+Monitor::get_local_info(String& nodename, String& clustername, String& msg)
+{
+	XMLObject cluster(parse_cluster_conf());
+
+	// nodes
+	vector<String> nodes;
+
+	for (list<XMLObject>::const_iterator
+			iter = cluster.children().begin() ;
+			iter != cluster.children().end() ;
+			iter++)
+	{
+		if (iter->tag() == "node")
+			nodes.push_back(iter->get_attr("name"));
+	}
+
+	// clustername
+	clustername = cluster.get_attr("name");
+
+	// nodename
+	nodename = this->nodename(nodes);
+
+	try {
+		cluster.set_attr("minQuorum", probe_quorum());
+	} catch ( ... ) {}
+
+	cluster.set_attr("cluster_version", _cl_version);
+
+	// insert current node info
+	const vector<String> clustered_nodes = this->clustered_nodes();
+	for (list<XMLObject>::const_iterator
+			iter = cluster.children().begin() ;
+			iter != cluster.children().end() ;
+			iter++)
+	{
+		XMLObject& kid = (XMLObject&) *iter;
+		if (kid.tag() == "node") {
+			String name(kid.get_attr("name"));
+			if (name == nodename) {
+				// insert info about this node -> self
+				kid.set_attr("uptime", uptime());
+			}
+
+			if (find(clustered_nodes.begin(), clustered_nodes.end(), name) !=
+				clustered_nodes.end())
+			{
+				kid.set_attr("online", "true");
+				kid.set_attr("clustered", "true");
+			}
+		}
+	}
+
+	// insert current service info
+	const vector<XMLObject> services_info = this->services_info();
+	for (vector<XMLObject>::const_iterator
+			iter_i = services_info.begin() ;
+			iter_i != services_info.end() ;
+			iter_i++)
+	{
+		const XMLObject& service = *iter_i;
+		for (list<XMLObject>::const_iterator
+				iter_c = cluster.children().begin() ;
+				iter_c != cluster.children().end() ;
+				iter_c++)
+		{
+			XMLObject& kid = (XMLObject&) *iter_c;
+			if (kid.tag() == "service") {
+				if (kid.get_attr("name") == service.get_attr("name")) {
+					for (map<String, String>::const_iterator
+							iter = service.attrs().begin() ;
+							iter != service.attrs().end() ;
+							iter++)
+					{
+						kid.set_attr(iter->first, iter->second);
+					}
+				}
+			}
+		}
+	}
+
+	// ** return values **
+
+	// msg
+	XMLObject msg_xml("clumond");
+	msg_xml.set_attr("type", "clusterupdate");
+	msg_xml.add_child(cluster);
+	msg = generateXML(msg_xml);
+
+	// return nodes - nodename
+	vector<String>::iterator iter = find(nodes.begin(), nodes.end(), nodename);
+	if (iter != nodes.end())
+		nodes.erase(iter);
+	return nodes;
 }
 
-XMLObject 
+XMLObject
 Monitor::parse_cluster_conf()
 {
-  XMLObject cluster_conf(readXML("/etc/cluster/cluster.conf"));
-  if (cluster_conf.tag() != "cluster" ||
-      utils::strip(cluster_conf.get_attr("name")).empty() ||
-      utils::strip(cluster_conf.get_attr("config_version")).empty())
-    throw String("parse_cluster_conf(): invalid cluster.conf");
-  
-  XMLObject cluster("cluster");
-  for (map<String, String>::const_iterator iter = cluster_conf.attrs().begin();
-       iter != cluster_conf.attrs().end();
-       iter++)
-    cluster.set_attr(iter->first, iter->second);
-  if (utils::strip(cluster.get_attr("alias")).empty())
-    cluster.set_attr("alias", cluster.get_attr("name"));
-  
-  for (list<XMLObject>::const_iterator iter = cluster_conf.children().begin();
-       iter != cluster_conf.children().end();
-       iter++) {
-    const XMLObject& kid = *iter;
-    if (kid.tag() == "clusternodes") {
-      for (list<XMLObject>::const_iterator iter_n = kid.children().begin();
-	   iter_n != kid.children().end();
-	   iter_n++) {
-	const XMLObject& node_conf = *iter_n;
-	if (node_conf.tag() == "clusternode") {
-	  XMLObject node("node");
-	  for (map<String, String>::const_iterator iter_a = node_conf.attrs().begin();
-	       iter_a != node_conf.attrs().end();
-	       iter_a++)
-	    node.set_attr(iter_a->first, iter_a->second);
-	  cluster.add_child(node);
-	}
-      }
-    } else if (kid.tag() == "rm") {
-      for (list<XMLObject>::const_iterator iter_s = kid.children().begin();
-	   iter_s != kid.children().end();
-	   iter_s++) {
-	const XMLObject& service_conf = *iter_s;
-	if (service_conf.tag() == "service" ||
-	    service_conf.tag() == "vm") {
-	  XMLObject service("service");
-	  for (map<String, String>::const_iterator iter_a = service_conf.attrs().begin();
-	       iter_a != service_conf.attrs().end();
-	       iter_a++)
-	    service.set_attr(iter_a->first, iter_a->second);
-	  if (service_conf.tag() == "vm")
-	    service.set_attr("vm", "true");
-	  else
-	    service.set_attr("vm", "false");
-	  cluster.add_child(service);
-	}
-      }
-    } else if (kid.tag() == "cman") {
-      cluster.set_attr("locking", "cman");
-      if (kid.has_attr("expected_votes"))
-	cluster.set_attr("minQuorum", kid.get_attr("expected_votes"));
-    } else if (kid.tag() == "gulm") {
-      cluster.set_attr("locking", "gulm");
-    }
-  }
-  
-  if (_cl_version == "5")
-    cluster.set_attr("locking", "cman");
-  _cman_locking = (cluster.get_attr("locking") == "cman");
-  
-  return cluster;
+	XMLObject cluster_conf(readXML("/etc/cluster/cluster.conf"));
+	if (cluster_conf.tag() != "cluster" ||
+		utils::strip(cluster_conf.get_attr("name")).empty() ||
+		utils::strip(cluster_conf.get_attr("config_version")).empty())
+	{
+		throw String("parse_cluster_conf(): invalid cluster.conf");
+	}
+
+	XMLObject cluster("cluster");
+	for (map<String, String>::const_iterator
+			iter = cluster_conf.attrs().begin() ;
+			iter != cluster_conf.attrs().end() ;
+			iter++)
+	{
+		cluster.set_attr(iter->first, iter->second);
+	}
+
+	if (utils::strip(cluster.get_attr("alias")).empty())
+		cluster.set_attr("alias", cluster.get_attr("name"));
+
+	for (list<XMLObject>::const_iterator
+		iter = cluster_conf.children().begin() ;
+		iter != cluster_conf.children().end() ;
+		iter++)
+	{
+		const XMLObject& kid = *iter;
+		if (kid.tag() == "clusternodes") {
+			for (list<XMLObject>::const_iterator
+					iter_n = kid.children().begin() ;
+					iter_n != kid.children().end() ;
+					iter_n++)
+			{
+				const XMLObject& node_conf = *iter_n;
+				if (node_conf.tag() == "clusternode") {
+					XMLObject node("node");
+					for (map<String, String>::const_iterator
+							iter_a = node_conf.attrs().begin() ;
+							iter_a != node_conf.attrs().end() ;
+							iter_a++)
+					{
+						node.set_attr(iter_a->first, iter_a->second);
+					}
+					cluster.add_child(node);
+				}
+			}
+		} else if (kid.tag() == "rm") {
+			for (list<XMLObject>::const_iterator
+					iter_s = kid.children().begin() ;
+					iter_s != kid.children().end() ;
+					iter_s++)
+			{
+				const XMLObject& service_conf = *iter_s;
+
+				if (service_conf.tag() == "service" ||
+					service_conf.tag() == "vm")
+				{
+					XMLObject service("service");
+					for (map<String, String>::const_iterator
+						iter_a = service_conf.attrs().begin() ;
+						iter_a != service_conf.attrs().end() ;
+						iter_a++)
+					{
+						service.set_attr(iter_a->first, iter_a->second);
+					}
+
+					if (service_conf.tag() == "vm")
+						service.set_attr("vm", "true");
+					else
+						service.set_attr("vm", "false");
+					cluster.add_child(service);
+				}
+			}
+		} else if (kid.tag() == "cman") {
+			cluster.set_attr("locking", "cman");
+			if (kid.has_attr("expected_votes"))
+				cluster.set_attr("minQuorum", kid.get_attr("expected_votes"));
+		} else if (kid.tag() == "gulm") {
+			cluster.set_attr("locking", "gulm");
+		}
+	}
+
+	if (_cl_version == "5")
+		cluster.set_attr("locking", "cman");
+	_cman_locking = (cluster.get_attr("locking") == "cman");
+
+	return cluster;
 }
 
-counting_auto_ptr<Cluster> 
+counting_auto_ptr<Cluster>
 Monitor::merge_data(const String& clustername)
 {
-  MutexLocker l(_mutex);
-  
-  XMLObject cluster("cluster");
-  cluster.set_attr("name", clustername);
-  cluster.set_attr("config_version", "0");
-  unsigned int config_version = 0;
-  
-  vector<map<String, pair<unsigned int, XMLObject> >::iterator> stales;
-  vector<String> online_nodes;
-  
-  for (map<String, pair<unsigned int, XMLObject> >::iterator iter = _cache.begin();
-       iter != _cache.end();
-       iter++) {
-    if (iter->second.first < time_sec() - 8)
-      stales.push_back(iter);
-    else {
-      online_nodes.push_back(iter->first);
-      const XMLObject& cl2 = iter->second.second;
-      if (cl2.has_attr("name") &&
-	  cl2.get_attr("name") == cluster.get_attr("name")) {
-	unsigned int v;
-	if (sscanf(cl2.get_attr("config_version").c_str(), "%u", &v) != 1)
-	  continue;
-	if (v == config_version)
-	  cluster = merge_xmls(cluster, cl2);
-	else if (v > config_version) {
-	  config_version = v;
-	  cluster = cl2;
-	}
-      }
-    }
-  }
-  for (unsigned int i=0; i<stales.size(); i++)
-    _cache.erase(stales[i]);
-  
-  // cout << "merged data: \n" << generateXML(cluster) << endl;
-  
-  if (_cache.size() == 0)
-    return counting_auto_ptr<Cluster>();
-  
-  // build cluster
-  counting_auto_ptr<Cluster> cluster_ret;
-  String name = cluster.get_attr("name");
-  String alias = cluster.get_attr("alias");
-  String clu_version = cluster.get_attr("cluster_version");
-  unsigned int minQuorum = 0;
-  if (sscanf(cluster.get_attr("minQuorum").c_str(), "%u", &minQuorum) != 1)
-    cluster_ret = counting_auto_ptr<Cluster> (new Cluster(name, alias, clu_version));
-  else
-    cluster_ret = counting_auto_ptr<Cluster> (new Cluster(name, alias, clu_version, minQuorum));
-  // nodes
-  for (list<XMLObject>::const_iterator iter = cluster.children().begin();
-       iter != cluster.children().end();
-       iter++) {
-    const XMLObject& obj = *iter;
-    if (obj.tag() == "node") {
-      String node_name = obj.get_attr("name");
-      if (node_name.empty())
-	throw String("merge_data(): node missing 'name' attr");
-      unsigned int votes;
-      if (sscanf(obj.get_attr("votes").c_str(), "%u", &votes) != 1)
-	votes = 1;
-      bool online;
-      if (obj.has_attr("online"))
-	online = obj.get_attr("online") == "true";
-      else
-	online = find(online_nodes.begin(), online_nodes.end(), node_name) != online_nodes.end();
-      bool clustered = obj.get_attr("clustered") == "true";
-      String uptime = obj.get_attr("uptime");
-      // add node to cluster
-      cluster_ret->addNode(node_name, votes, online, clustered, uptime);
-    }
-  }
-  // services
-  for (list<XMLObject>::const_iterator iter = cluster.children().begin();
-       iter != cluster.children().end();
-       iter++) {
-    const XMLObject& obj = *iter;
-    if (obj.tag() == "service") {
-      // name
-      String service_name = obj.get_attr("name");
-      if (service_name.empty())
-	throw String("merge_data(): service missing 'name' attr");
-      bool running = obj.get_attr("running") == "true";
-      String nodename = obj.get_attr("nodename");
-      if (running && nodename.empty())
-	throw String("merge_data(): running service missing 'nodename' attr");
-      bool failed = obj.get_attr("failed") == "true";
-      bool autostart = obj.get_attr("autostart") != "0";
-      String time_since_transition = obj.get_attr("time_since_transition");
-      // add service to cluster
-      cluster_ret->addService(service_name, nodename, failed, autostart, time_since_transition);
-    }
-  }
-  
-  return cluster_ret;
+	MutexLocker l(_mutex);
+
+	XMLObject cluster("cluster");
+	cluster.set_attr("name", clustername);
+	cluster.set_attr("config_version", "0");
+	unsigned int config_version = 0;
+
+	vector<map<String, pair<unsigned int, XMLObject> >::iterator> stales;
+	vector<String> online_nodes;
+
+	for (map<String, pair<unsigned int, XMLObject> >::iterator
+			iter = _cache.begin() ;
+			iter != _cache.end() ;
+			iter++)
+	{
+		if (iter->second.first < time_sec() - 8)
+			stales.push_back(iter);
+		else {
+			online_nodes.push_back(iter->first);
+			const XMLObject& cl2 = iter->second.second;
+			if (cl2.has_attr("name") &&
+				cl2.get_attr("name") == cluster.get_attr("name"))
+			{
+				unsigned int v;
+				int ret;
+
+				ret = sscanf(cl2.get_attr("config_version").c_str(), "%u", &v);
+				if (ret != 1)
+					continue;
+
+				if (v == config_version)
+					cluster = merge_xmls(cluster, cl2);
+				else if (v > config_version) {
+					config_version = v;
+					cluster = cl2;
+				}
+			}
+		}
+	}
+
+	for (unsigned int i = 0 ; i < stales.size() ; i++)
+		_cache.erase(stales[i]);
+
+	if (_cache.size() == 0)
+		return counting_auto_ptr<Cluster>();
+
+	// build cluster
+	counting_auto_ptr<Cluster> cluster_ret;
+	String name = cluster.get_attr("name");
+	String alias = cluster.get_attr("alias");
+	String clu_version = cluster.get_attr("cluster_version");
+	unsigned int minQuorum = 0;
+
+	if (sscanf(cluster.get_attr("minQuorum").c_str(), "%u", &minQuorum) != 1) {
+		cluster_ret =
+			counting_auto_ptr<Cluster> (new Cluster(name, alias, clu_version));
+	} else {
+		cluster_ret = counting_auto_ptr<Cluster> (new Cluster(name, alias, clu_version, minQuorum));
+	}
+
+	// nodes
+	for (list<XMLObject>::const_iterator
+			iter = cluster.children().begin() ;
+			iter != cluster.children().end() ;
+			iter++)
+	{
+		const XMLObject& obj = *iter;
+		if (obj.tag() == "node") {
+			String node_name = obj.get_attr("name");
+			if (node_name.empty())
+				throw String("merge_data(): node missing 'name' attr");
+			unsigned int votes;
+			if (sscanf(obj.get_attr("votes").c_str(), "%u", &votes) != 1)
+				votes = 1;
+			bool online;
+			if (obj.has_attr("online"))
+				online = obj.get_attr("online") == "true";
+			else
+				online = find(online_nodes.begin(), online_nodes.end(), node_name) != online_nodes.end();
+
+			bool clustered = obj.get_attr("clustered") == "true";
+			String uptime = obj.get_attr("uptime");
+
+			// add node to cluster
+			cluster_ret->addNode(node_name, votes, online, clustered, uptime);
+		}
+	}
+
+	// services
+	for (list<XMLObject>::const_iterator
+			iter = cluster.children().begin() ;
+			iter != cluster.children().end() ;
+			iter++)
+	{
+		const XMLObject& obj = *iter;
+		if (obj.tag() == "service") {
+			// name
+			String service_name = obj.get_attr("name");
+			if (service_name.empty())
+				throw String("merge_data(): service missing 'name' attr");
+
+			bool running = obj.get_attr("running") == "true";
+			String nodename = obj.get_attr("nodename");
+			if (running && nodename.empty())
+				throw String("merge_data(): running service missing 'nodename' attr");
+			bool failed = obj.get_attr("failed") == "true";
+			bool autostart = obj.get_attr("autostart") != "0";
+			String time_since_trans = obj.get_attr("time_since_transition");
+
+			// add service to cluster
+			cluster_ret->addService(service_name, nodename, failed,
+				autostart, time_since_trans);
+		}
+	}
+
+	return cluster_ret;
 }
 
 
 /*
-bool 
+bool
 Monitor::clustered()
 {
-  String out, err;
-  int status;
-  vector<String> args;
-  args.push_back("members");
-  if (execute("/sbin/magma_tool", args, out, err, status, EXECUTE_TIMEOUT))
-    throw String("clustered(): missing magma_tool");
-  if (status)
-    return false;
-  
-  // look for 'Connect failure' substring
-  if (out.find("Connect failure") != out.npos)
-    return false;
-  else
-    return true;
+	String out, err;
+	int status;
+	vector<String> args;
+
+	args.push_back("members");
+	if (execute("/sbin/magma_tool", args, out, err, status, EXECUTE_TIMEOUT))
+		throw String("clustered(): missing magma_tool");
+	if (status)
+		return false;
+
+	// look for 'Connect failure' substring
+	if (out.find("Connect failure") != out.npos)
+		return false;
+	else
+		return true;
 }
 */
 
 /*
-bool 
+bool
 Monitor::quorate()
 {
-  String out, err;
-  int status;
-  vector<String> args;
-  args.push_back("quorum");
-  if (execute("/sbin/magma_tool", args, out, err, status, EXECUTE_TIMEOUT))
-    throw String("quorate(): missing magma_tool");
-  if (status)
-    return false;
-  
-  // look for 'Quorate' substring
-  if (out.find("Quorate") != out.npos)
-    return true;
-  else
-    return false;
+	String out, err;
+	int status;
+	vector<String> args;
+
+	args.push_back("quorum");
+	if (execute("/sbin/magma_tool", args, out, err, status, EXECUTE_TIMEOUT))
+		throw String("quorate(): missing magma_tool");
+	if (status)
+		return false;
+
+	// look for 'Quorate' substring
+	if (out.find("Quorate") != out.npos)
+		return true;
+	else
+		return false;
 }
 */
 
-vector<String> 
+vector<String>
 Monitor::clustered_nodes()
 {
-  vector<String> running;
-  
-  if (_cman_locking) {
-    String out, err;
-    int status;
-    vector<String> args;
-    args.push_back("nodes");
-    if (execute(_cman_tool_path, args, out, err, status, EXECUTE_TIMEOUT))
-      throw String("clustered_nodes(): missing cman_tool");
-    if (status)
-      return vector<String>();
-    vector<String>::size_type Sts_idx = 0;
-    vector<String> lines = utils::split(out, "\n");
-    for (vector<String>::iterator iter = lines.begin();
-	 iter != lines.end();
-	 iter++) {
-      vector<String> words = utils::split(utils::strip(*iter));
-      if (words.size() < Sts_idx+1)
-	continue;
-      if (words[0] == "Node") {
-	// update Sts_idx
-	for (vector<String>::size_type i=0; i<words.size(); i++) 
-	  if (words[i] == "Sts")
-	    Sts_idx = i;
-      } else if (words[Sts_idx] == "M")
-	running.push_back(words.back());
-    }
-  } else if (_cl_version == "4") {
-    String out, err;
-    int status;
-    vector<String> args;
-    args.push_back("members");
-    if (execute("/sbin/magma_tool", args, out, err, status, EXECUTE_TIMEOUT))
-      throw String("clustered_nodes(): missing magma_tool");
-    if (status)
-      return vector<String>();
-    vector<String> lines = utils::split(out, "\n");
-    for (vector<String>::iterator iter = lines.begin();
-	 iter != lines.end();
-	 iter++) {
-      String line = utils::strip(*iter);
-      if (line.find("Member ID") != line.npos) {
-	String t = line.substr(line.find(": ") + 2);
-	String::size_type idx = t.find(',');
-	String name = t.substr(0, idx);
-	String rest = t.substr(idx);
-	if (rest.find("UP") != rest.npos)
-	  running.push_back(name);
-      }
-    }
-  } else 
-    throw String("cluster version ") + _cl_version + " not supported";
-  
-  return running;
+	vector<String> running;
+
+	if (_cman_locking) {
+		int ret_nodes = -1;
+		int ret;
+		cman_node_t *node_array;
+
+		cman_handle_t ch = cman_init(NULL);
+		if (ch == NULL)
+			throw String("Unable to communicate with cman");
+
+		ret = cman_get_node_count(ch);
+		if (ret <= 0) {
+			cman_finish(ch);
+			throw String("Unable to communicate with cman");
+		}
+	
+		node_array = (cman_node_t *) malloc(sizeof(*node_array) * ret);
+		if (node_array == NULL) {
+			cman_finish(ch);
+			throw String("Out of memory");
+		}
+
+		if (cman_get_nodes(ch, ret, &ret_nodes, node_array) != 0) {
+			cman_finish(ch);
+			free(node_array);
+			throw String("Unable to communicate with cman");
+		}
+		cman_finish(ch);
+
+		try {
+			for (int i = 0 ; i < ret_nodes ; i++) {
+				if (node_array[i].cn_nodeid == 0) {
+					/* qdisk */;
+					continue;
+				}
+				if (node_array[i].cn_member)
+					running.push_back(String(node_array[i].cn_name));
+			}
+		} catch (...) {
+			free(node_array);
+			throw;
+		}
+		free(node_array);
+	} else if (_cl_version == "4") {
+		String out, err;
+		int status;
+		vector<String> args;
+
+		args.push_back("members");
+		if (execute("/sbin/magma_tool", args, out, err, status,EXECUTE_TIMEOUT))
+			throw String("clustered_nodes(): missing magma_tool");
+		if (status)
+			return vector<String>();
+
+		vector<String> lines = utils::split(out, "\n");
+		for (vector<String>::iterator
+				iter = lines.begin() ;
+				iter != lines.end() ;
+				iter++)
+		{
+			String line = utils::strip(*iter);
+			if (line.find("Member ID") != line.npos) {
+				String t = line.substr(line.find(": ") + 2);
+				String::size_type idx = t.find(',');
+				String name = t.substr(0, idx);
+				String rest = t.substr(idx);
+
+				if (rest.find("UP") != rest.npos)
+					running.push_back(name);
+			}
+		}
+	} else
+		throw String("cluster version ") + _cl_version + " not supported";
+
+	return running;
 }
 
 String
 Monitor::nodename(const vector<String>& nodenames)
 {
-  if (_cman_locking) {
-    String out, err;
-    int status;
-    vector<String> args(1, "status");
-    if (execute(_cman_tool_path, args, out, err, status, EXECUTE_TIMEOUT))
-      throw String("nodename(): missing ") + _cman_tool_path;
-    if (status)
-      // cman not running, match using address
-      out.clear();
-    
-    vector<String> lines = utils::split(utils::strip(out), "\n");
-    for (vector<String>::const_iterator iter = lines.begin();
-	 iter != lines.end();
-	 iter++) {
-      vector<String> words = utils::split(utils::strip(*iter));
-      if (words.size() != 3)
-	continue;
-      if (words[0] + " " + words[1] == "Node name:")
-	return words[2];
-    }
-  }
-  
-  String out, err;
-  int status;
-  if (execute("/sbin/ifconfig", vector<String>(), out, err, status, EXECUTE_TIMEOUT))
-    throw String("nodename(): missing ifconfig");
-  if (status)
-    throw String("nodename(): ifconfig failed???");
-  
-  for (vector<String>::const_iterator iter = nodenames.begin();
-       iter != nodenames.end();
-       iter++) {
-    const String& nodename = *iter;
-    vector<String> ips = Network::name2IP(nodename);
-    for (vector<String>::iterator iter_ip = ips.begin();
-	 iter_ip != ips.end();
-	 iter_ip++) {
-      if (out.find(*iter_ip) != out.npos)
-	return nodename;
-    }
-  }
-  
-  return "";
+	struct ifaddrs *if_list = NULL;
+	struct addrinfo hints;
+
+	if (_cman_locking) {
+		cman_handle_t ch = cman_init(NULL);
+		if (ch != NULL) {
+			cman_node_t this_node;
+			if (cman_get_node(ch, CMAN_NODEID_US, &this_node) == 0) {
+				cman_finish(ch);
+				return String(this_node.cn_name);
+			}
+			cman_finish(ch);
+		}
+	}
+
+	if (getifaddrs(&if_list) != 0) 
+		throw ("Unable to determine local node name");
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_INET;
+
+	for (vector<String>::const_iterator
+			iter = nodenames.begin() ;
+			iter != nodenames.end() ;
+			iter++)
+	{
+		struct addrinfo *res;
+		if (getaddrinfo(iter->c_str(), NULL, &hints, &res) == 0) {
+			struct addrinfo *ai;
+			for (ai = res ; ai != NULL ; ai = ai->ai_next) {
+				struct ifaddrs *cur;
+
+				for (cur = if_list ; cur != NULL ; cur = cur->ifa_next) {
+					if (!cur->ifa_addr || !(cur->ifa_flags & IFF_UP))
+						continue;
+					if (cur->ifa_flags & IFF_LOOPBACK)
+						continue;
+					if (cur->ifa_addr->sa_family != AF_INET)
+						continue;
+					if (!memcmp(cur->ifa_addr, ai->ai_addr, ai->ai_addrlen)) {
+						freeaddrinfo(res);
+						freeifaddrs(if_list);
+						return *iter;
+					}
+				}
+			}
+			freeaddrinfo(res);
+		}
+	}
+	freeifaddrs(if_list);
+
+	return "";
 }
 
-vector<XMLObject> 
+vector<XMLObject>
 Monitor::services_info()
 {
-  vector<XMLObject> services;
-  
-  try {
-    String out, err;
-    int status;
-    vector<String> args;
-    
-    bool fast_available = false;  // clustat -f ?
-    args.push_back("-h");
-    if (execute("/usr/sbin/clustat", args, out, err, status, EXECUTE_TIMEOUT))
-      throw String("services_info(): missing clustat");
-    if (status)
-      throw String("services_info(): `clustat -h` failed");
-    if (out.find("-f") != out.npos)
-      fast_available = true;
-    
-    args.clear();
-    if (fast_available)
-      args.push_back("-f");
-    args.push_back("-x");
-    if (execute("/usr/sbin/clustat", args, out, err, status, EXECUTE_TIMEOUT))
-      throw String("services_info(): missing clustat");
-    if (status)
-      throw String("services_info(): `clustat -x` failed");
-    
-    XMLObject clustat = parseXML(out);
-    for (list<XMLObject>::const_iterator iter_c = clustat.children().begin();
-	 iter_c != clustat.children().end();
-	 iter_c++) {
-      if (iter_c->tag() == "groups") {
-	const XMLObject& groups = *iter_c;
-	for (list<XMLObject>::const_iterator iter = groups.children().begin();
-	     iter != groups.children().end();
-	     iter++) {
-	  const XMLObject& group = *iter;
-	  XMLObject service("service");
-	  service.set_attr("vm", "false");
-	  
-	  // name
-	  String name(group.get_attr("name"));
-	  String::size_type idx = name.find(":");
-	  if (idx != name.npos) {
-	    if (name.substr(0, idx) == "vm")
-	      service.set_attr("vm", "true");
-	    name = name.substr(idx + 1);
-	  }
-	  service.set_attr("name", name);
-	  
-	  
-	  // state
-	  bool failed, running;
-	  int state_code;
-	  if (sscanf(group.get_attr("state").c_str(), "%i", &state_code) != 1)
-	    continue;
-	  switch (state_code) {
-	  case RG_STATE_STOPPED:
-	  case RG_STATE_STOPPING:
-	  case RG_STATE_UNINITIALIZED:
-	  case RG_STATE_ERROR:
-	  case RG_STATE_RECOVER:
-	  case RG_STATE_DISABLED:
-	    running = failed = false;
-	    break;
-	  case RG_STATE_FAILED:
-	    running = false;
-	    failed = true;
-	    break;
-	  case RG_STATE_STARTING:
-	  case RG_STATE_STARTED:
-	  case RG_STATE_CHECK:
-	    running = true;
-	    failed = false;
-	    break;
-	  default:
-	    continue;
-	  }
-	  service.set_attr("failed", (failed)? "true" : "false");
-	  service.set_attr("running", (running)? "true" : "false");
-	  if (running)
-	    service.set_attr("nodename", group.get_attr("owner"));
-	  
-	  // last_transition
-	  time_t since = (time_t) utils::to_long(group.get_attr("last_transition"));
-	  if (since != 0) {
-	    time_t current = (time_t) time_sec();
-	    service.set_attr("time_since_transition", utils::to_string(current - since));
-	  }
-	  
-	  services.push_back(service);
-	}
-      }
-    }
-  } catch ( ... ) {}
-  
-  return services;
+	vector<XMLObject> services;
+
+	try {
+		String out, err;
+		int status;
+		vector<String> args;
+
+		args.clear();
+		args.push_back("-f");
+		args.push_back("-x");
+		if (execute("/usr/sbin/clustat", args, out, err,
+			status, EXECUTE_TIMEOUT))
+		{
+			throw String("services_info(): missing clustat");
+		}
+
+		if (status)
+			throw String("services_info(): `clustat -x` failed: " + err);
+
+		XMLObject clustat = parseXML(out);
+		for (list<XMLObject>::const_iterator
+				iter_c = clustat.children().begin() ;
+				iter_c != clustat.children().end() ;
+				iter_c++)
+		{
+			if (iter_c->tag() == "groups") {
+				const XMLObject& groups = *iter_c;
+				for (list<XMLObject>::const_iterator
+						iter = groups.children().begin() ;
+						iter != groups.children().end() ;
+						iter++)
+				{
+					const XMLObject& group = *iter;
+					XMLObject service("service");
+					service.set_attr("vm", "false");
+
+					// name
+					String name(group.get_attr("name"));
+					String::size_type idx = name.find(":");
+					if (idx != name.npos) {
+						if (name.substr(0, idx) == "vm")
+							service.set_attr("vm", "true");
+						name = name.substr(idx + 1);
+					}
+					service.set_attr("name", name);
+
+					// state
+					bool failed, running;
+					int state_code;
+					if (sscanf(group.get_attr("state").c_str(), "%i",
+						&state_code) != 1)
+					{
+						continue;
+					}
+					switch (state_code) {
+						case RG_STATE_STOPPED:
+						case RG_STATE_STOPPING:
+						case RG_STATE_UNINITIALIZED:
+						case RG_STATE_ERROR:
+						case RG_STATE_RECOVER:
+						case RG_STATE_DISABLED:
+							running = failed = false;
+							break;
+
+						case RG_STATE_FAILED:
+							running = false;
+							failed = true;
+							break;
+
+						case RG_STATE_MIGRATE:
+						case RG_STATE_STARTING:
+						case RG_STATE_STARTED:
+						case RG_STATE_CHECK:
+							running = true;
+							failed = false;
+							break;
+
+						default:
+							continue;
+					}
+					service.set_attr("failed", (failed) ? "true" : "false");
+					service.set_attr("running", (running) ? "true" : "false");
+					if (running)
+						service.set_attr("nodename", group.get_attr("owner"));
+
+					// last_transition
+					time_t since = (time_t)
+						utils::to_long(group.get_attr("last_transition"));
+					if (since != 0) {
+						time_t current = (time_t) time_sec();
+						service.set_attr("time_since_transition",
+							utils::to_string(current - since));
+					}
+
+					services.push_back(service);
+				}
+			}
+		}
+	} catch (String e) {
+		log(__LINE__ + ": caught exception: " + e, LogCommunicator);
+	} catch ( ... ) {}
+
+	return services;
 }
 
 String
 Monitor::uptime() const
 {
-  struct sysinfo s_info;
-  if (sysinfo(&s_info))
-    return "";
-  return String(utils::to_string(s_info.uptime));
-}
-
-String 
-Monitor::probe_quorum() const
-{
-  if (_cman_locking) {
-    int status;
-    String out, err;
-    vector<String> args;
-    args.push_back("status");
-    if (execute(_cman_tool_path, args, out, err, status, EXECUTE_TIMEOUT))
-      throw _cman_tool_path + " status failed";
-    if (status)
-      throw _cman_tool_path + " status failed";
-    
-    vector<String> lines = utils::split(out, "\n");
-    for (vector<String>::const_iterator iter = lines.begin();
-	 iter != lines.end();
-	 iter++) {
-      vector<String> words = utils::split(*iter);
-      if (words.size() < 2)
-	continue;
-      if (words[0] == "Quorum:")
-	return words[1];
-    }
-  } else {
-    // TODO: implement quorum detection on GULM clusters
-    throw String("GULM quorum detection not yet implemented");
-  }
-  throw String("quorum not found");
+	struct sysinfo s_info;
+	if (sysinfo(&s_info))
+		return "";
+	return String(utils::to_string(s_info.uptime));
 }
-  
 
 String
-cluster_version()
+Monitor::probe_quorum()
 {
-  int status;
-  String out, err;
-  vector<String> args;
-  args.push_back("-V");
-  if (execute(CCS_TOOL_PATH, args, out, err, status, EXECUTE_TIMEOUT))
-    throw String("missing ") + CCS_TOOL_PATH;
-  if (status)
-    throw String(CCS_TOOL_PATH) + " -V failed";
-  
-  vector<String> words = utils::split(utils::strip(out));
-  if (words.size() < 2)
-    throw String(CCS_TOOL_PATH) + " -V failed";
-  if (utils::strip(words[0]) != CCS_TOOL_PATH)
-    throw String(CCS_TOOL_PATH) + " -V failed";
-  String version = utils::strip(words[1]);
-  if (version.size() < 5)
-    throw String(CCS_TOOL_PATH) + ": unrecognizable version format";
-  if (version[0] == '1')
-    return "4";
-  else if (version[0] == '2')
-    return "5";
-  else
-    throw String(CCS_TOOL_PATH) + ": unsupported version";
+	if (_cman_locking) {
+		String ret;
+
+		cman_handle_t ch = cman_init(NULL);
+		if (ch == NULL) {
+			cman_finish(ch);
+			throw String("quorum not found");
+		}
+
+		if (cman_is_quorate(ch))
+			ret = "Quorate";
+		else
+			ret = "Not Quorate";
+
+		cman_finish(ch);
+		return ret;
+	} else {
+		// TODO: implement quorum detection on GULM clusters
+		throw String("GULM quorum detection not yet implemented");
+	}
+	throw String("quorum not found");
 }
 
+String
+cluster_version()
+{
+	cman_handle_t ch = cman_init(NULL);
+
+	if (ch != NULL) {
+		int ret;
+		cman_version_t cman_version;
+		char *clu_version = "";
+
+	    ret = cman_get_version(ch, &cman_version);
+		if (ret >= 0) {
+			if (cman_version.cv_major == 6)
+				clu_version = "5";
+			else if (cman_version.cv_major == 5)
+				clu_version = "4";
+			else {
+				char version[32];
+				snprintf(version, sizeof(version), "%d.%d.%d",
+					cman_version.cv_major, cman_version.cv_minor,
+					cman_version.cv_patch);
+				cman_finish(ch);
+				throw "unsupported cluster version: " + String(version);
+			}
+		}
+		cman_finish(ch);
+		return (clu_version);
+	}
+
+	int status;
+	String out, err;
+	vector<String> args;
+
+	args.push_back("-V");
+	if (execute(CCS_TOOL_PATH, args, out, err, status, EXECUTE_TIMEOUT))
+		throw String("missing ") + CCS_TOOL_PATH;
+
+	if (status)
+		throw String(CCS_TOOL_PATH) + " -V failed: " + out + " / " + err;
+
+	vector<String> words = utils::split(utils::strip(out));
+	if (words.size() < 2)
+		throw String(CCS_TOOL_PATH) + " -V failed: " + out + " / " + err;
+
+	if (utils::strip(words[0]) != CCS_TOOL_PATH)
+		throw String(CCS_TOOL_PATH) + " -V failed: " + out + " / " + err;
+
+	String version = utils::strip(words[1]);
+	if (version.size() < 5) {
+		throw String(CCS_TOOL_PATH)
+				+ ": unrecognizable version format: " + version;
+	}
+
+	if (version[0] == '1')
+		return "4";
+	else if (version[0] == '2')
+		return "5";
+	else
+		throw String(CCS_TOOL_PATH) + ": unsupported version: " + version[0];
+}
 
 XMLObject
 merge_xmls(const XMLObject& what, const XMLObject& with)
 {
-  if (what.tag() != with.tag())
-    throw String("merge_xmls(): tag mismatch");
-  
-  XMLObject new_xml(what.tag());
-  for (map<String, String>::const_iterator iter = what.attrs().begin();
-       iter != what.attrs().end();
-       iter++)
-    new_xml.set_attr(iter->first, iter->second);
-  for (map<String, String>::const_iterator iter = with.attrs().begin();
-       iter != with.attrs().end();
-       iter++)
-    new_xml.set_attr(iter->first, iter->second);
-  
-  list<XMLObject> kids_left = with.children();
-  
-  for (list<XMLObject>::const_iterator iter_o = what.children().begin();
-       iter_o != what.children().end();
-       iter_o++) {
-    XMLObject new_kid(*iter_o);
-    for (list<XMLObject>::const_iterator iter = with.children().begin();
-	 iter != with.children().end();
-	 iter++) {
-      const XMLObject& kid = *iter;
-      if (kid.tag() == new_kid.tag() &&
-	  kid.has_attr("name") && 
-	  new_kid.has_attr("name") &&
-	  kid.get_attr("name") == new_kid.get_attr("name")) {
-	// same tag and name -->> merge
-	new_kid = merge_xmls(new_kid, kid);
-	kids_left.remove(kid);
-      }
-    }
-    new_xml.add_child(new_kid);
-  }
-  
-  for (list<XMLObject>::const_iterator iter = kids_left.begin();
-       iter != kids_left.end();
-       iter++)
-    new_xml.add_child(*iter);
-  
-  return new_xml;
-}
+	if (what.tag() != with.tag())
+		throw String("merge_xmls(): tag mismatch");
+
+	XMLObject new_xml(what.tag());
+	for (map<String, String>::const_iterator
+		iter = what.attrs().begin() ;
+		iter != what.attrs().end() ;
+		iter++)
+	{
+		new_xml.set_attr(iter->first, iter->second);
+		for (map<String, String>::const_iterator
+				iter = with.attrs().begin() ;
+				iter != with.attrs().end() ;
+				iter++)
+		{
+			new_xml.set_attr(iter->first, iter->second);
+		}
+	}
 
+	list<XMLObject> kids_left = with.children();
 
+	for (list<XMLObject>::const_iterator
+			iter_o = what.children().begin() ;
+			iter_o != what.children().end() ;
+			iter_o++)
+	{
+		XMLObject new_kid(*iter_o);
+		for (list<XMLObject>::const_iterator
+				iter = with.children().begin() ;
+				iter != with.children().end() ;
+				iter++)
+		{
+			const XMLObject& kid = *iter;
+			if (kid.tag() == new_kid.tag() &&
+				kid.has_attr("name") &&
+				new_kid.has_attr("name") &&
+				kid.get_attr("name") == new_kid.get_attr("name"))
+			{
+				// same tag and name -->> merge
+				new_kid = merge_xmls(new_kid, kid);
+				kids_left.remove(kid);
+			}
+		}
+		new_xml.add_child(new_kid);
+	}
+
+	for (list<XMLObject>::const_iterator
+			iter = kids_left.begin() ;
+			iter != kids_left.end() ;
+			iter++)
+	{
+		new_xml.add_child(*iter);
+	}
+
+	return new_xml;
+}
 
 String
 get_cman_tool_path()
 {
-  String path = "/sbin/cman_tool";
-  if (access(path.c_str(), X_OK)) 
-    path = "/usr/sbin/cman_tool";
-  return path;
+	String path = "/sbin/cman_tool";
+	if (access(path.c_str(), X_OK))
+		path = "/usr/sbin/cman_tool";
+	return path;
 }
--- conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h	2007/03/27 02:06:27	1.5.4.1
+++ conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h	2007/10/10 18:10:37	1.5.4.2
@@ -1,28 +1,27 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
-#ifndef Monitor_h
-#define Monitor_h
+#ifndef __CONGA_MODCLUSTERD_MONITOR_H
+#define __CONGA_MODCLUSTERD_MONITOR_H
 
 #include "String.h"
 #include <map>
@@ -36,63 +35,62 @@
 namespace ClusterMonitoring
 {
 
+extern "C" {
+#	include <sys/socket.h>
+#	include <netdb.h>
+#	include <arpa/inet.h>
+#	include <net/if.h>
+#	include <ifaddrs.h>
+#	include <libcman.h>
+}
 
 class Monitor : public Thread, public CommDP
 {
- public:
-  Monitor(unsigned short port);
-  virtual ~Monitor();
-  
-  String request(const String&);
-  
-  virtual void msg_arrived(const String& host,
-			   const String& msg);
-  
- protected:
-  virtual void run();
- private:
-  
-  Mutex _mutex; // _cluster and _cache
-  counting_auto_ptr<Cluster> _cluster;
-  std::map<String, std::pair<unsigned int, XMLObject> > _cache;
-  
-  Communicator _comm;
-  
-  /* 
-     cluster versions:
-     RHEL3              = "3"
-     RHEL4, FC4, FC5    = "4"
-     RHEL5, FC6         = "5"
-  */
-  const String _cl_version;
-  
-  const String _cman_tool_path;
-  
-  bool _cman_locking;
-  
-  void update_now();
-  
-  // return (nodenames - my_nodename)
-  std::vector<String> get_local_info(String& nodename,
-				     String& clustername,
-				     String& msg);
-  counting_auto_ptr<Cluster> merge_data(const String& clustername);
-  
-  XMLObject parse_cluster_conf();
-  //  bool clustered();
-  //  bool quorate();
-  String nodename(const std::vector<String>& nodenames);
-  std::vector<String> clustered_nodes();
-  std::vector<XMLObject> services_info();
-  
-  String uptime() const;
-  
-  String probe_quorum() const;
-  
-};  // class Monitor
+	public:
+		Monitor(unsigned short port, const String& cluster_version);
+		virtual ~Monitor();
+
+		String request(const String&);
+
+		virtual void msg_arrived(const String& host, const String& msg);
+
+	protected:
+		virtual void run();
+
+	private:
+		Mutex _mutex; // _cluster and _cache
+		counting_auto_ptr<Cluster> _cluster;
+		std::map<String, std::pair<unsigned int, XMLObject> > _cache;
+		Communicator _comm;
+
+		/*
+		** cluster versions:
+		**	RHEL3			= "3"
+		**	RHEL4, FC4, FC5	= "4"
+		**	RHEL5, FC6		= "5"
+		*/
+		const String _cl_version;
+		const String _cman_tool_path;
+		bool _cman_locking;
+		void update_now();
+
+		// return (nodenames - my_nodename)
+		std::vector<String> get_local_info(	String& nodename,
+											String& clustername,
+											String& msg);
+		counting_auto_ptr<Cluster> merge_data(const String& clustername);
+		XMLObject parse_cluster_conf();
+		//bool clustered();
+		//bool quorate();
+		String probe_quorum();
+		String nodename(const std::vector<String>& nodenames);
+		std::vector<String> clustered_nodes();
+		std::vector<XMLObject> services_info();
 
+		String uptime() const;
+};
 
-};  // namespace ClusterMonitoring
 
+};
 
-#endif  // Monitor_h
+#endif
--- conga/ricci/modules/cluster/clumon/src/daemon/Peer.cpp	2006/10/14 18:00:02	1.3
+++ conga/ricci/modules/cluster/clumon/src/daemon/Peer.cpp	2007/10/10 18:10:37	1.3.4.1
@@ -1,26 +1,25 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include "Peer.h"
 #include "Logger.h"
 
@@ -30,85 +29,86 @@
 
 
 Peer::Peer() :
-  _sock(new ClientSocket()),
-  _in(new String()),
-  _out(new String())
+	_sock(new ClientSocket()),
+	_in(new String()),
+	_out(new String())
 {}
 
 Peer::Peer(const String& hostname, const ClientSocket& sock) :
-  _sock(new ClientSocket(sock)),
-  _hostname(hostname),
-  _in(new String()),
-  _out(new String())
+	_sock(new ClientSocket(sock)),
+	_hostname(hostname),
+	_in(new String()),
+	_out(new String())
 {
-  _sock->nonblocking(true);
+	_sock->nonblocking(true);
 }
 
 Peer::Peer(const String& hostname, unsigned short port) :
-  _sock(new ClientSocket(hostname, port)),
-  _hostname(hostname),
-  _in(new String()),
-  _out(new String())
+	_sock(new ClientSocket(hostname, port)),
+	_hostname(hostname),
+	_in(new String()),
+	_out(new String())
 {
-  _sock->nonblocking(true);
+	_sock->nonblocking(true);
 }
 
 Peer::~Peer()
 {}
 
-
-bool 
+bool
 Peer::operator== (const Peer& p) const
 {
-  return (_in == p._in &&
-	  _out == p._out &&
-	  _sock == p._sock &&
-	  _hostname == p._hostname);
+	return (_in == p._in &&
+			_out == p._out &&
+			_sock == p._sock &&
+			_hostname == p._hostname);
 }
 
-void 
+void
 Peer::send()
 {
-  if (_out->empty())
-    return;
-  log("sending data to " + _hostname, LogTransfer);
-  String rest = _sock->send(*_out);
-  *_out = rest;
+	if (_out->empty())
+		return;
+
+	log("sending data to " + _hostname, LogTransfer);
+	String rest = _sock->send(*_out);
+	*_out = rest;
 }
 
 vector<String>
 Peer::receive()
 {
-  log("receiving data from " + _hostname, LogTransfer);
-  
-  String& in = *_in;
-  in += _sock->recv();
-  
-  vector<String> ret;
-  while (true) {
-    String::size_type idx = in.find("\n\n");
-    if (idx == in.npos)
-      return ret;
-    idx += 2;
-    ret.push_back(in.substr(0, idx));
-    in = in.substr(idx);
-  }
+	log("receiving data from " + _hostname, LogTransfer);
+
+	String& in = *_in;
+	in += _sock->recv();
+
+	vector<String> ret;
+
+	while (true) {
+		String::size_type idx = in.find("\n\n");
+		if (idx == in.npos)
+			return ret;
+		idx += 2;
+		ret.push_back(in.substr(0, idx));
+		in = in.substr(idx);
+	}
 }
 
 void
 Peer::append(const String& msg)
 {
-  _out->append(msg);
+	_out->append(msg);
 }
 
-int 
+int
 Peer::get_sock_fd()
 {
-  return _sock->get_sock();
+	return _sock->get_sock();
 }
 
 String
 Peer::hostname()
 {
-  return _hostname;
+	return _hostname;
 }
--- conga/ricci/modules/cluster/clumon/src/daemon/Peer.h	2006/08/10 22:53:08	1.2
+++ conga/ricci/modules/cluster/clumon/src/daemon/Peer.h	2007/10/10 18:10:37	1.2.4.1
@@ -1,28 +1,27 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
-#ifndef Peer_h
-#define Peer_h
+#ifndef __CONGA_MODCLUSTERD_PEER_H
+#define __CONGA_MODCLUSTERD_PEER_H
 
 #include "counting_auto_ptr.h"
 #include "Socket.h"
@@ -30,43 +29,40 @@
 #include <vector>
 #include "String.h"
 
-
 namespace ClusterMonitoring
 {
 
 
 class Peer
 {
- public:
-  Peer();
-  Peer(const String& hostname, const ClientSocket&);
-  Peer(const String& hostname, unsigned short port);
-  virtual ~Peer();
-  
-  void send();
-  std::vector<String> receive();
-  
-  bool outq_empty() { return _out->empty(); }
-  
-  void append(const String& msg);
-  
-  int get_sock_fd();
-  
-  String hostname();
-  
-  bool operator== (const Peer&) const;
-  
- private:
-  counting_auto_ptr<ClientSocket> _sock;
-  const String _hostname;
-  
-  counting_auto_ptr<String> _in;
-  counting_auto_ptr<String> _out;
-  
-};  // class Peer
+	public:
+		Peer();
+		Peer(const String& hostname, const ClientSocket&);
+		Peer(const String& hostname, unsigned short port);
+		virtual ~Peer();
+
+		void send();
+		std::vector<String> receive();
+
+		bool outq_empty() { return _out->empty(); }
+
+		void append(const String& msg);
+
+		int get_sock_fd();
+
+		String hostname();
+
+		bool operator== (const Peer&) const;
+
+	private:
+		counting_auto_ptr<ClientSocket> _sock;
+		const String _hostname;
 
+		counting_auto_ptr<String> _in;
+		counting_auto_ptr<String> _out;
+};
 
-};  // namespace ClusterMonitoring 
 
+};
 
-#endif  // Peer
+#endif
--- conga/ricci/modules/cluster/clumon/src/daemon/main.cpp	2006/10/14 18:00:02	1.4
+++ conga/ricci/modules/cluster/clumon/src/daemon/main.cpp	2007/10/10 18:10:37	1.4.4.1
@@ -1,26 +1,25 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
 #include <unistd.h>
 #include <sys/types.h>
 #include <signal.h>
@@ -28,6 +27,8 @@
 
 #include <sys/poll.h>
 #include <errno.h>
+#include <libcman.h>
+
 typedef struct pollfd poll_fd;
 
 extern "C" {
@@ -57,184 +58,215 @@
 
 class ClientInfo
 {
-public:
-  ClientInfo() {}
-  ClientInfo(ClientSocket& sock, String str="") : 
-    sock(sock), str(str) {}
-  
-  ClientSocket sock;
-  String str;
+	public:
+		ClientInfo() {}
+		ClientInfo(ClientSocket& sock, String str="") :
+			sock(sock), str(str) {}
+
+		ClientSocket sock;
+		String str;
 };
 
+int
+main(int argc, char **argv)
+{
+	bool debug = false, foreground = false;
+	int v_level = -1;
+	int rv;
+	String clu_version("");
+
+	while ((rv = getopt(argc, argv, "c:fdv:")) != EOF) {
+		switch (rv) {
+			case 'c': {
+				char *p;
+				long cv = strtol(optarg, &p, 10);
+				if (*p != '\0' || cv < 3 || cv > 5) {
+					fprintf(stderr, "Invalid cluster version: %s\n", optarg);
+					exit(-1);
+				}
+				clu_version = String(optarg);
+			}
+
+			case 'd':
+				debug = true;
+				break;
+
+			case 'f':
+				foreground = true;
+				break;
+
+			case 'v':
+				if (sscanf(optarg, "%d", &v_level) != 1) {
+					fprintf(stderr, "Invalid verbosity level: %s\n", optarg);
+					v_level = -1;
+				}
+				break;
+
+			default:
+				break;
+		}
+	}
 
+	if (v_level < 0) {
+		if (debug) {
+			cout << "Setting verbosity level to LogAll" << endl;
+		} else {
+			cout << "Setting verbosity level to LogBasic" << endl;
+			v_level = LogBasic;
+		}
+	}
 
-int 
-main(int argc, char** argv)
-{
-  bool debug=false, foreground=false;
-  int v_level = -1;
-  
-  int rv;
-  while ((rv = getopt(argc, argv, "fdv:")) != EOF)
-    switch (rv) {
-    case 'd':
-      debug = true;
-      break;
-    case 'f':
-      foreground = true;
-      break;
-    case 'v':
-      sscanf(optarg, "%d", &v_level);
-      break;
-    default:
-      break;
-    }
-  
-  if (v_level < 0) {
-    cout << "Setting verbosity level to LogBasic" << endl;
-    v_level = LogBasic;
-  }
-  if (foreground)
-    set_logger(counting_auto_ptr<Logger>(new Logger(1, "clumond", LogLevel(v_level))));
-  else
-    set_logger(counting_auto_ptr<Logger>(new Logger(LOG_FILE, "clumond", LogLevel(v_level))));
-  
-  log("started");
-  try {
-    ServerSocket server(MONITORING_CLIENT_SOCKET);
-    server.nonblocking(true);
-    Monitor monitor(COMMUNICATION_PORT);
-    
-    if (!foreground && (geteuid() == 0))
-      daemon_init(argv[0]);
-    setup_signal(SIGINT, shutdown);
-    setup_signal(SIGTERM, shutdown);
-    setup_signal(SIGCHLD, sigchild);
-    setup_signal(SIGPIPE, SIG_IGN);
-    if (debug)
-      setup_signal(SIGSEGV, segfault);
-    else
-      unblock_signal(SIGSEGV);
-    
-    serve_clients(monitor, server);
-  } catch (String e) {
-    log("unhandled exception in main(): " + e);
-    log("died", LogAll);
-    return 1;
-  } catch ( ... ) {
-    log("unhandled unknown exception in main()");
-    log("died", LogAll);
-    return 1;
-  }
-  
-  unlink("/var/run/clumond.pid");
-  log("exited", LogAll);
-  return 0;
+	if (foreground)
+		set_logger(counting_auto_ptr<Logger>(new Logger(1, "clumond", LogLevel(v_level))));
+	else
+		set_logger(counting_auto_ptr<Logger>(new Logger(LOG_FILE, "clumond", LogLevel(v_level))));
+
+	log("started");
+	try {
+		ServerSocket server(MONITORING_CLIENT_SOCKET);
+		server.nonblocking(true);
+
+		Monitor monitor(COMMUNICATION_PORT, clu_version);
+
+		if (!foreground && (geteuid() == 0))
+			daemon_init(argv[0]);
+
+		setup_signal(SIGINT, shutdown);
+		setup_signal(SIGTERM, shutdown);
+		setup_signal(SIGCHLD, sigchild);
+		setup_signal(SIGPIPE, SIG_IGN);
+
+		if (debug)
+			setup_signal(SIGSEGV, segfault);
+		else
+			unblock_signal(SIGSEGV);
+
+		serve_clients(monitor, server);
+	} catch (String e) {
+		log("unhandled exception in main(): " + e);
+		log("died", LogAll);
+		return 1;
+	} catch ( ... ) {
+		log("unhandled unknown exception in main()");
+		log("died", LogAll);
+		return 1;
+	}
+
+	unlink("/var/run/clumond.pid");
+	log("exited", LogAll);
+	return 0;
 }
 
-void 
+void
 serve_clients(Monitor& monitor, ServerSocket& server)
 {
-  map<int, ClientInfo> clients;
-  
-  log("Starting monitor", LogMonitor);
-  monitor.start();
-  
-  while (!shutdown_pending) {
-    unsigned int socks_num = clients.size() + 1;
-    
-    // prepare poll structs
-    array_auto_ptr<poll_fd> poll_data(new poll_fd[socks_num]);
-    poll_data[0].fd = server.get_sock();
-    poll_data[0].events = POLLIN;
-    poll_data[0].revents = 0;
-    map<int, ClientInfo>::iterator iter = clients.begin();
-    for (unsigned int i=1; i<socks_num; i++) {
-      poll_data[i].fd = iter->first;
-      poll_data[i].events = POLLIN;
-      if ( ! iter->second.str.empty())
-	poll_data[i].events |= POLLOUT;
-      poll_data[i].revents = 0;
-      iter++;
-    }
-    
-    // wait for events
-    int ret = poll(poll_data.get(), socks_num, 500);
-    if (ret == 0)
-      continue;
-    else if (ret == -1) {
-      if (errno == EINTR)
-	continue;
-      else
-	throw String("serve_clients(): poll() error");
-    }
-    
-    // process events
-    for (unsigned int i=0; i<socks_num && !shutdown_pending; i++) {
-      poll_fd& poll_info = poll_data[i];
-      
-      // server socket
-      if (poll_info.fd == server.get_sock()) {
-	if (poll_info.revents & POLLIN) {
-	  try {
-	    ClientSocket sock = server.accept();
-	    sock.nonblocking(true);
-	    clients[sock.get_sock()] = ClientInfo(sock);
-	  } catch ( ... ) {}
-	}
-	if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL))
-	  throw String("serve_clients(): server socket error????");
-      } else {
-	// client socket
-	if (poll_info.revents & POLLIN) {
-	  ClientInfo& info = clients[poll_info.fd];
-	  try {
-	    String msg = info.sock.recv();
-	    if (msg.size())
-	      info.str = monitor.request(msg);
-	  } catch ( ... ) {
-	    clients.erase(poll_info.fd);
-	  }
-	  continue;
-	}
-	if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL)) {
-	  clients.erase(poll_info.fd);
-	  continue;
-	}
-	if (poll_info.revents & POLLOUT) {
-	  ClientInfo& info = clients[poll_info.fd];
-	  try {
-	    info.str = info.sock.send(info.str);
-	  } catch ( ... ) {
-	    clients.erase(poll_info.fd);
-	    continue;
-	  }
+	map<int, ClientInfo> clients;
+
+	log("Starting monitor", LogMonitor);
+	monitor.start();
+
+	while (!shutdown_pending) {
+		unsigned int socks_num = clients.size() + 1;
+
+		// prepare poll structs
+		array_auto_ptr<poll_fd> poll_data(new poll_fd[socks_num]);
+		poll_data[0].fd = server.get_sock();
+		poll_data[0].events = POLLIN;
+		poll_data[0].revents = 0;
+
+		map<int, ClientInfo>::iterator iter = clients.begin();
+		for (unsigned int i = 1 ; i < socks_num ; i++) {
+			poll_data[i].fd = iter->first;
+			poll_data[i].events = POLLIN;
+			if (!iter->second.str.empty())
+				poll_data[i].events |= POLLOUT;
+			poll_data[i].revents = 0;
+			iter++;
+		}
+
+		// wait for events
+		int ret = poll(poll_data.get(), socks_num, 500);
+		if (ret == 0)
+			continue;
+		else if (ret == -1) {
+			if (errno == EINTR)
+				continue;
+			else {
+				throw String("serve_clients(): poll() error: "
+						+ String(strerror(errno)));
+			}
+		}
+
+		// process events
+		for (unsigned int i = 0 ; i < socks_num && !shutdown_pending ; i++) {
+			poll_fd& poll_info = poll_data[i];
+
+			// server socket
+			if (poll_info.fd == server.get_sock()) {
+				if (poll_info.revents & POLLIN) {
+					try {
+						ClientSocket sock = server.accept();
+						sock.nonblocking(true);
+						clients[sock.get_sock()] = ClientInfo(sock);
+					} catch ( ... ) {}
+				}
+				if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+					throw String("serve_clients(): poll: " +
+							String(strerror(errno)));
+				}
+			} else {
+				// client socket
+				if (poll_info.revents & POLLIN) {
+					ClientInfo& info = clients[poll_info.fd];
+					try {
+						String msg = info.sock.recv();
+						if (msg.size())
+							info.str = monitor.request(msg);
+					} catch ( ... ) {
+						clients.erase(poll_info.fd);
+					}
+					continue;
+				}
+
+				if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+					clients.erase(poll_info.fd);
+					continue;
+				}
+
+				if (poll_info.revents & POLLOUT) {
+					ClientInfo& info = clients[poll_info.fd];
+					try {
+						info.str = info.sock.send(info.str);
+					} catch ( ... ) {
+						clients.erase(poll_info.fd);
+						continue;
+					}
+				}
+			}
+		}
 	}
-      }  // client socket
-    }  // process events
-  } // while
 }
 
-void 
+void
 shutdown(int)
 {
-  log_sigsafe("exit requested", LogExit);
-  shutdown_pending = true;
+	log_sigsafe("exit requested", LogExit);
+	shutdown_pending = true;
 }
 
 void
 segfault(int)
 {
-  char msg[128];
-  snprintf(msg, sizeof(msg)-1, "PID %d Thread %d: SIGSEGV, waiting forensics", 
-	   getpid(), (int) pthread_self());
-  log_sigsafe(msg, LogAll);
-  while(1)
-    sleep(60);
+	char msg[128];
+
+	snprintf(msg, sizeof(msg), "PID %d Thread %d: SIGSEGV, waiting forensics",
+		getpid(), (int) pthread_self());
+	log_sigsafe(msg, LogAll);
+	select(0, NULL, NULL, NULL, NULL);
 }
 
-void 
+void
 sigchild(int)
 {
-  // do nothing
+	// do nothing
 }
--- conga/ricci/modules/cluster/clumon/src/include/Cluster.h	2006/08/15 00:12:33	1.6
+++ conga/ricci/modules/cluster/clumon/src/include/Cluster.h	2007/10/10 18:10:37	1.6.4.1
@@ -1,28 +1,27 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
-#ifndef Cluster_h
-#define Cluster_h
+#ifndef __CONGA_MODCLUSTERD_CLUSTER_H
+#define __CONGA_MODCLUSTERD_CLUSTER_H
 
 #include <counting_auto_ptr.h>
 #include "String.h"
@@ -31,135 +30,125 @@
 
 #include "XML.h"
 
-
-namespace ClusterMonitoring 
+namespace ClusterMonitoring
 {
 
-
 class Node;
 class Service;
 class Cluster;
 
-
 String cluster2xml(Cluster& cluster);
 counting_auto_ptr<Cluster> xml2cluster(const String& xml);
 
 
 class Cluster
 {
- public:
-  Cluster(const String& name, 
-	  const String& alias, 
-	  const String& cluster_version, 
-	  unsigned int minQuorum=0);
-  virtual ~Cluster();
-  
-  String name();
-  String alias();
-  String version();
-  unsigned int votes();
-  unsigned int minQuorum();
-  bool quorate();
-  
-  counting_auto_ptr<Node> addNode(const String& name, 
-				  unsigned int votes, 
-				  bool online, 
-				  bool clustered,
-				  const String& uptime);
-  
-  counting_auto_ptr<Service> addService(const String& name, 
-					const String& nodeName, 
-					bool failed, 
-					bool autostart,
-					const String& time_since_transition);
-  
-  std::list<counting_auto_ptr<Node> > nodes();
-  std::list<counting_auto_ptr<Node> > clusteredNodes();
-  std::list<counting_auto_ptr<Node> > unclusteredNodes();
-  
-  std::list<counting_auto_ptr<Service> > services();
-  std::list<counting_auto_ptr<Service> > runningServices();
-  std::list<counting_auto_ptr<Service> > stoppedServices();
-  std::list<counting_auto_ptr<Service> > failedServices();
-  
- private:
-  String _name;
-  String _alias;
-  String _cl_version;
-  unsigned int _minQuorum;
-  std::map<String, counting_auto_ptr<Node> > _nodes;
-
+	public:
+		Cluster(const String& name,
+				const String& alias,
+				const String& cluster_version,
+				unsigned int minQuorum=0);
+		virtual ~Cluster();
+
+		String name();
+		String alias();
+		String version();
+		unsigned int votes();
+		unsigned int minQuorum();
+		bool quorate();
+
+		counting_auto_ptr<Node> addNode(const String& name,
+										unsigned int votes,
+										bool online,
+										bool clustered,
+										const String& uptime);
+
+		counting_auto_ptr<Service> addService(	const String& name,
+										const String& nodeName,
+										bool failed,
+										bool autostart,
+										const String& time_since_transition);
+
+		std::list<counting_auto_ptr<Node> > nodes();
+		std::list<counting_auto_ptr<Node> > clusteredNodes();
+		std::list<counting_auto_ptr<Node> > unclusteredNodes();
+
+		std::list<counting_auto_ptr<Service> > services();
+		std::list<counting_auto_ptr<Service> > runningServices();
+		std::list<counting_auto_ptr<Service> > stoppedServices();
+		std::list<counting_auto_ptr<Service> > failedServices();
+
+	private:
+		String _name;
+		String _alias;
+		String _cl_version;
+		unsigned int _minQuorum;
+		std::map<String, counting_auto_ptr<Node> > _nodes;
 };
 
-
 class Node
 {
- public:
-  Node(const String& name, 
-       const String& clustername,
-       unsigned int votes,
-       bool online,
-       bool clustered,
-       const String& uptime);
-  virtual ~Node();
-  
-  String name() const;
-  String clustername() const;
-  unsigned int votes() const;
-  bool online() const;
-  bool clustered() const;  // available to cluster
-  String uptime() const;
-  
-  counting_auto_ptr<Service> addService(const String& name,
-					bool failed,
-					bool autostart,
-					const String& time_since_transition);
-  std::list<counting_auto_ptr<Service> > services();
-  
- private:
-  String _name;
-  String _clustername;
-  unsigned int _votes;
-  bool _online;
-  bool _clustered;  // available to cluster
-  String _uptime;
-  
-  std::map<String, counting_auto_ptr<Service> > _services;
-  
-};
+	public:
+		Node(	const String& name,
+				const String& clustername,
+				unsigned int votes,
+				bool online,
+				bool clustered,
+				const String& uptime);
+		virtual ~Node();
+
+		String name() const;
+		String clustername() const;
+		unsigned int votes() const;
+		bool online() const;
+		bool clustered() const; // available to cluster
+		String uptime() const;
+
+		counting_auto_ptr<Service> addService(const String& name,
+										bool failed,
+										bool autostart,
+										const String& time_since_transition);
+		std::list<counting_auto_ptr<Service> > services();
+
+	private:
+		String _name;
+		String _clustername;
+		unsigned int _votes;
+		bool _online;
+		bool _clustered; // available to cluster
+		String _uptime;
 
+		std::map<String, counting_auto_ptr<Service> > _services;
+};
 
 class Service
 {
- public:
-  Service(const String& name,
-	  const String& clustername,
-	  const Node& node,
-	  bool failed,
-	  bool autostart,
-	  const String& time_since_transition);
-  virtual ~Service();
-  
-  String name() const;
-  String clustername() const;
-  bool running() const;
-  String nodename() const;
-  bool failed() const;
-  bool autostart() const;
-  String time_since_transition() const;
-  
- private:
-  String _name;
-  String _clustername;
-  String _nodename;
-  bool _autostart;
-  bool _failed;
-  String _time_since_transition;
-  
+	public:
+		Service(const String& name,
+				const String& clustername,
+				const Node& node,
+				bool failed,
+				bool autostart,
+				const String& time_since_transition);
+		virtual ~Service();
+
+		String name() const;
+		String clustername() const;
+		bool running() const;
+		String nodename() const;
+		bool failed() const;
+		bool autostart() const;
+		String time_since_transition() const;
+
+	private:
+		String _name;
+		String _clustername;
+		String _nodename;
+		bool _autostart;
+		bool _failed;
+		String _time_since_transition;
 };
 
-
-};  // namespace ClusterMonitoring 
-
+};
 
 #endif
--- conga/ricci/modules/cluster/clumon/src/include/ClusterMonitor.h	2006/08/10 22:53:08	1.2
+++ conga/ricci/modules/cluster/clumon/src/include/ClusterMonitor.h	2007/10/10 18:10:37	1.2.4.1
@@ -1,28 +1,27 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge,
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
-
-#ifndef ClusterMonitor_h
-#define ClusterMonitor_h
+#ifndef __CONGA_MODCLUSTERD_CLUSTERMONITOR_H
+#define __CONGA_MODCLUSTERD_CLUSTERMONITOR_H
 
 #include "Cluster.h"
 #include "counting_auto_ptr.h"
@@ -30,29 +29,25 @@
 
 #include "String.h"
 
-
 namespace ClusterMonitoring
 {
 
 
 class ClusterMonitor
 {
- public:
-  ClusterMonitor(const String& socket_path=MONITORING_CLIENT_SOCKET);
-  virtual ~ClusterMonitor();
-  
-  counting_auto_ptr<Cluster> get_cluster();
-  
- private:
-  String _sock_path;
-  
-  ClusterMonitor(const ClusterMonitor&);
-  ClusterMonitor& operator= (const ClusterMonitor&);
-  
-};  // class ClusterMonitor
+	public:
+		ClusterMonitor(const String& socket_path=MONITORING_CLIENT_SOCKET);
+		virtual ~ClusterMonitor();
+
+		counting_auto_ptr<Cluster> get_cluster();
 
+	private:
+		String _sock_path;
 
-};  // namespace ClusterMonitoring
+		ClusterMonitor(const ClusterMonitor&);
+		ClusterMonitor& operator= (const ClusterMonitor&);
+};
 
+};
 
 #endif
--- conga/ricci/modules/cluster/clumon/src/include/clumond_globals.h	2006/03/27 23:15:30	1.1
+++ conga/ricci/modules/cluster/clumon/src/include/clumond_globals.h	2007/10/10 18:10:37	1.1.4.1
@@ -1,34 +1,30 @@
 /*
-  Copyright Red Hat, Inc. 2005
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
-  MA 02139, USA.
+** Copyright (C) Red Hat, Inc. 2005-2007
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License version 2 as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to the
+** Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+** MA 02139, USA.
 */
+
 /*
  * Author: Stanko Kupcevic <kupcevic redhat com>
  */
 
+#ifndef __CONGA_MODCLUSTERD_GLOBALS_H
+#define __CONGA_MODCLUSTERD_GLOBALS_H
 
-#ifndef clumond_globals_h
-#define clumond_globals_h
-
-
-#define COMMUNICATION_PORT 16851
-#define MONITORING_CLIENT_SOCKET "/var/run/clumond.sock"
-
-#define LOG_FILE                 "/var/log/clumond.log"
-
+#define COMMUNICATION_PORT			16851
+#define MONITORING_CLIENT_SOCKET	"/var/run/clumond.sock"
+#define LOG_FILE					"/var/log/clumond.log"
 
 #endif
--- conga/ricci/modules/cluster/clumon/src/snmp-agent/Makefile	2007/09/09 14:19:37	1.3.4.1
+++ conga/ricci/modules/cluster/clumon/src/snmp-agent/Makefile	2007/10/10 18:10:38	1.3.4.2
@@ -20,7 +20,7 @@
 INCLUDE     += -I ../include
 CFLAGS      += $(SNMP_CFLAGS)
 CXXFLAGS    += $(SNMP_CFLAGS)
-LDFLAGS     += -shared ../common/*.o $(SNMP_LDLAGS)
+LDFLAGS     += -shared ../common/*.o $(SNMP_LDLAGS) -lcman
 
 
 
@@ -54,4 +54,4 @@
 
 
 $(TARGET): $(OBJECTS)
-	$(CXX) $(LDFLAGS) -o $@ $(OBJECTS)
+	$(CXX) -o $@ $(OBJECTS) $(LDFLAGS)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]