Clover Coverage Report - jmxmonitor 1.0.2
Coverage timestamp: Wed Feb 10 2010 07:36:51 GMT
../../../../../img/srcFileCovDistChart8.png 50% of files have more coverage
94   265   27   7.23
18   190   0.29   4.33
13     2.08  
3    
 
  ThreadManager       Line # 43 66 0% 16 27 68.6% 0.68604654
  ThreadManager.ShutdownRunner       Line # 190 22 0% 6 3 89.3% 0.89285713
  ThreadManager.MonitoringGroupHolder       Line # 239 6 0% 5 4 63.6% 0.6363636
 
  (2)
 
1    /*
2    * Copyright 2009 Ben Gidley
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10    * Unless required by applicable law or agreed to in writing, software
11    * distributed under the License is distributed on an "AS IS" BASIS,
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    * See the License for the specific language governing permissions and
14    * limitations under the License.
15    */
16   
17    package uk.co.gidley.jmxmonitor.services;
18   
19    import org.apache.commons.configuration.Configuration;
20    import org.apache.commons.lang.StringUtils;
21    import org.slf4j.Logger;
22    import org.slf4j.LoggerFactory;
23    import uk.co.gidley.jmxmonitor.monitoring.MonitoringGroup;
24   
25    import java.io.File;
26    import java.io.IOException;
27    import java.net.InetSocketAddress;
28    import java.nio.ByteBuffer;
29    import java.nio.CharBuffer;
30    import java.nio.channels.ClosedByInterruptException;
31    import java.nio.channels.ServerSocketChannel;
32    import java.nio.channels.SocketChannel;
33    import java.nio.charset.Charset;
34    import java.nio.charset.CharsetDecoder;
35    import java.util.HashMap;
36    import java.util.List;
37    import java.util.Map;
38    import java.util.NoSuchElementException;
39   
40    /**
41    * The manager service is responsible for managing the main thread loop and controlling the monitors
42    */
 
43    public class ThreadManager {
44    private static final Logger logger = LoggerFactory.getLogger(ThreadManager.class);
45    public static final String SHUTDOWN_MONITOR_THREAD = "ShutdownMonitor";
46    private Boolean threadManagerRunning = true;
47    private Map<String, MonitoringGroupHolder> monitoringGroups = new HashMap<String, MonitoringGroupHolder>();
48    private ThreadGroup threadGroup = new ThreadGroup("MonitoringGroups");
49    public static final String PROPERTY_PREFIX = "jmxmonitor.";
50    private MainConfiguration mainConfiguration;
51    public static final String JMXMONITOR_STOPPORT = "jmxmonitor.stopport";
52    public static final String JMXMONITOR_STOPKEY = "jmxmonitor.stopkey";
53   
 
54  4 toggle public ThreadManager(MainConfiguration mainConfiguration) {
55  4 this.mainConfiguration = mainConfiguration;
56    }
57   
58    /**
59    * Stop this asap (NOT sync)
60    */
 
61  2 toggle public void stop() {
62  2 this.threadManagerRunning = false;
63    }
64   
65   
 
66  4 toggle public void initialise() throws InitialisationException {
67    // Start shutdown socket service
68  4 ShutdownRunner shutdownRunner = null;
69  4 try {
70  4 shutdownRunner = new ShutdownRunner(mainConfiguration.getConfiguration());
71    } catch (IOException e) {
72  0 logger.error("{}", e);
73  0 throw new InitialisationException(e);
74    }
75  4 Thread shutdownThread = new Thread(shutdownRunner, SHUTDOWN_MONITOR_THREAD);
76   
77  4 try {
78   
79  4 shutdownThread.start();
80   
81    // Configure Monitoring Group instances
82  4 List<String> monitoringGroupNames = mainConfiguration.getConfiguration().getList(
83    PROPERTY_PREFIX + "groups");
84   
85  4 for (String groupName : monitoringGroupNames) {
86  4 if (!StringUtils.isEmpty(groupName)) {
87  3 logger.debug("Started initialising {}", groupName);
88  3 initialiseMonitoringGroup(groupName, mainConfiguration.getConfiguration());
89  3 logger.debug("Completed initialising {}", groupName);
90    }
91    }
92   
93   
94    // Start threads to begin monitoring
95  4 logger.info("Configuration complete starting all monitors");
96  4 for (String groupName : monitoringGroups.keySet()) {
97  3 Thread thread = monitoringGroups.get(groupName).getThread();
98  3 thread.start();
99    }
100   
101    // Continue to monitor for failures or stop message. On failure stop group, restart it if possible
102  25 while (threadManagerRunning) {
103  21 for (String groupName : monitoringGroups.keySet()) {
104  17 MonitoringGroup monitoringGroup = monitoringGroups.get(groupName).getMonitoringGroup();
105  17 if (!monitoringGroup.isAlive()) {
106  0 restartMonitoringGroup(groupName, mainConfiguration.getConfiguration());
107    }
108    }
109   
110    // Stop if the shutdown thread has triggered.
111  21 if (!shutdownThread.isAlive()) {
112  2 threadManagerRunning = false;
113  2 for (String groupName : monitoringGroups.keySet()) {
114  1 logger.debug("Stopping {}", groupName);
115  1 MonitoringGroup monitoringGroup = monitoringGroups.get(groupName).getMonitoringGroup();
116  1 monitoringGroup.stop();
117    }
118  2 for (String groupName : monitoringGroups.keySet()) {
119  1 Thread monitoringGroup = monitoringGroups.get(groupName).getThread();
120  1 monitoringGroup.join();
121  1 logger.debug("Stopped {}", groupName);
122    }
123    }
124   
125  21 Thread.sleep(5000);
126    }
127   
128   
129    } catch (NoSuchElementException e) {
130  0 logger.error("{}", e);
131  0 throw new InitialisationException(e);
132    } catch (InterruptedException e) {
133  0 logger.error("{}", e);
134  0 throw new RuntimeException(e);
135    } finally {
136    // Must shutdown the shutdown thread
137  4 shutdownThread.interrupt();
138   
139    }
140   
141    }
142   
 
143  0 toggle private void restartMonitoringGroup(String groupName,
144    Configuration config) throws InterruptedException, InitialisationException {
145  0 logger.warn("Monitoring Group is dead: {}. Restarting", groupName);
146   
147    // Tidy up
148  0 Thread oldThread = monitoringGroups.get(groupName).getThread();
149  0 if (oldThread.isAlive()) {
150    // Problem try to interrupt. This should force an exist
151  0 oldThread.interrupt();
152  0 oldThread.join(5000);
153  0 if (oldThread.isAlive()) {
154  0 logger.error("Unable to stop monitor thread {}", groupName);
155  0 throw new RuntimeException("Unable to stop monitor thread " + groupName);
156    }
157    }
158  0 monitoringGroups.remove(groupName);
159   
160    // Restart
161  0 initialiseMonitoringGroup(groupName, config);
162  0 Thread restartThread = monitoringGroups.get(groupName).getThread();
163  0 restartThread.start();
164    }
165   
 
166  3 toggle private void initialiseMonitoringGroup(String groupName,
167    Configuration config) throws InitialisationException {
168  3 String monitorFile = config.getString(PROPERTY_PREFIX + groupName + ".monitorConfiguration");
169  3 String expressionFile = config.getString(PROPERTY_PREFIX + groupName + ".expressionConfiguration");
170  3 Long interval = config.getLong(PROPERTY_PREFIX + groupName + ".interval");
171   
172  3 File monitor = findConfigurationFile(monitorFile);
173  3 File expression = findConfigurationFile(expressionFile);
174   
175  3 MonitoringGroup monitoringGroup = new MonitoringGroup();
176  3 monitoringGroup.initialise(groupName, monitor, expression, interval);
177  3 Thread thread = new Thread(threadGroup, monitoringGroup, groupName);
178  3 monitoringGroups.put(groupName, new MonitoringGroupHolder(monitoringGroup, thread));
179    }
180   
 
181  6 toggle private File findConfigurationFile(String configurationFile) throws InitialisationException {
182  6 File configuration = new File(configurationFile);
183  6 if (!configuration.exists()) {
184  0 throw new InitialisationException(
185    "Referenced Configuration File not found:" + configuration.getAbsolutePath());
186    }
187  6 return configuration;
188    }
189   
 
190    private class ShutdownRunner implements Runnable {
191    private ServerSocketChannel serverSocketChannel;
192    private ByteBuffer dbuf = ByteBuffer.allocateDirect(1024);
193    private Charset charset = Charset.forName("US-ASCII");
194    private CharsetDecoder decoder = charset.newDecoder();
195    private String stopKey;
196   
197   
 
198  4 toggle ShutdownRunner(Configuration config) throws IOException {
199  4 int stopPort = config.getInt(JMXMONITOR_STOPPORT);
200  4 stopKey = config.getString(JMXMONITOR_STOPKEY);
201  4 logger.debug("Initialising ShutdownRunner in {}", stopPort);
202  4 serverSocketChannel = ServerSocketChannel.open();
203  4 serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1", stopPort));
204  4 logger.debug("Initialised ShutdownRunner in {}", stopPort);
205    }
206   
 
207  4 toggle @Override
208    public void run() {
209  4 logger.info("Stop listener thread working");
210   
211  4 try {
212  4 boolean shutdownRunning = true;
213  6 while (shutdownRunning) {
214  4 SocketChannel socketChannel = serverSocketChannel.accept();
215  2 dbuf.clear();
216  2 socketChannel.read(dbuf);
217  2 dbuf.flip();
218  2 CharBuffer cb = decoder.decode(dbuf);
219  2 if (cb.toString().equals(stopKey)) {
220  2 serverSocketChannel.close();
221  2 shutdownRunning = false;
222  2 logger.info("Recieved Stop command");
223    }
224    }
225    } catch (ClosedByInterruptException e) {
226    // Ok just a shutdown of the main process
227  2 logger.debug("Closing shutdown thread {}", e);
228    } catch (IOException e) {
229  0 logger.error("{}", e);
230  0 throw new RuntimeException(e);
231    }
232   
233    }
234    }
235   
236    /**
237    * Used to hold the monitoring group
238    */
 
239    private class MonitoringGroupHolder {
240    private MonitoringGroup monitoringGroup;
241    private Thread thread;
242   
 
243  3 toggle private MonitoringGroupHolder(MonitoringGroup monitoringGroup, Thread thread) {
244  3 this.monitoringGroup = monitoringGroup;
245  3 this.thread = thread;
246    }
247   
 
248  18 toggle public MonitoringGroup getMonitoringGroup() {
249  18 return monitoringGroup;
250    }
251   
 
252  0 toggle public void setMonitoringGroup(MonitoringGroup monitoringGroup) {
253  0 this.monitoringGroup = monitoringGroup;
254    }
255   
 
256  4 toggle public Thread getThread() {
257  4 return thread;
258    }
259   
 
260  0 toggle public void setThread(Thread thread) {
261  0 this.thread = thread;
262    }
263    }
264   
265    }