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