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