KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ha > framework > server > util > TopologyMonitorService


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.ha.framework.server.util;
23
24 import java.net.InetAddress JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Vector JavaDoc;
27 import java.io.IOException JavaDoc;
28 import javax.naming.InitialContext JavaDoc;
29 import javax.management.ObjectName JavaDoc;
30
31 import org.jboss.ha.framework.interfaces.HAPartition;
32 import org.jboss.ha.framework.interfaces.HAPartition.AsynchHAMembershipListener;
33 import org.jboss.system.ServiceMBeanSupport;
34 import org.jboss.system.server.ServerConfigUtil;
35 import org.jboss.logging.Logger;
36 import org.apache.log4j.MDC;
37
38 /** A cluster parition membership monitor. It can be used to view how
39  the nodes in a cluster are seeing the topology change using either email or
40  a centralized log server.
41
42  To use this to send email on change notifications use the following log4j.xml
43  fragments:
44
45   <appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
46     <param name="To" value="admin@dot.com"/>
47     <param name="From" value="cluster-monitor@dot.com"/>
48     <param name="Subject" value="JBoss Cluster Changes"/>
49     <param name="SMTPHost" value="mailhost"/>
50     <param name="BufferSize" value="8"/>
51     <param name="EvaluatorClass"
52       value="org.jboss.logging.appender.RegexEventEvaluator" />
53     <layout class="org.apache.log4j.PatternLayout">
54       <param name="ConversionPattern" value="[%d{ABSOLUTE},%c{1}] %m%n"/>
55     </layout>
56   </appender>
57
58   <category name="org.jboss.ha.framework.server.util.TopologyMonitorService.membershipChanged">
59     <priority value="DEBUG" />
60     <appender-ref ref="SMTP"/>
61   </category>
62
63  You can also have this service notify another MBean of the change to perform
64  arbitrary checks by specifying the MBean name as the TriggerServiceName
65  attribute value. This MBean must have an operation with the following
66  signature:
67 <pre>
68    param: removed ArrayList<AddressPort> of nodes that were removed
69    param: added ArrayList<AddressPort> of nodes that were added
70    param: members ArrayList<AddressPort> of nodes currently in the cluster
71    param: logLoggerName the log4j category name used by the
72       TopologyMonitorService. This should be used for logging to integrate with
73       the TopologyMonitorService output.
74    public void membershipChanged(ArrayList deadMembers, ArrayList newMembers,
75       ArrayList allMembers, String logLoggerName)
76 </pre>
77
78  @author Scott.Stark@jboss.org
79  @version $Revision: 58095 $
80  */

81 public class TopologyMonitorService extends ServiceMBeanSupport
82    implements TopologyMonitorServiceMBean, AsynchHAMembershipListener
83 {
84    private static final String JavaDoc CHANGE_NAME = TopologyMonitorService.class.getName()
85          + ".membershipChanged";
86    private static Logger changeLog = Logger.getLogger(CHANGE_NAME);
87    private String JavaDoc partitionName = ServerConfigUtil.getDefaultPartitionName();
88    private HAPartition partition;
89    private String JavaDoc hostname;
90    private ObjectName JavaDoc triggerServiceName;
91
92    public TopologyMonitorService()
93    {
94    }
95
96 // --- Begin ServiceMBeanSupport overriden methods
97
protected void startService() throws Exception JavaDoc
98    {
99       InitialContext JavaDoc ctx = new InitialContext JavaDoc();
100       String JavaDoc partitionJndiName = "/HAPartition/" + partitionName;
101       partition = (HAPartition) ctx.lookup(partitionJndiName);
102       // Register as a listener of cluster membership changes
103
partition.registerMembershipListener(this);
104       log.info("Registered as MembershipListener");
105       try
106       {
107          hostname = InetAddress.getLocalHost().getHostName();
108       }
109       catch(IOException JavaDoc e)
110       {
111          log.warn("Failed to lookup local hostname", e);
112          hostname = "<unknown>";
113       }
114    }
115
116    protected void stopService() throws Exception JavaDoc
117    {
118       partition.unregisterMembershipListener(this);
119    }
120 // --- End ServiceMBeanSupport overriden methods
121

122 // --- Begin TopologyMonitorServiceMBean interface methods
123
public String JavaDoc getPartitionName()
124    {
125       return partitionName;
126    }
127    public void setPartitionName(String JavaDoc name)
128    {
129       this.partitionName = name;
130    }
131
132    public ObjectName JavaDoc getTriggerServiceName()
133    {
134       return triggerServiceName;
135    }
136    public void setTriggerServiceName(ObjectName JavaDoc triggerServiceName)
137    {
138       this.triggerServiceName = triggerServiceName;
139    }
140
141    public Vector JavaDoc getClusterNodes()
142    {
143       Vector JavaDoc view = null;
144       try
145       {
146          InitialContext JavaDoc ctx = new InitialContext JavaDoc();
147          String JavaDoc jndiName = "/HAPartition/" + partitionName;
148          HAPartition partition = (HAPartition) ctx.lookup(jndiName);
149          view = partition.getCurrentView();
150       }
151       catch(Exception JavaDoc e)
152       {
153          log.error("Failed to access HAPartition state", e);
154       }
155       return view;
156    }
157
158 // --- End TopologyMonitorServiceMBean interface methods
159

160 // --- Begin HAMembershipListener interface methods
161
/** Called when a new partition topology occurs.
162     * @param deadMembers A list of nodes that have died since the previous view
163     * @param newMembers A list of nodes that have joined the partition since
164     * the previous view
165     * @param allMembers A list of nodes that built the current view
166     */

167    public void membershipChanged(final Vector JavaDoc deadMembers, final Vector JavaDoc newMembers,
168          final Vector JavaDoc allMembers)
169    {
170       MDC.put("RegexEventEvaluator", "End membershipChange.*");
171       ArrayList JavaDoc removed = new ArrayList JavaDoc();
172       ArrayList JavaDoc added = new ArrayList JavaDoc();
173       ArrayList JavaDoc members = new ArrayList JavaDoc();
174       changeLog.info("Begin membershipChanged info, hostname="+hostname);
175       changeLog.info("DeadMembers: size="+deadMembers.size());
176       for(int m = 0; m < deadMembers.size(); m ++)
177       {
178          AddressPort addrInfo = getMemberAddress(deadMembers.get(m));
179          removed.add(addrInfo);
180          changeLog.info(addrInfo);
181       }
182       changeLog.info("NewMembers: size="+newMembers.size());
183       for(int m = 0; m < newMembers.size(); m ++)
184       {
185          AddressPort addrInfo = getMemberAddress(newMembers.get(m));
186          added.add(addrInfo);
187          changeLog.info(addrInfo);
188       }
189       changeLog.info("AllMembers: size="+allMembers.size());
190       for(int m = 0; m < allMembers.size(); m ++)
191       {
192          AddressPort addrInfo = getMemberAddress(allMembers.get(m));
193          members.add(addrInfo);
194          changeLog.info(addrInfo);
195       }
196       // Notify the trigger MBean
197
if( triggerServiceName != null )
198       {
199          changeLog.info("Invoking trigger service: "+triggerServiceName);
200          try
201          {
202             Object JavaDoc[] params = {removed, added, members, CHANGE_NAME};
203             String JavaDoc[] sig = {"java.util.ArrayList", "java.util.ArrayList",
204                "java.util.ArrayList", "java.lang.String"};
205             server.invoke(triggerServiceName, "membershipChanged", params, sig);
206          }
207          catch(Throwable JavaDoc t)
208          {
209             changeLog.error("Failed to notify trigger service: "+triggerServiceName, t);
210             log.debug("Failed to notify trigger service: "+triggerServiceName, t);
211          }
212       }
213       changeLog.info("End membershipChanged info, hostname="+hostname);
214       MDC.remove("RegexEventEvaluator");
215    }
216 // --- End HAMembershipListener interface methods
217

218    /** Use reflection to access the address InetAddress and port if they exist
219     * in the Address implementation
220     */

221    private AddressPort getMemberAddress(Object JavaDoc addr)
222    {
223       AddressPort info = null;
224       try
225       {
226          org.jboss.ha.framework.interfaces.ClusterNode node =
227                (org.jboss.ha.framework.interfaces.ClusterNode)addr;
228
229          InetAddress JavaDoc inetAddr = node.getOriginalJGAddress().getIpAddress();
230          Integer JavaDoc port = new Integer JavaDoc(node.getOriginalJGAddress().getPort());
231          info = new AddressPort(inetAddr, port);
232       }
233       catch(Exception JavaDoc e)
234       {
235          log.warn("Failed to obtain InetAddress/port from addr: "+addr, e);
236       }
237       return info;
238    }
239
240    public static class AddressPort
241    {
242       InetAddress JavaDoc addr;
243       Integer JavaDoc port;
244       AddressPort(InetAddress JavaDoc addr, Integer JavaDoc port)
245       {
246          this.addr = addr;
247          this.port = port;
248       }
249
250       public Integer JavaDoc getPort()
251       {
252          return port;
253       }
254       public InetAddress JavaDoc getInetAddress()
255       {
256          return addr;
257       }
258       public String JavaDoc getHostAddress()
259       {
260          return addr.getHostAddress();
261       }
262       public String JavaDoc getHostName()
263       {
264          return addr.getHostName();
265       }
266       public String JavaDoc toString()
267       {
268          return "{host("+addr+"), port("+port+")}";
269       }
270    }
271 }
272
Popular Tags