package org.jboss.ha.framework.server.util;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Vector;
import java.io.IOException;
import javax.naming.InitialContext;
import javax.management.ObjectName;
import org.jboss.ha.framework.interfaces.HAPartition;
import org.jboss.ha.framework.interfaces.HAPartition.AsynchHAMembershipListener;
import org.jboss.system.ServiceMBeanSupport;
import org.jboss.system.server.ServerConfigUtil;
import org.jboss.logging.Logger;
import org.apache.log4j.MDC;
public class TopologyMonitorService extends ServiceMBeanSupport
implements TopologyMonitorServiceMBean, AsynchHAMembershipListener
{
private static final String CHANGE_NAME = TopologyMonitorService.class.getName()
+ ".membershipChanged";
private static Logger changeLog = Logger.getLogger(CHANGE_NAME);
private String partitionName = ServerConfigUtil.getDefaultPartitionName();
private HAPartition partition;
private String hostname;
private ObjectName triggerServiceName;
public TopologyMonitorService()
{
}
protected void startService() throws Exception
{
InitialContext ctx = new InitialContext();
String partitionJndiName = "/HAPartition/" + partitionName;
partition = (HAPartition) ctx.lookup(partitionJndiName);
partition.registerMembershipListener(this);
log.info("Registered as MembershipListener");
try
{
hostname = InetAddress.getLocalHost().getHostName();
}
catch(IOException e)
{
log.warn("Failed to lookup local hostname", e);
hostname = "<unknown>";
}
}
protected void stopService() throws Exception
{
partition.unregisterMembershipListener(this);
}
public String getPartitionName()
{
return partitionName;
}
public void setPartitionName(String name)
{
this.partitionName = name;
}
public ObjectName getTriggerServiceName()
{
return triggerServiceName;
}
public void setTriggerServiceName(ObjectName triggerServiceName)
{
this.triggerServiceName = triggerServiceName;
}
public Vector getClusterNodes()
{
Vector view = null;
try
{
InitialContext ctx = new InitialContext();
String jndiName = "/HAPartition/" + partitionName;
HAPartition partition = (HAPartition) ctx.lookup(jndiName);
view = partition.getCurrentView();
}
catch(Exception e)
{
log.error("Failed to access HAPartition state", e);
}
return view;
}
public void membershipChanged(final Vector deadMembers, final Vector newMembers,
final Vector allMembers)
{
MDC.put("RegexEventEvaluator", "End membershipChange.*");
ArrayList removed = new ArrayList();
ArrayList added = new ArrayList();
ArrayList members = new ArrayList();
changeLog.info("Begin membershipChanged info, hostname="+hostname);
changeLog.info("DeadMembers: size="+deadMembers.size());
for(int m = 0; m < deadMembers.size(); m ++)
{
AddressPort addrInfo = getMemberAddress(deadMembers.get(m));
removed.add(addrInfo);
changeLog.info(addrInfo);
}
changeLog.info("NewMembers: size="+newMembers.size());
for(int m = 0; m < newMembers.size(); m ++)
{
AddressPort addrInfo = getMemberAddress(newMembers.get(m));
added.add(addrInfo);
changeLog.info(addrInfo);
}
changeLog.info("AllMembers: size="+allMembers.size());
for(int m = 0; m < allMembers.size(); m ++)
{
AddressPort addrInfo = getMemberAddress(allMembers.get(m));
members.add(addrInfo);
changeLog.info(addrInfo);
}
if( triggerServiceName != null )
{
changeLog.info("Invoking trigger service: "+triggerServiceName);
try
{
Object[] params = {removed, added, members, CHANGE_NAME};
String[] sig = {"java.util.ArrayList", "java.util.ArrayList",
"java.util.ArrayList", "java.lang.String"};
server.invoke(triggerServiceName, "membershipChanged", params, sig);
}
catch(Throwable t)
{
changeLog.error("Failed to notify trigger service: "+triggerServiceName, t);
log.debug("Failed to notify trigger service: "+triggerServiceName, t);
}
}
changeLog.info("End membershipChanged info, hostname="+hostname);
MDC.remove("RegexEventEvaluator");
}
private AddressPort getMemberAddress(Object addr)
{
AddressPort info = null;
try
{
org.jboss.ha.framework.interfaces.ClusterNode node =
(org.jboss.ha.framework.interfaces.ClusterNode)addr;
InetAddress inetAddr = node.getOriginalJGAddress().getIpAddress();
Integer port = new Integer(node.getOriginalJGAddress().getPort());
info = new AddressPort(inetAddr, port);
}
catch(Exception e)
{
log.warn("Failed to obtain InetAddress/port from addr: "+addr, e);
}
return info;
}
public static class AddressPort
{
InetAddress addr;
Integer port;
AddressPort(InetAddress addr, Integer port)
{
this.addr = addr;
this.port = port;
}
public Integer getPort()
{
return port;
}
public InetAddress getInetAddress()
{
return addr;
}
public String getHostAddress()
{
return addr.getHostAddress();
}
public String getHostName()
{
return addr.getHostName();
}
public String toString()
{
return "{host("+addr+"), port("+port+")}";
}
}
}