/* * Copyright 2009 Udai Gupta, Ralf Joachim * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.castor.cpa.test.test04; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.exolab.castor.jdo.Database; import org.exolab.castor.jdo.LockNotGrantedException; import org.exolab.castor.jdo.TransactionAbortedException; import org.exolab.castor.jdo.TransactionNotInProgressException; import org.junit.Ignore; @Ignore public class SecondThread extends Thread { /** The <a href="http://jakarta.apache.org/commons/logging/">Jakarta * Commons Logging</a> instance used for all logging. */ private static final Log LOG = LogFactory.getLog(SecondThread.class); private Database _db; private TestDeadlock _theTest; public boolean _resultOk; SecondThread(final Database db, final TestDeadlock theTest) { _db = db; _theTest = theTest; } public void run() { Sample object; try { _db.begin(); // Suspend and give the other thread a opportunity. synchronized (TestDeadlock._lock) { TestDeadlock._lock.wait(); } // Load first object and change something about it // (otherwise will not write) LOG.debug("2.1: Loading object " + (Sample.DEFAULT_ID + 1)); object = _db.load(Sample.class, new Integer(Sample.DEFAULT_ID + 1), TestDeadlock._accessMode); object.setValue2(Sample.DEFAULT_VALUE_2 + ":2"); LOG.debug("2.2: Modified to " + object); // Notify the other thread that it may proceed and suspend // to give the other thread a 2 second opportunity. synchronized (TestDeadlock._lock) { TestDeadlock._lock.notify(); TestDeadlock._lock.wait(2000); } LOG.debug("2.3: Loading object " + Sample.DEFAULT_ID); try { object = _db.load(Sample.class, new Integer(Sample.DEFAULT_ID), TestDeadlock._accessMode); } catch (LockNotGrantedException ex) { if (TestDeadlock._accessMode == Database.EXCLUSIVE || TestDeadlock._accessMode == Database.DBLOCKED) { LOG.debug("2.X OK: Deadlock detected"); } else { _theTest._secondProblem = ex; LOG.info("2.X Error: ", ex); } _db.rollback(); _resultOk = true; return; } object.setValue1(Sample.DEFAULT_VALUE_1 + ":2"); LOG.debug("2.4: Modified to " + object); // Notify the other thread that it may proceed and suspend // to give the other thread a 2 second opportunity. synchronized (TestDeadlock._lock) { TestDeadlock._lock.notify(); TestDeadlock._lock.wait(2000); } // Attempt to commit the transaction, must acquire a write // lock blocking until the first transaction completes. LOG.debug("2.5: Committing"); _db.commit(); synchronized (TestDeadlock._lock) { TestDeadlock._lock.notify(); } LOG.info("2.6 Error: no deadlock and second committed"); _theTest._secondProblem = new Exception( "deadlock not detected"); } catch (TransactionAbortedException ex) { if (ex.getCause() instanceof LockNotGrantedException) { LOG.debug("2.X OK: Deadlock detected"); _resultOk = true; } else { _theTest._secondProblem = ex; LOG.info("2.X Error: ", ex); } LOG.debug("2.X Second: aborting"); } catch (Exception ex) { _theTest._secondProblem = ex; LOG.info("2.X Error: ", ex); } finally { try { if (_db.isActive()) { _db.rollback(); } } catch (TransactionNotInProgressException ex) { } } } }