diff options
5 files changed, 129 insertions, 16 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DetachTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DetachTest.java index ccf6a47ee6..37f8eb34ec 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DetachTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DetachTest.java @@ -90,7 +90,7 @@ public class DetachTest extends AbstractCDOTest try { CDOObject object = transaction.getObject(id); - System.out.println(object); + msg(object); fail("ObjectNotFoundException expected"); } catch (ObjectNotFoundException expected) diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_390185_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_390185_Test.java new file mode 100644 index 0000000000..93d411e5f2 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_390185_Test.java @@ -0,0 +1,105 @@ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.model1.Category; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CommitException; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Bug 390185. + * + * @author Eike Stepper + */ +public class Bugzilla_390185_Test extends AbstractCDOTest +{ + private static final int THREADS = 5; + + private static final int TRANSACTIONS_PER_THREAD = 100; + + public void testIvalidationDeadlock() throws Exception + { + CDOSession session = openSession(); + + CountDownLatch latch = new CountDownLatch(THREADS); + List<Actor> actors = new ArrayList<Actor>(THREADS); + for (int i = 0; i < THREADS; i++) + { + Actor actor = new Actor(session, latch, i); + actors.add(actor); + } + + assertEquals(true, latch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)); + } + + /** + * @author Eike Stepper + */ + private class Actor extends Thread + { + private CDOSession session; + + private CountDownLatch latch; + + private int nr; + + public Actor(CDOSession session, CountDownLatch latch, int nr) + { + super("Actor-" + nr); + this.session = session; + this.latch = latch; + this.nr = nr; + start(); + } + + @Override + public void run() + { + for (int i = 0; i < TRANSACTIONS_PER_THREAD; i++) + { + CDOTransaction transaction = session.openTransaction(); + attemptCommit(transaction); + transaction.close(); + } + + latch.countDown(); + } + + private void attemptCommit(CDOTransaction transaction) + { + for (;;) + { + Category category = getModel1Factory().createCategory(); + category.setName("category-" + System.currentTimeMillis()); + + try + { + synchronized (transaction) + { + CDOResource res = transaction.getOrCreateResource(getResourcePath("/res-" + nr)); + res.getContents().add(category); + transaction.commit(); + break; + } + } + catch (CommitException ex) + { + transaction.rollback(); + } + catch (Exception ex) + { + ex.printStackTrace(); + break; + } + } + + transaction.close(); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineTest.java index eba5ffeef9..2ccf003808 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineTest.java @@ -200,6 +200,8 @@ public class OfflineTest extends AbstractSyncingTest resource.getContents().add(company); transaction.commit(); + sleep(1000); + IEvent[] events = listener.getEvents(); assertEquals(1, events.length); } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java index 5b94c0f3a1..35b1ad839a 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java @@ -1077,14 +1077,14 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme long nextPreviousTimeStamp = lastUpdateTime; for (;;) { + Runnable invalidationRunnable = null; synchronized (outOfSequenceInvalidations) { OutOfSequenceInvalidation currentInvalidation = outOfSequenceInvalidations.remove(nextPreviousTimeStamp); - - // If we don't have the invalidation that follows the last one we processed, - // then there is nothing we can do right now if (currentInvalidation == null) { + // If we don't have the invalidation that follows the last one we processed, + // then there is nothing we can do right now break; } @@ -1093,22 +1093,26 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme final boolean currentClearResourcePathCache = currentInvalidation.isClearResourcePathCache(); nextPreviousTimeStamp = currentCommitInfo.getTimeStamp(); - if (sender == null) + invalidationRunnable = new Runnable() { - QueueRunner invalidationRunner = getInvalidationRunner(); - invalidationRunner.addWork(new Runnable() + public void run() { - public void run() - { - invalidateOrdered(currentCommitInfo, currentSender, currentClearResourcePathCache); - } - }); - } - else + invalidateOrdered(currentCommitInfo, currentSender, currentClearResourcePathCache); + } + }; + + if (sender == null) { - invalidateOrdered(currentCommitInfo, currentSender, currentClearResourcePathCache); + QueueRunner invalidationRunner = getInvalidationRunner(); + invalidationRunner.addWork(invalidationRunnable); + invalidationRunnable = null; } } + + if (invalidationRunnable != null) + { + invalidationRunnable.run(); + } } } diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/QueueWorker.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/QueueWorker.java index 5a13aca1bb..c6a159236f 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/QueueWorker.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/QueueWorker.java @@ -10,6 +10,8 @@ */ package org.eclipse.net4j.util.concurrent; +import org.eclipse.net4j.util.lifecycle.LifecycleState; + import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -57,7 +59,7 @@ public abstract class QueueWorker<E> extends Worker public boolean addWork(E element) { - if (queue != null) + if (queue != null && getLifecycleState() != LifecycleState.DEACTIVATING) { return queue.offer(element); } |