001: package com.rimfaxe.thread;
002:
003: import java.util.*;
004:
005: /** The ThreadWatchDog class is the watchdog used to monitor threads
006: * in an application. There are two dogs used to monitor, the ALPHA_DOG
007: * and the BETA_DOG. The BETA_DOG's sole responsibility is to monitor
008: * the ALPHA_DOG. The ALPHA_DOG monitors the BETA_DOG and all assigned
009: * threads for monitoring. If a thread dies, the dogs will report an
010: * exception. If the dead thread is a MutableThread, the dog will try to
011: * restart it.
012: */
013: public class ThreadWatchDog extends MutableThread {
014:
015: private static ThreadWatchDog mAlphaThread = null; // alphadog instance
016: private static ThreadWatchDog mBetaThread = null; // betadog instance
017: private static HashMap mThreadHashMap = null; // vector of all threads
018: private static int mAlphaPriority = Thread.NORM_PRIORITY;
019: private static int mBetaPriority = Thread.NORM_PRIORITY;
020: private static long POLL_TIME = 3000; // 3 second check for TEST Change this to 60000 for one min. etc
021: /** The attribute mWatchDogPollCount is added for test interest. It shows
022: * how many times the polling has occurred within the dog.
023: */
024: public int mWatchDogPollCount = 0; // test count
025: private int mDogIdentity = 0;
026:
027: private ThreadWatchDog() {
028: super ();
029: mThreadHashMap = new HashMap();
030: }
031:
032: public void endWatching() {
033: mAlphaThread.clear();
034: mBetaThread.clear();
035: }
036:
037: public void clear() {
038: mThreadHashMap = new HashMap();
039: }
040:
041: /** The getInstance method insures that the ALPHA_DOG (and therefore also
042: * the BETA_DOG) is a singleton. It is static so that it can be referenced
043: * throughout the application within the JVM.
044: */
045: public synchronized static ThreadWatchDog getInstance() {
046: if (mAlphaThread == null) {
047: mAlphaThread = new ThreadWatchDog();
048: mAlphaThread.setPriority(mAlphaPriority);
049: mAlphaThread.setName("ALPHA DOG");
050: mBetaThread = new ThreadWatchDog();
051: mBetaThread.setPriority(mBetaPriority);
052: mBetaThread.setName("BETA DOG");
053: // these dogs watch each other
054: mAlphaThread.put(mBetaThread);
055: mBetaThread.put(mAlphaThread);
056: }
057: return mAlphaThread;
058: }
059:
060: /** This is the run method for the thread.
061: */
062: public void run() {
063: //System.out.println("run()");
064: while (true) {
065:
066: try {
067: //System.out.println("checkAllThreads()");
068: checkAllThreads();
069: poll();
070:
071: } catch (ReportingException eReportingException) {
072: ReportingExceptionHandler
073: .processException(eReportingException);
074: }
075: }
076: }
077:
078: /** The checkAllThreads method for a dog checks each thread which has been
079: * put into the HashMap.
080: */
081:
082: public synchronized void checkAllThreads() {
083:
084: Set lThreadSet = mThreadHashMap.keySet();
085: Iterator lThreadIterator = lThreadSet.iterator();
086:
087: while (lThreadIterator.hasNext()) {
088: String lThreadKey = (String) lThreadIterator.next();
089: Object lTestThread = mThreadHashMap.get(lThreadKey);
090:
091: if (lTestThread instanceof MutableThread) {
092:
093: if (!((MutableThread) lTestThread).isAlive()) {
094: ReportingExceptionHandler
095: .processException(new ReportingException(
096: "Mutable Thread " + lThreadKey
097: + " is dead"));
098: try {
099: ReportingLogger
100: .logDebug("Attempting to restart thread : "
101: + lThreadKey);
102: // attempt to restart the thread by clearing and restarting
103: ReportingLogger.logDebug("Creating Thread for "
104: + lThreadKey);
105: ((MutableThread) lTestThread).createThread();
106: ReportingLogger.logDebug("Starting "
107: + lThreadKey);
108: ((MutableThread) lTestThread).start();
109: ReportingLogger.logDebug("Restart Successful");
110: } catch (Exception eException) {
111: ReportingException lReportingException = new ReportingException(
112: "Thread " + lThreadKey
113: + " restart failure");
114: lReportingException.put("eException",
115: eException);
116: ReportingExceptionHandler
117: .processException(lReportingException);
118: }
119: } else {
120: ReportingLogger.logDebug("Mutable Thread "
121: + ((MutableThread) lTestThread).getName()
122: + " is Alive");
123: }
124:
125: ReportingLogger.logDebug("Thread "
126: + ((MutableThread) lTestThread).getName()
127: + " is alive ");
128: } else { // not a Mutable thread
129: if (!((Thread) lTestThread).isAlive()) {
130:
131: // LOG this except for "BETA DOG" and "ALPHA DOG"
132:
133: if ((!lThreadKey.equalsIgnoreCase("ALPHA DOG"))
134: && (!lThreadKey
135: .equalsIgnoreCase("BETA DOG"))) {
136: com.rimfaxe.util.Log.log("Thread " + lThreadKey
137: + " is being restarted");
138: }
139:
140: ReportingExceptionHandler
141: .processException(new ReportingException(
142: "Thread " + lThreadKey + " is dead"));
143: } else {
144: // thread is alive
145: ReportingLogger.logDebug("Thread "
146: + ((Thread) lTestThread).getName()
147: + " is Alive");
148: }
149: }
150: }
151:
152: }
153:
154: /** The put method puts a mutable thread into the HashMap for monitoring by a dog.
155: * Note that this is an overloaded method which also allows for non-mutable Threads to
156: * be monitored as well.
157: */
158: public synchronized void put(MutableThread aMutableThread) {
159: ReportingLogger
160: .logDebug("ThreadWatchDog.adding mutable thread : "
161: + aMutableThread.getName());
162: mThreadHashMap.put(aMutableThread.getName(), aMutableThread);
163: }
164:
165: public synchronized void remove(MutableThread aMutableThread) {
166: ReportingLogger
167: .logDebug("ThreadWatchDog.adding mutable thread : "
168: + aMutableThread.getName());
169: mThreadHashMap.remove(aMutableThread.getName());
170: }
171:
172: /** The put method causes the dog to monitor the passed Thread.
173: */
174: public synchronized void put(Thread aThread) {
175: ReportingLogger.logDebug("ThreadWatchDog.adding thread : "
176: + aThread.getName());
177: mThreadHashMap.put(aThread.getName(), aThread);
178: }
179:
180: private synchronized void poll() throws ReportingException {
181: try {
182: mWatchDogPollCount++; // for test and monitoring, shows the number of times polling has occurred
183: ReportingLogger.logDebug("WatchDogPollCount is "
184: + mWatchDogPollCount + " for " + this .getName());
185: this .wait(POLL_TIME);
186: } catch (InterruptedException eInterruptedException) {
187: ReportingException lReportingException = new ReportingException(
188: "Interrupted Exception Thread WatchDog poll");
189: lReportingException.put("eInterruptedException",
190: eInterruptedException);
191: throw lReportingException;
192: }
193:
194: }
195:
196: }
|