1
2
3
4
5
6
7
8
9
10
11 package org.mule.util.monitor;
12
13 import org.mule.api.lifecycle.Disposable;
14 import org.mule.config.i18n.CoreMessages;
15 import org.mule.util.concurrent.DaemonThreadFactory;
16
17 import java.util.Iterator;
18 import java.util.Map;
19
20 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
21 import edu.emory.mathcs.backport.java.util.concurrent.ScheduledThreadPoolExecutor;
22 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27
28
29
30
31
32 public class ExpiryMonitor implements Runnable, Disposable
33 {
34
35
36
37 protected static final Log logger = LogFactory.getLog(ExpiryMonitor.class);
38
39 protected ScheduledThreadPoolExecutor scheduler;
40
41 private Map monitors;
42
43 private int monitorFrequency;
44
45 private String name;
46
47 private ClassLoader contextClassLoader;
48
49 public ExpiryMonitor(String name)
50 {
51 this(name, 1000);
52 }
53
54 public ExpiryMonitor(String name, int monitorFrequency)
55 {
56 this.name = name;
57 this.monitorFrequency = monitorFrequency;
58 init();
59 }
60
61 public ExpiryMonitor(String name, int monitorFrequency, ClassLoader contextClassLoader)
62 {
63 this.name = name;
64 this.monitorFrequency = monitorFrequency;
65 this.contextClassLoader = contextClassLoader;
66 init();
67 }
68
69 public ExpiryMonitor(String name, int monitorFrequency, ScheduledThreadPoolExecutor scheduler)
70 {
71 this.name = name;
72 this.monitorFrequency = monitorFrequency;
73 this.scheduler = scheduler;
74 init();
75 }
76
77 protected void init()
78 {
79 if (monitorFrequency <= 0)
80 {
81 throw new IllegalArgumentException(CoreMessages.propertyHasInvalidValue("monitorFrequency",
82 new Integer(monitorFrequency)).toString());
83 }
84 monitors = new ConcurrentHashMap();
85 if (scheduler == null)
86 {
87 this.scheduler = new ScheduledThreadPoolExecutor(1);
88 scheduler.setThreadFactory(new DaemonThreadFactory(name + "-Monitor", contextClassLoader));
89 scheduler.scheduleWithFixedDelay(this, 0, monitorFrequency,
90 TimeUnit.MILLISECONDS);
91 }
92 }
93
94
95
96
97
98
99
100
101
102 public void addExpirable(long value, TimeUnit timeUnit, Expirable expirable)
103 {
104 if (isRegistered(expirable))
105 {
106 resetExpirable(expirable);
107 }
108 else
109 {
110 if (logger.isDebugEnabled())
111 {
112 logger.debug("Adding new expirable: " + expirable);
113 }
114 monitors.put(expirable, new ExpirableHolder(timeUnit.toNanos(value), expirable));
115 }
116 }
117
118 public boolean isRegistered(Expirable expirable)
119 {
120 return (monitors.get(expirable) != null);
121 }
122
123 public void removeExpirable(Expirable expirable)
124 {
125 if (logger.isDebugEnabled())
126 {
127 logger.debug("Removing expirable: " + expirable);
128 }
129 monitors.remove(expirable);
130 }
131
132 public void resetExpirable(Expirable expirable)
133 {
134 ExpirableHolder eh = (ExpirableHolder) monitors.get(expirable);
135 if (eh != null)
136 {
137 eh.reset();
138 if (logger.isDebugEnabled())
139 {
140 logger.debug("Reset expirable: " + expirable);
141 }
142 }
143 }
144
145
146
147
148 public void run()
149 {
150 ExpirableHolder holder;
151 for (Iterator iterator = monitors.values().iterator(); iterator.hasNext();)
152 {
153 holder = (ExpirableHolder) iterator.next();
154 if (holder.isExpired())
155 {
156 removeExpirable(holder.getExpirable());
157 holder.getExpirable().expired();
158 }
159 }
160 }
161
162 public void dispose()
163 {
164 logger.info("disposing monitor");
165 scheduler.shutdown();
166 ExpirableHolder holder;
167 for (Iterator iterator = monitors.values().iterator(); iterator.hasNext();)
168 {
169 holder = (ExpirableHolder) iterator.next();
170 removeExpirable(holder.getExpirable());
171 try
172 {
173 holder.getExpirable().expired();
174 }
175 catch (Exception e)
176 {
177
178 logger.debug(e.getMessage());
179 }
180 }
181 }
182
183 private static class ExpirableHolder
184 {
185
186 private long nanoseconds;
187 private Expirable expirable;
188 private long created;
189
190 public ExpirableHolder(long nanoseconds, Expirable expirable)
191 {
192 this.nanoseconds = nanoseconds;
193 this.expirable = expirable;
194 created = System.nanoTime();
195 }
196
197 public long getNanoSeconds()
198 {
199 return nanoseconds;
200 }
201
202 public Expirable getExpirable()
203 {
204 return expirable;
205 }
206
207 public boolean isExpired()
208 {
209 return (System.nanoTime() - nanoseconds) > created;
210 }
211
212 public void reset()
213 {
214 created = System.nanoTime();
215 }
216 }
217 }