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