KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > JEntitySwitchCS


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: JEntitySwitchCS.java,v 1.25 2005/04/28 16:52:59 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas_ejb.container;
27
28 import javax.ejb.EJBException JavaDoc;
29 import javax.ejb.NoSuchObjectLocalException JavaDoc;
30 import javax.ejb.TransactionRolledbackLocalException JavaDoc;
31 import javax.transaction.Status JavaDoc;
32 import javax.transaction.SystemException JavaDoc;
33 import javax.transaction.Transaction JavaDoc;
34
35 import org.objectweb.jonas_ejb.deployment.api.EntityDesc;
36
37 import org.objectweb.util.monolog.api.BasicLevel;
38
39 /**
40  * Container Serialized lock-policy.
41  * Transaction Isolation managed by the container.
42  * All transactions are serialized.
43  * @author Philippe Durieux
44  */

45 public class JEntitySwitchCS extends JEntitySwitch {
46
47     /**
48      * unique EntityContext
49      */

50     protected JEntityContext itContext = null;
51
52     // max time to wait when in a transaction, before checking if
53
// transaction has been set rollback only (deadlock detection)
54
protected static int maxtime = 3000; // 3 sec.
55

56     /**
57      * empty constructor. Object is initialized via init() because it is
58      * implemented differently according to jorm mappers.
59      */

60     public JEntitySwitchCS() {
61         lockpolicy = EntityDesc.LOCK_CONTAINER_SERIALIZED;
62         txUpdates = false; // TODO : can set this in DD.
63
}
64
65     protected void initpolicy(JEntityFactory bf) {
66         lazyregister = false;
67     }
68
69     protected JEntityContext getContext4Tx(Transaction JavaDoc tx) {
70         return itContext;
71     }
72
73     protected void setContext4Tx(Transaction JavaDoc tx, JEntityContext ctx) {
74         if (TraceEjb.isDebugContext()) {
75             TraceEjb.context.log(BasicLevel.DEBUG, "set itContext=" + ctx);
76         }
77         itContext = ctx;
78     }
79
80     protected void removeContext4Tx(Transaction JavaDoc tx) {
81         if (TraceEjb.isDebugContext()) {
82             TraceEjb.context.log(BasicLevel.DEBUG, "unset itContext=" + itContext);
83         }
84         itContext = null;
85     }
86
87     public void waitmyturn(Transaction JavaDoc tx) {
88         // Synchronization.
89
if (tx == null) {
90             // Must wait in case of TX
91
while (runningtx != null) {
92                 if (TraceEjb.isDebugSynchro()) {
93                     TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IH: WAIT end IT");
94                 }
95                 waiters++;
96                 try {
97                     wait(maxtime);
98                     if (TraceEjb.isDebugSynchro())
99                             TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IH: NOTIFIED");
100                 } catch (InterruptedException JavaDoc e) {
101                     if (TraceEjb.isDebugSynchro())
102                             TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IH: INTERRUPTED");
103                 } catch (Exception JavaDoc e) {
104                     throw new EJBException JavaDoc("JEntitySwitch synchronization pb", e);
105                 } finally {
106                     waiters--;
107                 }
108             }
109         } else {
110
111             // Must wait in case of TX or if instance has been modified outside
112
// transaction.
113
// Don't wait transactions if 1 instance per transaction.
114
int waitcount = 0;
115             while (inDirtyList || (runningtx != null && !tx.equals(runningtx))) {
116                 // instance is dirty : must write it before working on it again.
117
// this is mandatory to be able to retrieve a good state in case
118
// of rollback.
119
if (inDirtyList) {
120                     if (TraceEjb.isDebugSynchro())
121                             TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: WAIT end IH");
122                     // Cannot passivate here, because must be done outside tx
123
// context
124
bf.synchronizeEntities();
125                 } else {
126                     if (TraceEjb.isDebugSynchro())
127                             TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: WAIT end IT");
128                     // deadlock detection
129
blockedtx = tx;
130                     if (waitcount++ > 1 && bf.isBlocked(runningtx) && bf.isBlocking(tx)) {
131                         try {
132                             tx.setRollbackOnly();
133                         } catch (SystemException JavaDoc e) {
134                             TraceEjb.logger.log(BasicLevel.ERROR, ident
135                                     + "getICtx IT: unexpected exception setting rollbackonly");
136                         }
137                         TraceEjb.logger.log(BasicLevel.WARN, ident + "getICtx IT: transaction rolled back");
138                         throw new TransactionRolledbackLocalException JavaDoc("possible deadlock");
139                     }
140                 }
141                 waiters++;
142                 try {
143                     wait(maxtime);
144                     if (TraceEjb.isDebugSynchro())
145                             TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: NOTIFIED");
146                 } catch (InterruptedException JavaDoc e) {
147                     if (TraceEjb.isDebugSynchro())
148                             TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: INTERRUPTED");
149                 } catch (Exception JavaDoc e) {
150                     throw new EJBException JavaDoc("JEntitySwitch synchronization pb", e);
151                 } finally {
152                     waiters--;
153                     blockedtx = null;
154                 }
155                 // If transaction has been rolledback or set rollback only, give
156
// up.
157
int status = Status.STATUS_ROLLEDBACK;
158                 try {
159                     status = tx.getStatus();
160                 } catch (SystemException JavaDoc e) {
161                     TraceEjb.logger.log(BasicLevel.ERROR, ident
162                             + "getICtx IT: unexpected exception getting transaction status");
163                 }
164                 switch (status) {
165                 case Status.STATUS_MARKED_ROLLBACK:
166                 case Status.STATUS_ROLLEDBACK:
167                 case Status.STATUS_ROLLING_BACK:
168                     TraceEjb.logger.log(BasicLevel.WARN, ident + "getICtx IT: transaction rolled back");
169                     throw new TransactionRolledbackLocalException JavaDoc("rollback occured while waiting");
170                 }
171             }
172         }
173
174     }
175
176     /**
177      * try to passivate IH (called from swapper)
178      * @param passivation false if only store bean state.
179      * @return false if instance still in memory (busy for example)
180      */

181     public synchronized boolean passivateIH(boolean passivation) {
182
183         JEntityContext jec = getContext4Tx(null);
184
185         // If already passivated, look if we can destroy the objects
186
if (jec == null) {
187             if (inactivityTimeout > 0) {
188                 long diff = System.currentTimeMillis() - timestamp;
189                 if (diff > inactivityTimeout) {
190                     if (TraceEjb.isDebugContext()) {
191                         TraceEjb.context.log(BasicLevel.DEBUG, ident + timestamp);
192                     }
193                     discardContext(null, true, false);
194                 }
195             }
196             return true;
197         }
198
199         // If the instance is busy, don't touch it.
200
if (countIH > 0 && !txUpdates) {
201             // will be stored later, when released by last thread (countIH = 0)
202
// return true to remove from the dirty list, since it will be
203
// written anyway.
204
if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " used off TX");
205             mustStore = true;
206             return true;
207         }
208         if (runningtx != null) {
209             if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " used in TX");
210             return false;
211         }
212
213         if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident);
214
215         if (jec.isMarkedRemoved()) {
216             discardContext(null, true, true);
217             return true;
218         }
219
220         // Store the instance state
221
// -> only if instance not discarded, and not readonly.
222
if (!todiscard && !txUpdates) {
223             try {
224                 jec.storeIfModified();
225             } catch (Exception JavaDoc e) {
226                 TraceEjb.logger.log(BasicLevel.ERROR, ident, "error while storing bean state:", e);
227             }
228             mustStore = false;
229             // don't set dirty false here, will be done in endIH.
230
// this prevent duplicates in dirty list.
231
}
232
233         // passivate this instance if required.
234
if (passivation) {
235             if (TraceEjb.isDebugContext()) TraceEjb.context.log(BasicLevel.DEBUG, "passivated: " + jec);
236             jec.passivate();
237             bf.releaseJContext(jec);
238             removeContext4Tx(null);
239             // passivation done, set the timestamp
240
timestamp = System.currentTimeMillis();
241             if (TraceEjb.isDebugContext()) {
242                 TraceEjb.context.log(BasicLevel.DEBUG, ident + timestamp);
243             }
244             if (waiters > 0) {
245                 if (TraceEjb.isDebugSynchro()) {
246                     TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " notify");
247                 }
248                 notifyAll();
249             }
250         }
251         return true;
252     }
253
254     /**
255      * Instance is ready to use for new transaction.
256      */

257     public synchronized void endIH() {
258         inDirtyList = false;
259         if (getContext4Tx(null) == null) {
260             if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " discarded!");
261             return;
262         }
263         // If the instance is busy, don't touch it.
264
// If no context mapped, nothing to do
265
if (TraceEjb.isDebugSynchro()) {
266             if (countIH == 0) {
267                 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " ready again");
268             } else {
269                 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " busy!");
270             }
271         }
272         if (waiters > 0) {
273             if (TraceEjb.isDebugSynchro()) {
274                 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " notify");
275             }
276             notifyAll();
277         }
278     }
279
280     public synchronized void notifyWriting(Transaction JavaDoc tx, JEntityContext bctx) {
281         return; // NEVER
282
}
283
284     /**
285      * @return State of this instance. State values are 0=in-tx, 1=out-tx, 2=idle,
286      * 3=passive, 4=removed. we don't synchronize this method to avoid
287      * jadmin blocks
288      */

289     public int getState() {
290         if (itContext != null) {
291             if (itContext.isMarkedRemoved()) {
292                 return 4;
293             } else {
294                 if (runningtx != null) {
295                     return 0;
296                 } else {
297                     if (inDirtyList) {
298                         return 1;
299                     } else {
300                         return 2;
301                     }
302                 }
303             }
304         }
305         return 3;
306     }
307
308 }
309
Popular Tags