package org.csc.phynixx.watchdog;
/*
* #%L
* phynixx-watchdog
* %%
* Copyright (C) 2014 csc
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.csc.phynixx.common.generator.IDGenerator;
import org.csc.phynixx.common.generator.IDGenerators;
import org.csc.phynixx.common.logger.IPhynixxLogger;
import org.csc.phynixx.common.logger.PhynixxLogManager;
import java.util.*;
/**
* @author
* @version $Revision: 1.6 $
* @see ThreadGroup
*/
public class WatchdogRegistry {
private static final IDGenerator<Long> ID_GENERATOR = IDGenerators.createLongGenerator(1, true);
private static final String WATCHDOG_MANAGEMENT_INTERVAL_PROP = "org.csc.phynixx.watchdog.management_interval";
public static final String OK = "ok";
private static long WATCHDOG_MANAGEMENT_INTERVAL = 1100;
private static WatchdogRegistry theRegistry = null;
public interface IWatchdogVisitor {
void visit(IWatchdog th);
}
private Watchdog watchTheWatchdogs = null;
private Watchdog watchTheWatchdogWatcher = null;
public static long getWatchdogManagementInterval() {
return WATCHDOG_MANAGEMENT_INTERVAL;
}
public static void setWatchdogManagementInterval(long watchdogManagementInterval) {
WatchdogRegistry.WATCHDOG_MANAGEMENT_INTERVAL = watchdogManagementInterval;
// lock all restart conditions and assign a new check interval ...
Set conditions = WatchdogRegistry.theRegistry.watchTheWatchdogs.getAliveConditions();
conditions.addAll(WatchdogRegistry.theRegistry.watchTheWatchdogWatcher.getAliveConditions());
for (Iterator iterator = conditions.iterator(); iterator.hasNext(); ) {
IWatchedCondition cond = (IWatchedCondition) iterator.next();
if (cond instanceof TimeoutCondition) {
TimeoutCondition toCond = (TimeoutCondition) cond;
synchronized (toCond) {
toCond.resetCondition(WatchdogRegistry.WATCHDOG_MANAGEMENT_INTERVAL);
}
}
}
}
public static long getWatchTheWatchdogInterval() {
return WATCHDOG_MANAGEMENT_INTERVAL;
}
static {
WatchdogRegistry.WATCHDOG_MANAGEMENT_INTERVAL = Long.getLong(WATCHDOG_MANAGEMENT_INTERVAL_PROP, 5000).longValue();
WatchdogRegistry.theRegistry = new WatchdogRegistry();
}
private WatchdogRegistry() {
// System.out.println("Start the WatchdogRegistry");
this.watchTheWatchdogs = new Watchdog(ID_GENERATOR.generate(), WatchdogRegistry.getWatchdogManagementInterval() / 2, "Watches The Watchdogs");
this.watchTheWatchdogWatcher = new Watchdog(ID_GENERATOR.generate(), WatchdogRegistry.getWatchdogManagementInterval() / 2, "Watches The WatchdogWatcher");
IWatchedCondition watchesTheWatcherCond =
new RestartCondition(WatchdogRegistry.getWatchdogManagementInterval(), watchTheWatchdogs) {
public String toString() {
return new StringBuffer("watches the watchdog watcher ").
append("isActive=").append(this.isActive()).
append(" Watched WD.isAlive=").append(watchTheWatchdogs.isAlive()).
append(" Watched WD.isKilled=").append(watchTheWatchdogs.isKilled()).
toString();
}
};
watchesTheWatcherCond.setActive(true);
this.watchTheWatchdogWatcher.registerCondition(watchesTheWatcherCond, false);
/**
* checks if the
*/
IWatchedCondition managementActivity = new TimeoutCondition(WATCHDOG_MANAGEMENT_INTERVAL) {
public void conditionViolated() {
this.resetCondition();
WatchdogRegistry.getTheRegistry().clearOut();
}
};
managementActivity.setActive(true);
this.watchTheWatchdogWatcher.registerCondition(managementActivity, false);
this.restartManagementWatchdogs();
}
/**
* Logger
*/
protected IPhynixxLogger log = PhynixxLogManager.getLogger(this.getClass());
/**
* @associates WorkerThread
*/
private Map registeredWachdogs = new HashMap();
private void checkManagementWatchdogs() {
if (watchTheWatchdogs == null || !watchTheWatchdogs.isAlive()) {
throw new IllegalStateException("WatchTheWatchdogs is not started -> call WatchdogRegistry.restart()");
}
if (watchTheWatchdogWatcher == null || !watchTheWatchdogWatcher.isAlive()) {
throw new IllegalStateException("WatchTheWatchdogWatcher is not started -> call WatchdogRegistry.restart()");
}
}
private void restartManagementWatchdogs() {
if (watchTheWatchdogs != null && (!watchTheWatchdogs.isAlive())) {
watchTheWatchdogs.restart();
watchTheWatchdogs.activate();
}
if (watchTheWatchdogWatcher != null && (!watchTheWatchdogWatcher.isAlive())) {
watchTheWatchdogWatcher.restart();
watchTheWatchdogWatcher.activate();
}
}
private void shutdownManagementWatchdogs() {
if (watchTheWatchdogs != null && (watchTheWatchdogs.isAlive())) {
watchTheWatchdogs.stop();
}
if (watchTheWatchdogWatcher != null && (watchTheWatchdogWatcher.isAlive())) {
watchTheWatchdogWatcher.stop();
}
}
public WatchdogInfo[] getManagementWatchdogsInfo() {
WatchdogInfo[] wds = new WatchdogInfo[2];
wds[0] = new WatchdogInfo(watchTheWatchdogs);
wds[1] = new WatchdogInfo(watchTheWatchdogWatcher);
return wds;
}
public synchronized String getManagementWatchdogsState() {
if (!watchTheWatchdogs.isAlive() || !watchTheWatchdogWatcher.isAlive()) {
return "Management Watchdogs aren't alive -> restart it";
}
return OK;
}
public synchronized IWatchdog createWatchdog(final long checkInterval) {
checkManagementWatchdogs();
Watchdog wd = new Watchdog(ID_GENERATOR.generate(), checkInterval);
// the watchdigWatcher registered the new Watchdog ....
IWatchedCondition restartCondition = wd.getRestartCondition();
restartCondition.setActive(true);
watchTheWatchdogs.registerCondition(restartCondition, true);
WatchdogRegistry.getTheRegistry().registerWatchdog(wd);
if (log.isDebugEnabled()) {
log.debug("Watchdog created \n" + wd);
log.debug(watchTheWatchdogs.toString());
}
checkManagementWatchdogs();
return wd;
}
public static WatchdogRegistry getTheRegistry() {
return theRegistry;
}
/**
* Fuegt einen Thread hinzu
*
* @param key String Schluessel unter dem der Thread gespeichert wird
* @param wd Watchdog
* @throws IllegalStateException falls Thread NICHT zur aktuellen ThreadGroup( ==this) geh�rt;
*/
private synchronized void registerWatchdog(Long key, Watchdog wd) {
if (wd == null) {
throw new NullPointerException("Thread");
}
if (wd.getThread() == null) {
wd.restart();
}
registeredWachdogs.put(key, wd);
}
/**
* Thread wird unter seinem Namen verwaltet (t.getName())
*
* @param wd Watchdog
* @throws IllegalStateException falls Thread NICHT zur aktuellen ThreadGroup( ==this) geh�rt;
*/
public void registerWatchdog(Watchdog wd) {
registerWatchdog(wd.getId(), wd);
}
public synchronized void deregisterWatchdog(Long key) {
if (registeredWachdogs.containsKey(key)) {
registeredWachdogs.remove(key);
}
}
synchronized Watchdog findWatchdog(Long id) {
Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
if (wd == null) {
return null;
}
return wd;
}
public synchronized IWatchdog resolveWatchdogId(Long id) {
Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
if (wd == null) {
return null;
}
return new WatchdogReference(wd);
}
public void deregisterWatchdog(IWatchdog wd) {
deregisterWatchdog(wd.getId());
}
public synchronized void clearOut() {
// shutdown all watchdogs
Set copy = new HashSet(registeredWachdogs.values());
Iterator iter = copy.iterator();
while (iter.hasNext()) {
Watchdog wd = (Watchdog) iter.next();
if (wd.isUseless()) {
wd.kill();
this.deregisterWatchdog(wd);
if (log.isInfoEnabled()) {
log.info("WatchdogRegistry.restart() : Watchdog " + wd.getId() + " closed");
}
}
}
}
/**
* restarts all Watchdogs
*/
public synchronized void restart() {
restartManagementWatchdogs();
// shutdown all watchdogs
Set copy = new HashSet(registeredWachdogs.values());
Iterator iter = copy.iterator();
while (iter.hasNext()) {
Watchdog wd = (Watchdog) iter.next();
if (wd.isUseless()) {
wd.kill();
this.deregisterWatchdog(wd);
if (log.isInfoEnabled()) {
log.info("WatchdogRegistry.restart() : Watchdog " + wd.getId() + " closed");
}
} else if (!wd.isAlive() && !wd.isKilled()) {
wd.restart();
if (log.isInfoEnabled()) {
log.info("WatchdogRegistry.restart() : Watchdog " + wd.getId() + " restarted");
}
}
}
}
/**
* restarts all Watchdogs
*/
public synchronized void stop() {
// stopps all watchdogs
Iterator iter = registeredWachdogs.values().iterator();
while (iter.hasNext()) {
Watchdog wd = (Watchdog) iter.next();
wd.stop();
if (log.isInfoEnabled()) {
log.info("WatchdogRegistry.stop() : Watchdog " + wd.getId() + " is stopped");
}
}
}
/**
* activates all Watchdogs
*/
public synchronized void activate() {
// activate all Watchdogs ....
Iterator iter = registeredWachdogs.values().iterator();
while (iter.hasNext()) {
IWatchdog th = (IWatchdog) iter.next();
th.activate();
if (log.isInfoEnabled()) {
log.info(". . . Activating Watchdog " + th.getId());
}
}
}
/**
* restarts all Watchdogs
*/
public synchronized void deactivate() {
Iterator iter = registeredWachdogs.values().iterator();
while (iter.hasNext()) {
IWatchdog th = (IWatchdog) iter.next();
th.deactivate();
if (log.isInfoEnabled()) {
log.info(". . . deactivating Watchdog " + th.getId());
}
}
}
/**
* killt alle Threads der Gruppe
*/
private void kill() {
Set copy = new HashSet(registeredWachdogs.values());
Iterator iter = copy.iterator();
while (iter.hasNext()) {
Watchdog th = (Watchdog) iter.next();
if (th.isAlive()) {
if (log.isInfoEnabled()) {
log.info(". . . Killing Watchdog " + th.getId());
}
th.kill();
}
}
this.joinAllThreads();
// remove all Watchdogs frim the registry ....
iter = copy.iterator();
while (iter.hasNext()) {
this.deregisterWatchdog((IWatchdog) iter.next());
}
}
/**
* killt alle Threads der Gruppe und wartet bis auch der letzte beendet ist.
* Es wird der evtl. Exceptionhandler geschlossen.
*/
public synchronized void shutdown() {
this.shutdownManagementWatchdogs();
// deactivate all Watchdogs ....
Iterator iter = registeredWachdogs.values().iterator();
while (iter.hasNext()) {
IWatchdog th = (IWatchdog) iter.next();
th.deactivate();
if (log.isInfoEnabled()) {
log.info(". . . Deactivating Watchdog " + th.getId());
}
}
this.kill();
}
/**
* wartet bis auch der letzte Thread beendet ist
*/
private void joinAllThreads() {
Iterator iter = registeredWachdogs.values().iterator();
while (iter.hasNext()) {
Watchdog th = (Watchdog) iter.next();
boolean isJoining = true;
if (!th.isAlive() && log.isDebugEnabled()) {
log.debug("Thread " + th + " finished");
}
while (th.isAlive() && isJoining) {
try {
th.getThread().join();
isJoining = false;
if (log.isDebugEnabled()) {
log.debug("Thread " + th + " joined and finished");
}
} catch (InterruptedException e) {
}
}
}
}
public synchronized int getCountWatchdogs() {
return this.registeredWachdogs.size();
}
public WatchdogInfo[] getWatchdogInfos() {
final List watchdogs = new ArrayList();
WatchdogRegistry.IWatchdogVisitor visitor = new WatchdogRegistry.IWatchdogVisitor() {
public void visit(IWatchdog wd) {
watchdogs.add(new WatchdogInfo(wd));
}
};
this.visitWatchdogRegistry(visitor);
WatchdogInfo[] wds = new WatchdogInfo[watchdogs.size()];
int i = 0;
for (Iterator iterator = watchdogs.iterator(); iterator.hasNext(); i++) {
WatchdogInfo info = (WatchdogInfo) iterator.next();
wds[i] = info;
}
return wds;
}
public String[][] showWatchdogInfos() {
WatchdogInfo[] infos = this.getWatchdogInfos();
String[][] wds = new String[infos.length][];
for (int j = 0; j < infos.length; j++) {
wds[j] = infos[j].getWatchdogInfos();
}
return wds;
}
/**
*
**/
public synchronized void visitWatchdogRegistry(IWatchdogVisitor visitor) {
Iterator iter = registeredWachdogs.values().iterator();
while (iter.hasNext()) {
IWatchdog th = (IWatchdog) iter.next();
visitor.visit(th);
}
}
/**
* stops the the Watchdog with the given id
* The executing thread of the watchdog is stopped, but the watchdog is not
* removed from the registry.
* It can be restarted
*
* @throws IllegalStateException Watchdog does not exist,
* check existence with {@link #findWatchdog(Long)}
* @see #restart(Long)
* @see #shutdown(Long)
*/
public void stop(Long id) {
Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
if (wd == null) {
throw new IllegalStateException("Watchdog " + id + " ist not registered");
}
wd.stop();
}
/**
* stops the the Watchdog with the given id
* The executing thread of the watchdog is stopped and the watchdog is removed from the registry.
* It can nor be restarted
*
* @throws IllegalStateException Watchdog does not exist,
* check existence with {@link #findWatchdog(Long)}
* @see #restart(Long)
* @see #stop(Long)
*/
public void shutdown(Long id) {
Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
if (wd == null) {
throw new IllegalStateException("Watchdog " + id + " ist not registered");
}
wd.kill();
this.deregisterWatchdog(id);
}
/**
* restart the Watchdog with the given id
*
* @throws IllegalStateException Watchdog does not exist,
* check existence with {@link #findWatchdog(Long)}
*/
public void restart(Long id) {
Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
if (wd == null) {
throw new IllegalStateException("Watchdog " + id + " ist not registered");
}
wd.restart();
}
/**
* deactivates all Conditions of the Watchdog with the given id
*
* @throws IllegalStateException Watchdog does not exist,
* check existence with {@link #findWatchdog(Long)}
*/
public void deactivate(Long id) {
Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
if (wd == null) {
throw new IllegalStateException("Watchdog " + id + " ist not registered");
}
wd.deactivate();
}
/**
* activates all Conditions of the Watchdog with the given id
*
* @throws IllegalStateException Watchdog does not exist,
* check existence with {@link #findWatchdog(Long)}
*/
public void activate(Long id) {
Watchdog wd = (Watchdog) this.registeredWachdogs.get(id);
if (wd == null) {
throw new IllegalStateException("Watchdog " + id + " ist not registered");
}
wd.activate();
}
}