KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > util > watchdog > InaccurateTimeoutWatchdog


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.util.watchdog;
19
20 import org.apache.avalon.excalibur.thread.ThreadPool;
21 import org.apache.avalon.framework.activity.Disposable;
22 import org.apache.avalon.framework.logger.AbstractLogEnabled;
23
24 /**
25  * This class represents an watchdog process that serves to
26  * monitor a situation and triggers an action after a certain time has
27  * passed. This implementation is deliberately inaccurate, trading
28  * accuracy for minimal impact on reset. This should be used when
29  * the time of the Watchdog trigger is not critical, and a high number
30  * of resets are expected.
31  *
32  */

33 public class InaccurateTimeoutWatchdog
34     extends AbstractLogEnabled
35     implements Watchdog, Runnable JavaDoc, Disposable {
36
37     /**
38      * Whether the watchdog is currently checking the trigger condition
39      */

40     private volatile boolean isChecking = false;
41
42     /**
43      * Whether the watchdog has been reset since the thread slept.
44      */

45     private volatile boolean isReset = false;
46
47
48     /**
49      * The number of milliseconds until the watchdog times out.
50      */

51     private final long timeout;
52
53     /**
54      * The last time the internal timer was reset, as measured in milliseconds since
55      * January 1, 1970 00:00:00.000 GMT.
56      */

57     private volatile long lastReset;
58
59     /**
60      * The WatchdogTarget whose execute() method will be called upon triggering
61      * of the condition.
62      */

63     private WatchdogTarget triggerTarget;
64
65     /**
66      * The thread that runs the watchdog.
67      */

68     private Thread JavaDoc watchdogThread;
69
70     /**
71      * The thread pool used to generate InaccurateTimeoutWatchdogs
72      */

73     private ThreadPool myThreadPool;
74
75     /**
76      * The sole constructor for the InaccurateTimeoutWatchdog
77      *
78      * @param timeout the time (in msec) that it will take the Watchdog to timeout
79      * @param target the WatchdogTarget to be executed when this Watchdog expires
80      * @param threadPool the thread pool used to generate threads for this implementation.
81      */

82     public InaccurateTimeoutWatchdog(long timeout, WatchdogTarget target, ThreadPool threadPool) {
83         if (target == null) {
84             throw new IllegalArgumentException JavaDoc("The WatchdogTarget for this TimeoutWatchdog cannot be null.");
85         }
86         if (threadPool == null) {
87             throw new IllegalArgumentException JavaDoc("The thread pool for this TimeoutWatchdog cannot be null.");
88         }
89         this.timeout = timeout;
90         triggerTarget = target;
91         myThreadPool = threadPool;
92     }
93
94     /**
95      * Start this Watchdog, causing it to begin checking.
96      */

97     public void start() {
98         getLogger().debug("Calling start()");
99         lastReset = System.currentTimeMillis();
100         isChecking = true;
101         synchronized(this) {
102             if ( watchdogThread == null) {
103                 myThreadPool.execute(this);
104             }
105         }
106     }
107
108     /**
109      * Reset this Watchdog. Tells the Watchdog thread to reset
110      * the timer when it next awakens.
111      */

112     public void reset() {
113         if (watchdogThread != null) {
114             getLogger().debug("Calling reset() " + watchdogThread.getName());
115         } else {
116             getLogger().debug("Calling reset() for inactive watchdog");
117         }
118         isReset = true;
119     }
120
121     /**
122      * Stop this Watchdog, causing the Watchdog to stop checking the trigger
123      * condition. The monitor can be restarted with a call to startWatchdog.
124      */

125     public void stop() {
126         if (watchdogThread != null) {
127             getLogger().debug("Calling stop() " + watchdogThread.getName());
128         } else {
129             getLogger().debug("Calling stop() for inactive watchdog");
130         }
131         isChecking = false;
132     }
133
134     /**
135      * Execute the body of the Watchdog, triggering as appropriate.
136      */

137     public void run() {
138
139         try {
140             watchdogThread = Thread.currentThread();
141
142             while ((!(Thread.currentThread().interrupted())) && (watchdogThread != null)) {
143                 try {
144                     if (!isChecking) {
145                         if (getLogger().isDebugEnabled()) {
146                             getLogger().debug("Watchdog " + Thread.currentThread().getName() + " is not active - going to exit.");
147                         }
148                         synchronized (this) {
149                             if (!isChecking) {
150                                 watchdogThread = null;
151                             }
152                             continue;
153                         }
154                     } else {
155                         long currentTime = System.currentTimeMillis();
156                         if (isReset) {
157                             isReset = false;
158                             lastReset = currentTime;
159                         }
160                         long timeToSleep = lastReset + timeout - currentTime;
161                         if (watchdogThread != null) {
162                             getLogger().debug("Watchdog " + watchdogThread.getName() + " has time to sleep " + timeToSleep);
163                         } else {
164                             getLogger().debug("Watchdog has time to sleep " + timeToSleep);
165                         }
166                         if (timeToSleep <= 0) {
167                             try {
168                                 synchronized (this) {
169                                     if ((isChecking) && (triggerTarget != null)) {
170                                         triggerTarget.execute();
171                                     }
172                                     watchdogThread = null;
173                                 }
174                             } catch (Throwable JavaDoc t) {
175                                 getLogger().error("Encountered error while executing Watchdog target.", t);
176                             }
177                             isChecking = false;
178                             continue;
179                         } else {
180                             synchronized(this) {
181                                 wait(timeToSleep);
182                             }
183                         }
184                     }
185                 } catch (InterruptedException JavaDoc ie) {
186                 }
187             }
188
189             synchronized( this ) {
190                 watchdogThread = null;
191             }
192         } finally {
193             // Ensure that the thread is in a non-interrupted state when it gets returned
194
// to the pool.
195
Thread.currentThread().interrupted();
196         }
197         getLogger().debug("Watchdog " + Thread.currentThread().getName() + " is exiting run().");
198     }
199
200     /**
201      * @see org.apache.avalon.framework.activity.Disposable#dispose()
202      */

203     public void dispose() {
204         synchronized(this) {
205             isChecking = false;
206             if (watchdogThread != null) {
207                 getLogger().debug("Calling disposeWatchdog() " + watchdogThread.getName());
208             } else {
209                 getLogger().debug("Calling disposeWatchdog() for inactive watchdog");
210             }
211             if (watchdogThread != null) {
212                 watchdogThread = null;
213                 notifyAll();
214             }
215             if (triggerTarget instanceof Disposable) {
216                 ((Disposable)triggerTarget).dispose();
217             }
218             triggerTarget = null;
219         }
220     }
221 }
222
Popular Tags