00001
00026 package org.objectweb.jonas_ejb.container;
00027
00028 import javax.ejb.EJBException;
00029 import javax.ejb.NoSuchObjectLocalException;
00030 import javax.ejb.TransactionRolledbackLocalException;
00031 import javax.transaction.Status;
00032 import javax.transaction.SystemException;
00033 import javax.transaction.Transaction;
00034
00035 import org.objectweb.jonas_ejb.deployment.api.EntityDesc;
00036
00037 import org.objectweb.util.monolog.api.BasicLevel;
00038
00045 public class JEntitySwitchCS extends JEntitySwitch {
00046
00050 protected JEntityContext itContext = null;
00051
00052
00053
00054 protected static int maxtime = 3000;
00055
00060 public JEntitySwitchCS() {
00061 lockpolicy = EntityDesc.LOCK_CONTAINER_SERIALIZED;
00062 txUpdates = false;
00063 }
00064
00065 protected void initpolicy(JEntityFactory bf) {
00066 lazyregister = false;
00067 }
00068
00069 protected JEntityContext getContext4Tx(Transaction tx) {
00070 return itContext;
00071 }
00072
00073 protected void setContext4Tx(Transaction tx, JEntityContext ctx) {
00074 if (TraceEjb.isDebugContext()) {
00075 TraceEjb.context.log(BasicLevel.DEBUG, "set itContext=" + ctx);
00076 }
00077 itContext = ctx;
00078 }
00079
00080 protected void removeContext4Tx(Transaction tx) {
00081 if (TraceEjb.isDebugContext()) {
00082 TraceEjb.context.log(BasicLevel.DEBUG, "unset itContext=" + itContext);
00083 }
00084 itContext = null;
00085 }
00086
00087 public void waitmyturn(Transaction tx) {
00088
00089 if (tx == null) {
00090
00091 while (runningtx != null) {
00092 if (TraceEjb.isDebugSynchro()) {
00093 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IH: WAIT end IT");
00094 }
00095 waiters++;
00096 try {
00097 wait(maxtime);
00098 if (TraceEjb.isDebugSynchro())
00099 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IH: NOTIFIED");
00100 } catch (InterruptedException e) {
00101 if (TraceEjb.isDebugSynchro())
00102 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IH: INTERRUPTED");
00103 } catch (Exception e) {
00104 throw new EJBException("JEntitySwitch synchronization pb", e);
00105 } finally {
00106 waiters--;
00107 }
00108 }
00109 } else {
00110
00111
00112
00113
00114 int waitcount = 0;
00115 while (inDirtyList || (runningtx != null && !tx.equals(runningtx))) {
00116
00117
00118
00119 if (inDirtyList) {
00120 if (TraceEjb.isDebugSynchro())
00121 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: WAIT end IH");
00122
00123
00124 bf.synchronizeEntities();
00125 } else {
00126 if (TraceEjb.isDebugSynchro())
00127 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: WAIT end IT");
00128
00129 blockedtx = tx;
00130 if (waitcount++ > 1 && bf.isBlocked(runningtx) && bf.isBlocking(tx)) {
00131 try {
00132 tx.setRollbackOnly();
00133 } catch (SystemException e) {
00134 TraceEjb.logger.log(BasicLevel.ERROR, ident
00135 + "getICtx IT: unexpected exception setting rollbackonly");
00136 }
00137 TraceEjb.logger.log(BasicLevel.WARN, ident + "getICtx IT: transaction rolled back");
00138 throw new TransactionRolledbackLocalException("possible deadlock");
00139 }
00140 }
00141 waiters++;
00142 try {
00143 wait(maxtime);
00144 if (TraceEjb.isDebugSynchro())
00145 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: NOTIFIED");
00146 } catch (InterruptedException e) {
00147 if (TraceEjb.isDebugSynchro())
00148 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + "mapICtx IT: INTERRUPTED");
00149 } catch (Exception e) {
00150 throw new EJBException("JEntitySwitch synchronization pb", e);
00151 } finally {
00152 waiters--;
00153 blockedtx = null;
00154 }
00155
00156
00157 int status = Status.STATUS_ROLLEDBACK;
00158 try {
00159 status = tx.getStatus();
00160 } catch (SystemException e) {
00161 TraceEjb.logger.log(BasicLevel.ERROR, ident
00162 + "getICtx IT: unexpected exception getting transaction status");
00163 }
00164 switch (status) {
00165 case Status.STATUS_MARKED_ROLLBACK:
00166 case Status.STATUS_ROLLEDBACK:
00167 case Status.STATUS_ROLLING_BACK:
00168 TraceEjb.logger.log(BasicLevel.WARN, ident + "getICtx IT: transaction rolled back");
00169 throw new TransactionRolledbackLocalException("rollback occured while waiting");
00170 }
00171 }
00172 }
00173
00174 }
00175
00181 public synchronized boolean passivateIH(boolean passivation) {
00182
00183 JEntityContext jec = getContext4Tx(null);
00184
00185
00186 if (jec == null) {
00187 if (inactivityTimeout > 0) {
00188 long diff = System.currentTimeMillis() - timestamp;
00189 if (diff > inactivityTimeout) {
00190 TraceEjb.context.log(BasicLevel.DEBUG, ident + timestamp);
00191 discardContext(null, true, false);
00192 }
00193 }
00194 return true;
00195 }
00196
00197
00198 if (countIH > 0 && !txUpdates) {
00199
00200
00201
00202 if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " used off TX");
00203 mustStore = true;
00204 return true;
00205 }
00206 if (runningtx != null) {
00207 if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " used in TX");
00208 return false;
00209 }
00210
00211 if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident);
00212
00213 if (jec.isMarkedRemoved()) {
00214 discardContext(null, true, true);
00215 return true;
00216 }
00217
00218
00219
00220 if (!todiscard && !txUpdates) {
00221 try {
00222 jec.storeIfModified();
00223 } catch (Exception e) {
00224 TraceEjb.logger.log(BasicLevel.ERROR, ident, "error while storing bean state:", e);
00225 }
00226 mustStore = false;
00227
00228
00229 }
00230
00231
00232 if (passivation) {
00233 if (TraceEjb.isDebugContext()) TraceEjb.context.log(BasicLevel.DEBUG, "passivated: " + jec);
00234 jec.passivate();
00235 bf.releaseJContext(jec);
00236 removeContext4Tx(null);
00237
00238 timestamp = System.currentTimeMillis();
00239 TraceEjb.context.log(BasicLevel.DEBUG, ident + timestamp);
00240 if (waiters > 0) {
00241 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " notify");
00242 notifyAll();
00243 }
00244 }
00245 return true;
00246 }
00247
00251 public synchronized void endIH() {
00252 inDirtyList = false;
00253 if (getContext4Tx(null) == null) {
00254 if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " discarded!");
00255 return;
00256 }
00257
00258
00259 if (countIH == 0) {
00260 if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " ready again");
00261 } else {
00262 if (TraceEjb.isDebugSynchro()) TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " busy!");
00263 }
00264 if (waiters > 0) {
00265 TraceEjb.synchro.log(BasicLevel.DEBUG, ident + " notify");
00266 notifyAll();
00267 }
00268 }
00269
00270 public synchronized void notifyWriting(Transaction tx, JEntityContext bctx) {
00271 return;
00272 }
00273
00279 public int getState() {
00280 if (itContext != null) {
00281 if (itContext.isMarkedRemoved()) {
00282 return 4;
00283 } else {
00284 if (runningtx != null) {
00285 return 0;
00286 } else {
00287 if (inDirtyList) {
00288 return 1;
00289 } else {
00290 return 2;
00291 }
00292 }
00293 }
00294 }
00295 return 3;
00296 }
00297
00298 }