1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.mule.work;
29
30 import org.mule.api.MuleContext;
31 import org.mule.api.MuleException;
32 import org.mule.api.config.MuleConfiguration;
33 import org.mule.api.config.ThreadingProfile;
34 import org.mule.api.context.MuleContextAware;
35 import org.mule.api.context.WorkManager;
36 import org.mule.api.work.WorkExecutor;
37
38 import java.text.MessageFormat;
39 import java.util.List;
40 import java.util.concurrent.Executor;
41 import java.util.concurrent.ExecutorService;
42 import java.util.concurrent.TimeUnit;
43
44 import javax.resource.spi.XATerminator;
45 import javax.resource.spi.work.ExecutionContext;
46 import javax.resource.spi.work.Work;
47 import javax.resource.spi.work.WorkCompletedException;
48 import javax.resource.spi.work.WorkException;
49 import javax.resource.spi.work.WorkListener;
50
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54
55
56
57
58
59 public class MuleWorkManager implements WorkManager, MuleContextAware
60 {
61
62
63
64 protected static final Log logger = LogFactory.getLog(MuleWorkManager.class);
65
66
67
68
69
70
71
72 private static final long FORCEFUL_SHUTDOWN_TIMEOUT = 5000L;
73
74
75
76
77 private final ThreadingProfile threadingProfile;
78
79
80
81
82
83 private volatile ExecutorService workExecutorService;
84 private final String name;
85 private int gracefulShutdownTimeout;
86 private MuleContext muleContext;
87
88
89
90
91 private final WorkExecutor scheduleWorkExecutor = new ScheduleWorkExecutor();
92 private final WorkExecutor startWorkExecutor = new StartWorkExecutor();
93 private final WorkExecutor syncWorkExecutor = new SyncWorkExecutor();
94
95 public MuleWorkManager(ThreadingProfile profile, String name, int shutdownTimeout)
96 {
97 super();
98
99 if (name == null)
100 {
101 name = "WorkManager#" + hashCode();
102 }
103
104 this.threadingProfile = profile;
105 this.name = name;
106 gracefulShutdownTimeout = shutdownTimeout;
107 }
108
109 public synchronized void start() throws MuleException
110 {
111 gracefulShutdownTimeout = getMuleContext().getConfiguration().getShutdownTimeout();
112
113 if (workExecutorService == null)
114 {
115 workExecutorService = threadingProfile.createPool(name);
116 }
117 }
118
119 public synchronized void dispose()
120 {
121 if (workExecutorService != null)
122 {
123
124 workExecutorService.shutdown();
125 try
126 {
127
128 if (!workExecutorService.awaitTermination(gracefulShutdownTimeout, TimeUnit.MILLISECONDS))
129 {
130
131
132 List outstanding = workExecutorService.shutdownNow();
133
134 if (!workExecutorService.awaitTermination(FORCEFUL_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS))
135 {
136 logger.warn(MessageFormat.format(
137 "Pool {0} did not terminate in time; {1} work items were cancelled.", name,
138 outstanding.isEmpty() ? "No" : Integer.toString(outstanding.size())));
139 }
140 else
141 {
142 if (!outstanding.isEmpty())
143 {
144 logger.warn(MessageFormat.format(
145 "Pool {0} terminated; {1} work items were cancelled.", name,
146 Integer.toString(outstanding.size())));
147 }
148 }
149 }
150 }
151 catch (InterruptedException ie)
152 {
153
154 workExecutorService.shutdownNow();
155
156 Thread.currentThread().interrupt();
157 }
158 finally
159 {
160 workExecutorService = null;
161 }
162 }
163 }
164
165
166
167 public XATerminator getXATerminator()
168 {
169 return null;
170 }
171
172 public void doWork(Work work) throws WorkException
173 {
174 executeWork(new WorkerContext(work), syncWorkExecutor);
175 }
176
177 public void doWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)
178 throws WorkException
179 {
180 WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
181 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
182 executeWork(workWrapper, syncWorkExecutor);
183 }
184
185 public long startWork(Work work) throws WorkException
186 {
187 WorkerContext workWrapper = new WorkerContext(work);
188 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
189 executeWork(workWrapper, startWorkExecutor);
190 return System.currentTimeMillis() - workWrapper.getAcceptedTime();
191 }
192
193 public long startWork(Work work,
194 long startTimeout,
195 ExecutionContext execContext,
196 WorkListener workListener) throws WorkException
197 {
198 WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
199 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
200 executeWork(workWrapper, startWorkExecutor);
201 return System.currentTimeMillis() - workWrapper.getAcceptedTime();
202 }
203
204 public void scheduleWork(Work work) throws WorkException
205 {
206 WorkerContext workWrapper = new WorkerContext(work);
207 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
208 executeWork(workWrapper, scheduleWorkExecutor);
209 }
210
211 public void scheduleWork(Work work,
212 long startTimeout,
213 ExecutionContext execContext,
214 WorkListener workListener) throws WorkException
215 {
216 WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
217 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
218 executeWork(workWrapper, scheduleWorkExecutor);
219 }
220
221
222
223
224 public void execute(Runnable work)
225 {
226 if (!isStarted())
227 {
228 throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
229 }
230 workExecutorService.execute(work);
231 }
232
233
234
235
236
237
238
239
240 private void executeWork(WorkerContext work, WorkExecutor workExecutor) throws WorkException
241 {
242 if (!isStarted())
243 {
244 throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
245 }
246
247 try
248 {
249 work.workAccepted(this);
250 workExecutor.doExecute(work, workExecutorService);
251 WorkException exception = work.getWorkException();
252 if (null != exception)
253 {
254 throw exception;
255 }
256 }
257 catch (InterruptedException e)
258 {
259 WorkCompletedException wcj = new WorkCompletedException("The execution has been interrupted for WorkManager: " + name, e);
260 wcj.setErrorCode(WorkException.INTERNAL);
261 throw wcj;
262 }
263 }
264
265 public boolean isStarted()
266 {
267 return (workExecutorService != null && !workExecutorService.isShutdown());
268 }
269
270 public MuleContext getMuleContext()
271 {
272 return muleContext;
273 }
274
275 public void setMuleContext(MuleContext muleContext)
276 {
277 this.muleContext = muleContext;
278 if (this.threadingProfile != null && muleContext != null)
279 {
280 threadingProfile.setMuleContext(muleContext);
281 }
282 }
283 }