1 /*
2 * Copyright 1999-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.tomcat.util.threads;
18
19
20 /**
21 * The reaper is a background thread with which ticks every minute
22 * and calls registered objects to allow reaping of old session
23 * data.
24 *
25 * @author James Duncan Davidson [duncan@eng.sun.com]
26 * @author Costin Manolache
27 */
28 public class Reaper extends Thread {
29
30
31 private static org.apache.commons.logging.Log log=
32 org.apache.commons.logging.LogFactory.getLog(Reaper.class );
33
34 private boolean daemon = false;
35
36 public Reaper() {
37 if (daemon)
38 this.setDaemon(true);
39 this.setName("TomcatReaper");
40 }
41
42 public Reaper(String name) {
43 if (daemon)
44 this.setDaemon(true);
45 this.setName(name);
46 }
47
48 private long interval = 1000 * 60; //ms
49
50 // XXX TODO Allow per/callback interval, find next, etc
51 // Right now the "interval" is used for all callbacks
52 // and it represent a sleep between runs.
53
54 ThreadPoolRunnable cbacks[] = new ThreadPoolRunnable[30]; // XXX max
55 Object tdata[][] = new Object[30][]; // XXX max
56 int count = 0;
57
58 /** Adding and removing callbacks is synchronized
59 */
60 Object lock = new Object();
61 static boolean running = true;
62
63 // XXX Should be called 'interval' not defaultInterval
64
65 public void setDefaultInterval(long t) {
66 interval = t;
67 }
68
69 public long getDefaultIntervale() {
70 return interval;
71 }
72
73 public int addCallback(ThreadPoolRunnable c, int interval) {
74 synchronized (lock) {
75 cbacks[count] = c;
76 count++;
77 return count - 1;
78 }
79 }
80
81 public void removeCallback(int idx) {
82 synchronized (lock) {
83 count--;
84 cbacks[idx] = cbacks[count];
85 cbacks[count] = null;
86 }
87 }
88
89 public void startReaper() {
90 running = true;
91 this.start();
92 }
93
94 public synchronized void stopReaper() {
95 running = false;
96 if (log.isDebugEnabled())
97 log.debug("Stop reaper ");
98 this.interrupt(); // notify() doesn't stop sleep
99 }
100
101 public void run() {
102 while (running) {
103 if (!running)
104 break;
105 try {
106 Thread.sleep(interval);
107 } catch (InterruptedException ie) {
108 // sometimes will happen
109 }
110
111 if (!running)
112 break;
113 for (int i = 0; i < count; i++) {
114 ThreadPoolRunnable callB = cbacks[i];
115 // it may be null if a callback is removed.
116 // I think the code is correct
117 if (callB != null) {
118 callB.runIt(tdata[i]);
119 }
120 if (!running)
121 break;
122 }
123 }
124 }
125 }