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