ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/client/monitors/Heartbeat__Monitor.java
(Generate patch)

Comparing projects/cms/source/server/uk/org/iscream/cms/server/client/monitors/Heartbeat__Monitor.java (file contents):
Revision 1.14 by ajm, Thu Mar 22 21:36:26 2001 UTC vs.
Revision 1.19 by tdb, Mon Mar 26 18:07:11 2001 UTC

# Line 10 | Line 10 | import uk.org.iscream.util.*;
10   import uk.org.iscream.componentmanager.*;
11  
12   /**
13 < * This Monitor watches heartbeats
13 > * This Monitor watches heartbeats.
14 > * It generates an alert when a heartbeat that is expected
15 > * does not arrive. Unlike all the other monitors, this one
16 > * is driven by an event *not* occuring, rather than an
17 > * event occuring. This means it must be actively checking
18 > * for missing heartbeat's, and thus has an extra inner class
19 > * thread.
20   *
21   * @author  $Author$
22   * @version $Id$
# Line 24 | Line 30 | public class Heartbeat__Monitor extends MonitorSkeleto
30       */
31      public final String REVISION = "$Revision$";
32      
33 +    /**
34 +     * A description of this monitor
35 +     */
36      public final String DESC = "Monitors Heartbeats.";
37      
38 +    /**
39 +     * The default (used if not configured) period at
40 +     * which to check for old heartbeats. (in seconds)
41 +     */
42      public final int DEFAULT_CHECK_PERIOD = 60;
43      
44   //---STATIC METHODS---
45  
46   //---CONSTRUCTORS---
47 <
47 >    
48 >    /**
49 >     * Constructs a new Heartbeat monitor, and starts off
50 >     * the worker thread.
51 >     */
52      public Heartbeat__Monitor() {
53 <        new Thread(this).start();
53 >        super();
54          new HeartbeatWorker().start();
55      }
56  
57   //---PUBLIC METHODS---
58      
59 +    /**
60 +     * Analyse a packet of data. In this case, this will just
61 +     * register the fact that a heartbeat has arrived.
62 +     *
63 +     * @param packet The packet of data to analyse
64 +     */
65      public void analysePacket(XMLPacket packet) {
66          String source = packet.getParam("packet.attributes.machine_name");
67          if (!_hosts.containsKey(source)) {
68              synchronized(this) {
69 <                HashMap registerHash = new HashMap();
47 <                registerHash.put(source, new Register(source, _name));
48 <                _hosts.put(source, new HeartbeatHolder(registerHash));
69 >                _hosts.put(source, new HeartbeatHolder(new Register(source, _name)));
70              }
71          }
72          HeartbeatHolder lastHeartbeat = (HeartbeatHolder) _hosts.get(source);
# Line 76 | Line 97 | public class Heartbeat__Monitor extends MonitorSkeleto
97      }
98  
99   //---PRIVATE METHODS---
79
80    private boolean analyseHB(String source) {
81        ConfigurationProxy cp = ConfigurationProxy.getInstance();
82        HeartbeatHolder hbHolder = (HeartbeatHolder) _hosts.get(source);
83        Register reg = (Register) ((HashMap) hbHolder.getRegisterHash()).get(source);
84        
85        // get host's HB interval (seconds)
86        // this should always exist, thus we set to 0
87        int hostHBinterval = 0;
88        try {
89            hostHBinterval = Integer.parseInt(cp.getProperty("Host."+source, "Host.TCPUpdateTime"));
90        } catch (PropertyNotFoundException e) {
91            hostHBinterval = 0;
92            _logger.write(toString(), Logger.WARNING, "TCPUpdateTime value unavailable using default of " + hostHBinterval + " seconds");
93        } catch (NumberFormatException e) {
94            hostHBinterval = 0;
95            _logger.write(toString(), Logger.WARNING, "Erronous TCPUpdateTime value in configuration using default of " + hostHBinterval + " seconds");
96        }
97        
98        // get host's last HB time (seconds)
99        long lastHeartbeat = hbHolder.getLastHeartbeat();
100        // time since last heartbeat (seconds)
101        long timeSinceLastHB = (System.currentTimeMillis()/1000) - lastHeartbeat;
102        // time since (or until if negative) the expected heartbeat
103        long timeSinceExpectedHB = timeSinceLastHB - (long) hostHBinterval;
104        
105        // best do a check in case the expected heartbeat is in the future
106        if(timeSinceExpectedHB < 0) {
107            timeSinceExpectedHB = 0;
108        }
109        
110        // find out the threshold level we're at
111        int newThreshold = checkAttributeThreshold(timeSinceExpectedHB, reg);
112        
113        // process the alert
114        processAlert(newThreshold, "Heartbeat", reg, source, String.valueOf(timeSinceExpectedHB));
115        
116        if(reg.getLastAlertLevel() == Alert.alertFINAL) {
117            return true;
118        }
119        return false;
120    }
100      
101 +    /**
102 +     * Checks whether the time since the last heartbeat
103 +     * is beyond the threshold(s).
104 +     *
105 +     * @param timeSinceLastHB a long time since the last heartbeat arrived
106 +     * @param reg the Register for this host
107 +     * @return the level which has been breached, if any
108 +     */
109      private int checkAttributeThreshold(long timeSinceLastHB, Register reg) {
110          for(int thresholdLevel = Alert.thresholdLevels.length - 1; thresholdLevel >= 0; thresholdLevel--) {
111              if (reg.getThreshold(thresholdLevel) != -1.0) {
# Line 131 | Line 118 | public class Heartbeat__Monitor extends MonitorSkeleto
118      }
119  
120   //---ACCESSOR/MUTATOR METHODS---
121 <
121 >    
122 >    /**
123 >     * Returns a reference to the Queue we're getting data
124 >     * from. This is specific to this monitor.
125 >     *
126 >     * @return a reference to a Queue to get data from
127 >     */
128      protected Queue getQueue() {
129          return MonitorManager.getInstance().getHeartbeatQueue();
130      }
# Line 153 | Line 146 | public class Heartbeat__Monitor extends MonitorSkeleto
146       * A reference to the configuration proxy in use
147       */
148      private ConfigurationProxy _cp = ConfigurationProxy.getInstance();
149 <
149 >    
150 >    /**
151 >     * A HashMap of hosts, with associated HeartbeatHolder's.
152 >     */
153      private HashMap _hosts = new HashMap();
154 +    
155 +    /**
156 +     * A reference to the system logger.
157 +     */
158 +    private Logger _logger = ReferenceManager.getInstance().getLogger();
159  
160   //---STATIC ATTRIBUTES---
161  
162   //---INNER CLASSES---
163 <
163 >    
164 >    /**
165 >     * This inner class simply holding some information
166 >     * about a specific host.
167 >     */
168      private class HeartbeatHolder {
169          
170 <        public HeartbeatHolder(HashMap registerHash) {
171 <            _registerHash = registerHash;
170 >        /**
171 >         * Construct a new HeartbeatHolder.
172 >         */
173 >        public HeartbeatHolder(Register register) {
174 >            _register = register;
175          }
176          
177 +        /**
178 +         * Set the time of the last heartbeat
179 +         */
180          public void setLastHeartbeat(long lastHeartbeat) {
181              _lastHeartbeat = lastHeartbeat;
182          }
183          
184 +        /**
185 +         * Get the time of the last heartbeat
186 +         */
187          public long getLastHeartbeat() {
188              return _lastHeartbeat;
189          }
190          
191 <        public HashMap getRegisterHash() {
192 <            return _registerHash;
191 >        /**
192 >         * Get the Register
193 >         */
194 >        public Register getRegister() {
195 >            return _register;
196          }
197          
198 +        /**
199 +         * last heartbeat time
200 +         */
201          private long _lastHeartbeat;
202 <        private HashMap _registerHash;
202 >        
203 >        /**
204 >         * register ref
205 >         */
206 >        private Register _register;
207      }
208      
209 +    /**
210 +     * This worker thread just checks all the hosts and then
211 +     * waits a period of time before doing it again. It sends
212 +     * Alerts as required.
213 +     */
214      private class HeartbeatWorker extends Thread {
215          
216 +        /**
217 +         * The main run method of this worker thread. It simply
218 +         * checks through all the hosts it has stored, running
219 +         * the analyseHB method on each. It then removes any
220 +         * that have passed a FINAL, and waits a (configured)
221 +         * length of time before doing it again.
222 +         */
223          public void run() {
224              ConfigurationProxy cp = ConfigurationProxy.getInstance();
225              while(true) {
# Line 193 | Line 229 | public class Heartbeat__Monitor extends MonitorSkeleto
229                      checkPeriod = Integer.parseInt(cp.getProperty(_name, "Monitor.Heartbeat.checkPeriod"));
230                  } catch (PropertyNotFoundException e) {
231                      checkPeriod = DEFAULT_CHECK_PERIOD;
232 <                    _logger.write(this.toString(), Logger.WARNING, "Monitor.Heartbeat.checkPeriod value unavailable using default of " + checkPeriod + " seconds");
232 >                    _logger.write(Heartbeat__Monitor.this.toString(), Logger.WARNING, "Monitor.Heartbeat.checkPeriod value unavailable using default of " + checkPeriod + " seconds");
233                  } catch (NumberFormatException e) {
234                      checkPeriod = DEFAULT_CHECK_PERIOD;
235 <                    _logger.write(this.toString(), Logger.WARNING, "Erronous Monitor.Heartbeat.checkPeriod value in configuration using default of " + checkPeriod + " seconds");
235 >                    _logger.write(Heartbeat__Monitor.this.toString(), Logger.WARNING, "Erronous Monitor.Heartbeat.checkPeriod value in configuration using default of " + checkPeriod + " seconds");
236                  }
237                  
238 <                synchronized(this) {
238 >                synchronized(Heartbeat__Monitor.this) {
239                      // perform the checks (use HB hash, although they *should* be the same)
240                      Iterator i = _hosts.keySet().iterator();
241                      while(i.hasNext()) {
# Line 207 | Line 243 | public class Heartbeat__Monitor extends MonitorSkeleto
243                          String source = (String) i.next();
244                          // check it
245                          boolean remove = analyseHB(source);
246 +                        // remove it if it's passed a FINAL
247                          if(remove) {
248                              i.remove();
249                          }
# Line 217 | Line 254 | public class Heartbeat__Monitor extends MonitorSkeleto
254                  try {Thread.sleep(checkPeriod * 1000);} catch (InterruptedException e) {}
255              }
256          }
257 +        
258 +        /**
259 +         * Analyses a given host's state, and if need be generates
260 +         * a relevant Alert. Note that it also checks if the last
261 +         * alert sent is FINAL, in which case it returns true to
262 +         * indicate removal of this host.
263 +         *
264 +         * @param source the host to check
265 +         * @return whether this host can be deleted
266 +         */
267 +        private boolean analyseHB(String source) {
268 +            ConfigurationProxy cp = ConfigurationProxy.getInstance();
269 +            HeartbeatHolder hbHolder = (HeartbeatHolder) _hosts.get(source);
270 +            Register reg = hbHolder.getRegister();
271 +            
272 +            // get host's HB interval (seconds)
273 +            // this should always exist, thus we set to 0
274 +            int hostHBinterval = 0;
275 +            try {
276 +                hostHBinterval = Integer.parseInt(cp.getProperty("Host."+source, "Host.TCPUpdateTime"));
277 +            } catch (PropertyNotFoundException e) {
278 +                hostHBinterval = 0;
279 +                _logger.write(Heartbeat__Monitor.this.toString(), Logger.WARNING, "TCPUpdateTime value unavailable using default of " + hostHBinterval + " seconds");
280 +            } catch (NumberFormatException e) {
281 +                hostHBinterval = 0;
282 +                _logger.write(Heartbeat__Monitor.this.toString(), Logger.WARNING, "Erronous TCPUpdateTime value in configuration using default of " + hostHBinterval + " seconds");
283 +            }
284 +            
285 +            // get host's last HB time (seconds)
286 +            long lastHeartbeat = hbHolder.getLastHeartbeat();
287 +            // time since last heartbeat (seconds)
288 +            long timeSinceLastHB = (System.currentTimeMillis()/1000) - lastHeartbeat;
289 +            // time since (or until if negative) the expected heartbeat
290 +            long timeSinceExpectedHB = timeSinceLastHB - (long) hostHBinterval;
291 +            
292 +            // best do a check in case the expected heartbeat is in the future
293 +            if(timeSinceExpectedHB < 0) {
294 +                timeSinceExpectedHB = 0;
295 +            }
296 +            
297 +            // find out the threshold level we're at
298 +            int newThreshold = checkAttributeThreshold(timeSinceExpectedHB, reg);
299 +            
300 +            // process the alert
301 +            Heartbeat__Monitor.this.processAlert(newThreshold, "Heartbeat", reg, source, String.valueOf(timeSinceExpectedHB));
302 +            
303 +            if(reg.getLastAlertLevel() == Alert.alertFINAL) {
304 +                return true;
305 +            }
306 +            return false;
307 +        }
308      }
221
309   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines