View Javadoc

1   package org.csc.phynixx.watchdog;
2   
3   /*
4    * #%L
5    * phynixx-watchdog
6    * %%
7    * Copyright (C) 2014 csc
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  
24  import org.apache.log4j.LogManager;
25  import org.apache.log4j.Logger;
26  import org.csc.phynixx.common.generator.IDGenerator;
27  import org.csc.phynixx.common.generator.IDGenerators;
28  
29  import java.util.*;
30  
31  
32  /**
33   * @author
34   * @version $Revision: 1.6 $
35   * @project phynixx
36   * @see ThreadGroup
37   */
38  public class WatchdogRegistry {
39  
40  
41      private static final IDGenerator<Long> ID_GENERATOR = IDGenerators.createLongGenerator(1, true);
42  
43      private static final String WATCHDOG_MANAGEMENT_INTERVAL_PROP = "org.csc.phynixx.watchdog.management_interval";
44  
45      public static final String OK = "ok";
46  
47      private static long WATCHDOG_MANAGEMENT_INTERVAL = 1100;
48  
49  
50      private static WatchdogRegistry theRegistry = null;
51  
52      public interface IWatchdogVisitor {
53          void visit(IWatchdog th);
54      }
55  
56      private Watchdog watchTheWatchdogs = null;
57      private Watchdog watchTheWatchdogWatcher = null;
58  
59  
60      public static long getWatchdogManagementInterval() {
61          return WATCHDOG_MANAGEMENT_INTERVAL;
62      }
63  
64      public static void setWatchdogManagementInterval(long watchdogManagementInterval) {
65          WatchdogRegistry.WATCHDOG_MANAGEMENT_INTERVAL = watchdogManagementInterval;
66  
67          // lock all restart conditions and assign a new check interval ...
68          Set conditions = WatchdogRegistry.theRegistry.watchTheWatchdogs.getAliveConditions();
69          conditions.addAll(WatchdogRegistry.theRegistry.watchTheWatchdogWatcher.getAliveConditions());
70          for (Iterator iterator = conditions.iterator(); iterator.hasNext(); ) {
71              IWatchedCondition cond = (IWatchedCondition) iterator.next();
72              if (cond instanceof TimeoutCondition) {
73                  TimeoutCondition toCond = (TimeoutCondition) cond;
74                  synchronized (toCond) {
75                      toCond.resetCondition(WatchdogRegistry.WATCHDOG_MANAGEMENT_INTERVAL);
76                  }
77  
78              }
79  
80          }
81      }
82  
83      public static long getWatchTheWatchdogInterval() {
84          return WATCHDOG_MANAGEMENT_INTERVAL;
85      }
86  
87  
88      static {
89          WatchdogRegistry.WATCHDOG_MANAGEMENT_INTERVAL = Long.getLong(WATCHDOG_MANAGEMENT_INTERVAL_PROP, 5000).longValue();
90  
91          WatchdogRegistry.theRegistry = new WatchdogRegistry();
92      }
93  
94      private WatchdogRegistry() {
95          // System.out.println("Start the WatchdogRegistry");
96          this.watchTheWatchdogs = new Watchdog(ID_GENERATOR.generate(), WatchdogRegistry.getWatchdogManagementInterval() / 2, "Watches The Watchdogs");
97          this.watchTheWatchdogWatcher = new Watchdog(ID_GENERATOR.generate(), WatchdogRegistry.getWatchdogManagementInterval() / 2, "Watches The WatchdogWatcher");
98  
99          IWatchedCondition watchesTheWatcherCond =
100                 new RestartCondition(WatchdogRegistry.getWatchdogManagementInterval(), watchTheWatchdogs) {
101                     public String toString() {
102                         return new StringBuffer("watches the watchdog watcher ").
103                                 append("isActive=").append(this.isActive()).
104                                 append(" Watched WD.isAlive=").append(watchTheWatchdogs.isAlive()).
105                                 append(" Watched WD.isKilled=").append(watchTheWatchdogs.isKilled()).
106                                 toString();
107                     }
108                 };
109 
110 
111         watchesTheWatcherCond.setActive(true);
112         this.watchTheWatchdogWatcher.registerCondition(watchesTheWatcherCond, false);
113 
114         /**
115          * checks if the
116          */
117         IWatchedCondition managementActivity = new TimeoutCondition(WATCHDOG_MANAGEMENT_INTERVAL) {
118 
119             public void conditionViolated() {
120                 this.resetCondition();
121                 WatchdogRegistry.getTheRegistry().clearOut();
122             }
123 
124         };
125         managementActivity.setActive(true);
126         this.watchTheWatchdogWatcher.registerCondition(managementActivity, false);
127 
128         this.restartManagementWatchdogs();
129 
130     }
131 
132 
133     /**
134      * Logger
135      */
136     protected Logger log = LogManager.getLogger(this.getClass());
137 
138     /**
139      * @associates WorkerThread
140      */
141     private Map registeredWachdogs = new HashMap();
142 
143     private void checkManagementWatchdogs() {
144         if (watchTheWatchdogs == null || !watchTheWatchdogs.isAlive()) {
145             throw new IllegalStateException("WatchTheWatchdogs is not started -> call WatchdogRegistry.restart()");
146         }
147         if (watchTheWatchdogWatcher == null || !watchTheWatchdogWatcher.isAlive()) {
148             throw new IllegalStateException("WatchTheWatchdogWatcher is not started -> call WatchdogRegistry.restart()");
149         }
150     }
151 
152     private void restartManagementWatchdogs() {
153 
154         if (watchTheWatchdogs != null && (!watchTheWatchdogs.isAlive())) {
155             watchTheWatchdogs.restart();
156             watchTheWatchdogs.activate();
157         }
158         if (watchTheWatchdogWatcher != null && (!watchTheWatchdogWatcher.isAlive())) {
159             watchTheWatchdogWatcher.restart();
160             watchTheWatchdogWatcher.activate();
161         }
162     }
163 
164     private void shutdownManagementWatchdogs() {
165 
166 
167         if (watchTheWatchdogs != null && (watchTheWatchdogs.isAlive())) {
168             watchTheWatchdogs.stop();
169         }
170         if (watchTheWatchdogWatcher != null && (watchTheWatchdogWatcher.isAlive())) {
171             watchTheWatchdogWatcher.stop();
172         }
173     }
174 
175     public WatchdogInfo[] getManagementWatchdogsInfo() {
176 
177         WatchdogInfo[] wds = new WatchdogInfo[2];
178         wds[0] = new WatchdogInfo(watchTheWatchdogs);
179         wds[1] = new WatchdogInfo(watchTheWatchdogWatcher);
180 
181         return wds;
182     }
183 
184     public synchronized String getManagementWatchdogsState() {
185         if (!watchTheWatchdogs.isAlive() || !watchTheWatchdogWatcher.isAlive()) {
186 
187             return "Management Watchdogs aren't alive  -> restart it";
188         }
189 
190         return OK;
191     }
192 
193     public synchronized IWatchdog createWatchdog(final long checkInterval) {
194 
195         checkManagementWatchdogs();
196 
197         Watchdog wd = new Watchdog(ID_GENERATOR.generate(), checkInterval);
198 
199 
200         // the watchdigWatcher registered the new Watchdog ....
201 
202         IWatchedCondition restartCondition = wd.getRestartCondition();
203         restartCondition.setActive(true);
204 
205         watchTheWatchdogs.registerCondition(restartCondition, true);
206 
207         WatchdogRegistry.getTheRegistry().registerWatchdog(wd);
208 
209         if (log.isDebugEnabled()) {
210             log.debug("Watchdog created \n" + wd);
211             log.debug(watchTheWatchdogs);
212         }
213 
214         checkManagementWatchdogs();
215 
216         return wd;
217     }
218 
219 
220     public static WatchdogRegistry getTheRegistry() {
221         return theRegistry;
222     }
223 
224     /**
225      * Fuegt einen Thread hinzu
226      *
227      * @param key String Schluessel unter dem der Thread gespeichert wird
228      * @param wd  Watchdog
229      * @throws IllegalStateException falls Thread NICHT zur aktuellen ThreadGroup( ==this) geh�rt;
230      */
231     private synchronized void registerWatchdog(Long key, Watchdog wd) {
232         if (wd == null) {
233             throw new NullPointerException("Thread");
234         }
235         if (wd.getThread() == null) {
236             wd.restart();
237         }
238         registeredWachdogs.put(key, wd);
239     }
240 
241     /**
242      * Thread wird unter seinem Namen verwaltet (t.getName())
243      *
244      * @param wd Watchdog
245      * @throws IllegalStateException falls Thread NICHT zur aktuellen ThreadGroup( ==this) geh�rt;
246      */
247     public void registerWatchdog(Watchdog wd) {
248         registerWatchdog(wd.getId(), wd);
249     }
250 
251     public synchronized void deregisterWatchdog(Long key) {
252         if (registeredWachdogs.containsKey(key)) {
253             registeredWachdogs.remove(key);
254         }
255     }
256 
257     synchronized Watchdog findWatchdog(Long id) {
258         Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
259         if (wd == null) {
260             return null;
261         }
262         return wd;
263     }
264 
265     public synchronized IWatchdog resolveWatchdogId(Long id) {
266         Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
267         if (wd == null) {
268             return null;
269         }
270         return new WatchdogReference(wd);
271     }
272 
273 
274     public void deregisterWatchdog(IWatchdog wd) {
275         deregisterWatchdog(wd.getId());
276     }
277 
278 
279     public synchronized void clearOut() {
280 
281         // shutdown all watchdogs
282         Set copy = new HashSet(registeredWachdogs.values());
283         Iterator iter = copy.iterator();
284         while (iter.hasNext()) {
285             Watchdog wd = (Watchdog) iter.next();
286             if (wd.isUseless()) {
287                 wd.kill();
288                 this.deregisterWatchdog(wd);
289                 if (log.isInfoEnabled()) {
290                     log.info("WatchdogRegistry.restart() : Watchdog " + wd.getId() + " closed");
291                 }
292             }
293         }
294 
295     }
296 
297     /**
298      * restarts all Watchdogs
299      */
300     public synchronized void restart() {
301 
302         restartManagementWatchdogs();
303         // shutdown all watchdogs
304         Set copy = new HashSet(registeredWachdogs.values());
305         Iterator iter = copy.iterator();
306         while (iter.hasNext()) {
307             Watchdog wd = (Watchdog) iter.next();
308             if (wd.isUseless()) {
309                 wd.kill();
310                 this.deregisterWatchdog(wd);
311                 if (log.isInfoEnabled()) {
312                     log.info("WatchdogRegistry.restart() : Watchdog " + wd.getId() + " closed");
313                 }
314             } else if (!wd.isAlive() && !wd.isKilled()) {
315                 wd.restart();
316                 if (log.isInfoEnabled()) {
317                     log.info("WatchdogRegistry.restart() : Watchdog " + wd.getId() + " restarted");
318                 }
319             }
320         }
321 
322     }
323 
324     /**
325      * restarts all Watchdogs
326      */
327     public synchronized void stop() {
328         // stopps all watchdogs
329         Iterator iter = registeredWachdogs.values().iterator();
330         while (iter.hasNext()) {
331             Watchdog wd = (Watchdog) iter.next();
332             wd.stop();
333             if (log.isInfoEnabled()) {
334                 log.info("WatchdogRegistry.stop() : Watchdog " + wd.getId() + " is stopped");
335             }
336         }
337 
338 
339     }
340 
341     /**
342      * activates all Watchdogs
343      */
344     public synchronized void activate() {
345         // activate all Watchdogs ....
346         Iterator iter = registeredWachdogs.values().iterator();
347 
348         while (iter.hasNext()) {
349             IWatchdog th = (IWatchdog) iter.next();
350             th.activate();
351             if (log.isInfoEnabled()) {
352                 log.info(". . . Activating Watchdog " + th.getId());
353             }
354         }
355     }
356 
357     /**
358      * restarts all Watchdogs
359      */
360     public synchronized void deactivate() {
361         Iterator iter = registeredWachdogs.values().iterator();
362         while (iter.hasNext()) {
363             IWatchdog th = (IWatchdog) iter.next();
364             th.deactivate();
365             if (log.isInfoEnabled()) {
366                 log.info(". . . deactivating Watchdog " + th.getId());
367             }
368         }
369     }
370 
371 
372     /**
373      * killt alle Threads der Gruppe
374      */
375     private void kill() {
376         Set copy = new HashSet(registeredWachdogs.values());
377         Iterator iter = copy.iterator();
378         while (iter.hasNext()) {
379             Watchdog th = (Watchdog) iter.next();
380             if (th.isAlive()) {
381 
382                 if (log.isInfoEnabled()) {
383                     log.info(". . . Killing Watchdog " + th.getId());
384                 }
385                 th.kill();
386             }
387         }
388 
389         this.joinAllThreads();
390 
391         // remove all Watchdogs frim the registry ....
392         iter = copy.iterator();
393         while (iter.hasNext()) {
394             this.deregisterWatchdog((IWatchdog) iter.next());
395         }
396     }
397 
398 
399     /**
400      * killt alle Threads der Gruppe und wartet bis auch der letzte beendet ist.
401      * Es wird der evtl. Exceptionhandler geschlossen.
402      */
403     public synchronized void shutdown() {
404         this.shutdownManagementWatchdogs();
405 
406         // deactivate all Watchdogs ....
407         Iterator iter = registeredWachdogs.values().iterator();
408         while (iter.hasNext()) {
409             IWatchdog th = (IWatchdog) iter.next();
410             th.deactivate();
411             if (log.isInfoEnabled()) {
412                 log.info(". . . Deactivating Watchdog " + th.getId());
413             }
414         }
415 
416         this.kill();
417 
418     }
419 
420     /**
421      * wartet bis auch der letzte Thread beendet ist
422      */
423     private void joinAllThreads() {
424         Iterator iter = registeredWachdogs.values().iterator();
425         while (iter.hasNext()) {
426             Watchdog th = (Watchdog) iter.next();
427             boolean isJoining = true;
428             if (!th.isAlive() && log.isDebugEnabled()) {
429                 log.debug("Thread " + th + " finished");
430             }
431             while (th.isAlive() && isJoining) {
432                 try {
433                     th.getThread().join();
434                     isJoining = false;
435                     if (log.isDebugEnabled()) {
436                         log.debug("Thread " + th + " joined and finished");
437                     }
438                 } catch (InterruptedException e) {
439                 }
440             }
441         }
442     }
443 
444 
445     public synchronized int getCountWatchdogs() {
446         return this.registeredWachdogs.size();
447     }
448 
449 
450     public WatchdogInfo[] getWatchdogInfos() {
451 
452         final List watchdogs = new ArrayList();
453         WatchdogRegistry.IWatchdogVisitor visitor = new WatchdogRegistry.IWatchdogVisitor() {
454             public void visit(IWatchdog wd) {
455                 watchdogs.add(new WatchdogInfo(wd));
456             }
457         };
458         this.visitWatchdogRegistry(visitor);
459 
460         WatchdogInfo[] wds = new WatchdogInfo[watchdogs.size()];
461         int i = 0;
462         for (Iterator iterator = watchdogs.iterator(); iterator.hasNext(); i++) {
463             WatchdogInfo info = (WatchdogInfo) iterator.next();
464             wds[i] = info;
465         }
466         return wds;
467     }
468 
469 
470     public String[][] showWatchdogInfos() {
471 
472         WatchdogInfo[] infos = this.getWatchdogInfos();
473         String[][] wds = new String[infos.length][];
474         for (int j = 0; j < infos.length; j++) {
475             wds[j] = infos[j].getWatchdogInfos();
476         }
477         return wds;
478 
479     }
480 
481 
482     /**
483      *
484      **/
485     public synchronized void visitWatchdogRegistry(IWatchdogVisitor visitor) {
486         Iterator iter = registeredWachdogs.values().iterator();
487         while (iter.hasNext()) {
488             IWatchdog th = (IWatchdog) iter.next();
489             visitor.visit(th);
490         }
491 
492     }
493 
494     /**
495      * stops the the Watchdog with the given id
496      * The executing thread of the watchdog is stopped, but the watchdog is not
497      * removed from the registry.
498      * It can be restarted
499      *
500      * @throws IllegalStateException Watchdog does not exist,
501      *                               check existence with {@link #findWatchdog(Long)}
502      * @see #restart(Long)
503      * @see #shutdown(Long)
504      */
505     public void stop(Long id) {
506 
507         Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
508         if (wd == null) {
509             throw new IllegalStateException("Watchdog " + id + " ist not registered");
510         }
511         wd.stop();
512     }
513 
514 
515     /**
516      * stops the the Watchdog with the given id
517      * The executing thread of the watchdog is stopped and the watchdog is removed from the registry.
518      * <p/>
519      * It can nor be restarted
520      *
521      * @throws IllegalStateException Watchdog does not exist,
522      *                               check existence with {@link #findWatchdog(Long)}
523      * @see #restart(Long)
524      * @see #stop(Long)
525      */
526     public void shutdown(Long id) {
527 
528         Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
529         if (wd == null) {
530             throw new IllegalStateException("Watchdog " + id + " ist not registered");
531         }
532         wd.kill();
533         this.deregisterWatchdog(id);
534     }
535 
536 
537     /**
538      * restart the Watchdog with the given id
539      *
540      * @throws IllegalStateException Watchdog does not exist,
541      *                               check existence with {@link #findWatchdog(Long)}
542      */
543     public void restart(Long id) {
544 
545         Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
546         if (wd == null) {
547             throw new IllegalStateException("Watchdog " + id + " ist not registered");
548         }
549         wd.restart();
550     }
551 
552     /**
553      * deactivates all Conditions of the Watchdog with the given id
554      *
555      * @throws IllegalStateException Watchdog does not exist,
556      *                               check existence with {@link #findWatchdog(Long)}
557      */
558     public void deactivate(Long id) {
559 
560         Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
561         if (wd == null) {
562             throw new IllegalStateException("Watchdog " + id + " ist not registered");
563         }
564         wd.deactivate();
565     }
566 
567     /**
568      * activates all Conditions of the Watchdog with the given id
569      *
570      * @throws IllegalStateException Watchdog does not exist,
571      *                               check existence with {@link #findWatchdog(Long)}
572      */
573     public void activate(Long id) {
574 
575         Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
576         if (wd == null) {
577             throw new IllegalStateException("Watchdog " + id + " ist not registered");
578         }
579         wd.activate();
580     }
581 
582 
583 }