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