KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > connectors > work > WorkCoordinator


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.connectors.work;
25
26 import com.sun.corba.ee.spi.orbutil.threadpool.*;
27 import com.sun.enterprise.J2EETransactionManager;
28 import com.sun.enterprise.distributedtx.J2EETransactionManagerOpt;
29 import com.sun.enterprise.Switch;
30 import com.sun.logging.LogDomains;
31 import javax.resource.spi.work.*;
32 import java.util.logging.*;
33
34 /**
35  * WorkCoordinator : Coordinates one work's execution. Handles all
36  * exception conditions and does JTS coordination.
37  *
38  * @author Binod P.G
39  */

40 public class WorkCoordinator {
41
42     static int WAIT_UNTIL_START = 1;
43     static int WAIT_UNTIL_FINISH = 2;
44     static int NO_WAIT = 3;
45
46     static int CREATED = 1;
47     static int STARTED = 2;
48     static int COMPLETED = 3;
49     static int TIMEDOUT = 4;
50
51     private int waitMode;
52     private volatile int state=CREATED;
53
54     private boolean workIsBad = false;
55
56     private javax.resource.spi.work.Work JavaDoc work;
57     private long timeout;
58     private long startTime;
59     private ExecutionContext ec;
60     private WorkQueue queue;
61     private WorkListener listener;
62     private WorkException exception;
63     private Object JavaDoc lock;
64     private static int seed;
65     private int id;
66
67     private static Logger logger =
68         LogDomains.getLogger(LogDomains.RSR_LOGGER);
69     
70     /**
71      * <code>workStats</code> is responsible for holding all monitorable
72      * properties of a work-manager. Workstats would be null, if monitoring is
73      * *not* enabled.
74      */

75     private WorkStats workStats = null;
76
77     /**
78      * Constructs a coordinator
79      * @param work A work object as submitted by the resource adapter
80      * @param timeout timeout for the work instance
81      * @param ec ExecutionContext object.
82      * @param queue WorkQueue of the threadpool, to which the work
83      * will be submitted
84      * @param listener WorkListener object from the resource adapter.
85      */

86     public WorkCoordinator(javax.resource.spi.work.Work JavaDoc work,
87                            long timeout,
88                            ExecutionContext ec,
89                            WorkQueue queue,
90                            WorkListener listener, WorkStats workStats) {
91                           
92         this.work = work;
93         this.timeout = timeout;
94         this.ec = ec;
95         this.queue = queue;
96         this.listener = listener;
97         this.id = ++seed;
98         this.lock = new Object JavaDoc();
99         this.workStats = workStats;
100     }
101  
102     /**
103      * Submits the work to the queue and generates a work accepted event.
104      */

105     public void submitWork(int waitMode) {
106         this.waitMode = waitMode;
107         this.startTime = System.currentTimeMillis();
108         if (listener != null) {
109             listener.workAccepted(
110                 new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));
111         }
112         queue.addWork( new OneWork(work, this));
113         if(workStats != null) {
114             workStats.submittedWorkCount++;
115             workStats.incrementWaitQueueLength();
116         }
117         
118     }
119
120     /**
121      * Pre-invoke operation. This does the following
122      * <pre>
123      * 1. Notifies the <code> WorkManager.startWork </code> method.
124      * 2. Checks whether the wok has already been timed out.
125      * 3. Recreates the transaction with JTS.
126      * </pre>
127      */

128     public void preInvoke() {
129        
130         // If the work is just scheduled, check whether it has timed out or not.
131
if (waitMode == NO_WAIT && timeout > -1) {
132            long elapsedTime = System.currentTimeMillis() - startTime ;
133            
134            if(workStats != null) {
135                workStats.setWorkWaitTime(elapsedTime);
136            }
137            
138            if (elapsedTime > timeout) {
139                workTimedOut();
140            }
141         }
142
143         // Change the status to started.
144
setState(STARTED);
145
146         if (waitMode == WAIT_UNTIL_START) {
147             unLock();
148         }
149
150         // If the work is timed out then return.
151
if (!proceed()) {
152             if (workStats != null) {
153                 workStats.decrementWaitQueueLength();
154             }
155             return;
156         }
157
158         // All set to do start the work. So send the event.
159
if (listener != null) {
160             listener.workStarted(
161                 new WorkEvent(this, WorkEvent.WORK_STARTED, work, null));
162         }
163
164
165         try {
166             J2EETransactionManager tm = Switch.getSwitch().getTransactionManager();
167             if (ec != null && ec.getXid() != null) {
168                 tm.recreate(ec.getXid(), ec.getTransactionTimeout());
169             }
170         } catch(WorkException we) {
171             this.exception = we;
172         } catch(Exception JavaDoc e) {
173             setException(e);
174         }
175
176         if(workStats != null) {
177             workStats.setActiveWorkCount(workStats.currentActiveWorkCount++);
178             workStats.decrementWaitQueueLength();
179         }
180         
181     }
182
183     /**
184      * Post-invoke operation. This does the following after the work is executed.
185      * <pre>
186      * 1. Releases the transaction with JTS.
187      * 2. Generates work completed event.
188      * 3. Clear the thread context.
189      * </pre>
190      */

191     public void postInvoke() {
192         boolean txImported = (ec != null && ec.getXid() != null);
193         try {
194             J2EETransactionManager tm = Switch.getSwitch().getTransactionManager();
195             if (txImported) {
196                 tm.release(ec.getXid());
197             }
198         } catch (WorkException ex) {
199             setException(ex);
200         } finally {
201             try {
202                 if(workStats != null) {
203                     workStats.setActiveWorkCount
204                                 (workStats.currentActiveWorkCount--);
205                     workStats.completedWorkCount++;
206                 }
207                 
208                 //If exception is not null, the work has already been rejected.
209
if (listener != null) {
210                     if ((!isTimedOut()) && (exception == null)) {
211                         listener.workCompleted(
212                             new WorkEvent(this, WorkEvent.WORK_COMPLETED, work,
213                                             getException()));
214                     }
215                 }
216
217                 //Also release the TX from the record of TX Optimizer
218
if (txImported) {
219                     J2EETransactionManager tm =
220                     Switch.getSwitch().getTransactionManager();
221                     if (tm instanceof J2EETransactionManagerOpt) {
222                         ((J2EETransactionManagerOpt) tm).clearThreadTx();
223                     }
224                 }
225             } catch(Exception JavaDoc e) {
226             logger.log(Level.WARNING, e.getMessage());
227             }
228         }
229
230         setState(COMPLETED);
231         if (waitMode == WAIT_UNTIL_FINISH) {
232             unLock();
233         }
234     }
235     
236     /**
237      * Times out the thread
238      */

239     private void workTimedOut() {
240         setState(TIMEDOUT);
241         exception = new WorkRejectedException();
242         exception.setErrorCode(WorkException.START_TIMED_OUT);
243         if (listener != null) {
244             listener.workRejected(
245                 new WorkEvent(this, WorkEvent.WORK_REJECTED, work, exception));
246         }
247         if(workStats != null) {
248             workStats.rejectedWorkCount++;
249             workStats.setActiveWorkCount(workStats.currentActiveWorkCount--);
250         }
251     }
252
253     /**
254      * Checks the work is good to proceed with further processing.
255      *
256      * @return true if the work is good and false if it is bad.
257      */

258     public boolean proceed() {
259         return !isTimedOut() && exception == null;
260     }
261
262     private boolean isTimedOut() {
263         return getState() == TIMEDOUT;
264     }
265
266     /**
267      * Retrieves the exception created during the work's execution.
268      *
269      * @return a <code>WorkException</code> object.
270      */

271     public WorkException getException() {
272         return exception;
273     }
274
275     /**
276      * Accepts an exception object and converts to a
277      * <code>WorkException</code> object.
278      *
279      * @param e Throwable object.
280      */

281     public void setException(Throwable JavaDoc e) {
282         if (getState() < STARTED ) {
283             if (e instanceof WorkRejectedException) {
284                 exception = (WorkException) e;
285             } else if (e instanceof WorkException) {
286                 WorkException we = (WorkException) e;
287                 exception = new WorkRejectedException(we);
288                 exception.setErrorCode(we.getErrorCode());
289             } else {
290                 exception = new WorkRejectedException(e);
291                 exception.setErrorCode(WorkException.UNDEFINED);
292             }
293         } else {
294             if (e instanceof WorkCompletedException) {
295                 exception = (WorkException) e;
296             } else if (e instanceof WorkException) {
297                 WorkException we = (WorkException) e;
298                 exception = new WorkCompletedException(we);
299                 exception.setErrorCode(we.getErrorCode());
300             } else {
301                 exception = new WorkCompletedException(e);
302                 exception.setErrorCode(WorkException.UNDEFINED);
303             }
304         }
305     }
306
307     /**
308      * Lock the thread upto the end of execution or start of work
309      * execution.
310      *
311      * @param waitMode either WAIT_UNTIL_START or WAIT_UNTIL_FINISH
312      */

313     public void lock() {
314
315         if (!lockRequired()) {
316             return;
317         }
318
319         try {
320             synchronized (lock) {
321                 if (checkStateBeforeLocking()) {
322                         if (timeout != -1) {
323                             lock.wait(timeout);
324                         } else {
325                             lock.wait();
326                         }
327                 }
328             }
329
330             if (getState() < STARTED) {
331                 workTimedOut();
332             }
333             if (lockRequired()) {
334                 synchronized (lock) {
335                    if (checkStateBeforeLocking()) {
336                            lock.wait();
337                     }
338                 }
339             }
340             
341         } catch(Exception JavaDoc e) {
342             setException(e);
343         }
344     }
345
346     /**
347      * Unlocks the thread.
348      */

349     private void unLock() {
350         try {
351             synchronized (lock) {
352                 lock.notify();
353             }
354         } catch(Exception JavaDoc e) {
355             setException(e);
356         }
357     }
358
359     /**
360      * Returns the string representation of WorkCoordinator.
361      *
362      * @return Unique identification concatenated by work object.
363      */

364     public String JavaDoc toString() {
365         return id + ":" + work;
366     }
367
368     /**
369      * Sets the state of the work coordinator object
370      *
371      * @param state CREATED or Either STARTED or COMPLETED or TIMEDOUT
372      */

373     public synchronized void setState(int state) {
374         this.state = state;
375     }
376
377     /**
378      * Retrieves the state of the work coordinator object.
379      *
380      * @return Integer represnting the state.
381      */

382     public synchronized int getState() {
383         return state;
384     }
385
386     private boolean lockRequired() {
387         if (!proceed()) {
388             return false;
389         }
390         if (waitMode == NO_WAIT) {
391             return false;
392         }
393         if (waitMode == WAIT_UNTIL_FINISH) {
394             return getState() < COMPLETED;
395         }
396     if (waitMode == WAIT_UNTIL_START) {
397             return getState() < STARTED;
398         }
399         return false;
400     }
401
402     /**
403      * It is possible that state is modified just before
404      * the lock is obtained. So check it again.
405      * Access the variable directly to avoid nested locking.
406      */

407     private boolean checkStateBeforeLocking() {
408         if (waitMode == WAIT_UNTIL_FINISH) {
409             return state < COMPLETED;
410         }
411     if (waitMode == WAIT_UNTIL_START) {
412             return state < STARTED;
413         }
414         return false;
415     }
416
417 }
418
Popular Tags