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