diff options
author | Eike Stepper | 2016-01-16 07:45:58 +0000 |
---|---|---|
committer | Eike Stepper | 2016-01-16 07:45:58 +0000 |
commit | be45bd8af72711993c5c1777bf755a9506c5a90c (patch) | |
tree | de2ba3462facfa475f63cb674c2b0c6f0e7041f2 | |
parent | 1f436278ef4bc0e07e718366ef271f5c705a79fd (diff) | |
download | cdo-be45bd8af72711993c5c1777bf755a9506c5a90c.tar.gz cdo-be45bd8af72711993c5c1777bf755a9506c5a90c.tar.xz cdo-be45bd8af72711993c5c1777bf755a9506c5a90c.zip |
[323788] Deadlock on Display.syncExec()
https://bugs.eclipse.org/bugs/show_bug.cgi?id=323788
23 files changed, 5103 insertions, 2424 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java index ef3bfd6faa..2e40085253 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java @@ -109,7 +109,7 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd public ServerCDOView(InternalSession session, CDOBranchPoint branchPoint, CDORevisionProvider revisionProvider) { - super(branchPoint); + super(null, branchPoint); this.session = new ServerCDOSession(session); this.revisionProvider = revisionProvider; @@ -147,13 +147,13 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd return this; } - public synchronized InternalCDORevision getRevision(CDOID id, boolean loadOnDemand) + public InternalCDORevision getRevision(CDOID id, boolean loadOnDemand) { return (InternalCDORevision)revisionProvider.getRevision(id); } @Override - protected synchronized void excludeNewObject(CDOID id) + protected void excludeNewObject(CDOID id) { // Do nothing } @@ -1225,5 +1225,15 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd { throw new UnsupportedOperationException(); } + + public boolean isDelegableViewLockEnabled() + { + throw new UnsupportedOperationException(); + } + + public void setDelegableViewLockEnabled(boolean enabled) + { + throw new UnsupportedOperationException(); + } } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Locking_SequenceWithChildListTest_DISABLED.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Locking_SequenceWithChildListTest_DISABLED.java index adc69f3021..84530e236d 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Locking_SequenceWithChildListTest_DISABLED.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Locking_SequenceWithChildListTest_DISABLED.java @@ -24,6 +24,8 @@ import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.net4j.util.io.IOUtil; +import org.eclipse.emf.spi.cdo.InternalCDOTransaction; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -164,64 +166,73 @@ public class Locking_SequenceWithChildListTest_DISABLED extends AbstractLockingT for (int allocation = 0; allocation < ADDITIONS; allocation++) { CDOSession session = Locking_SequenceWithChildListTest_DISABLED.this.openSession(); - CDOTransaction transaction = session.openTransaction(); + InternalCDOTransaction transaction = (InternalCDOTransaction)session.openTransaction(); try { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - for (int retry = 0; retry < RETRIES; ++retry) - { - Company company = transaction.getObject(c); - CDOObject cdoObject = CDOUtil.getCDOObject(company); - CDOLock lock = cdoObject.cdoWriteLock(); + transaction.lockView(); - TimerThread timerThread = new TimerThread(getName() + ": lock(" + LOCK_TIMEOUT + ")"); - - try + try + { + for (int retry = 0; retry < RETRIES; ++retry) { - timerThread.start(); - lock.lock(LOCK_TIMEOUT); + Company company = transaction.getObject(c); + CDOObject cdoObject = CDOUtil.getCDOObject(company); + CDOLock lock = cdoObject.cdoWriteLock(); - Category category = getModel1Factory().createCategory(); - company.getCategories().add(category); + TimerThread timerThread = new TimerThread(getName() + ": lock(" + LOCK_TIMEOUT + ")"); try { - int version = cdoObject.cdoRevision().getVersion() + 1; - System.out.println(getName() + ": committing version " + version); - - transaction.setCommitComment(getName() + ": version " + version); - transaction.commit(); - - ++additions; - msg("Category added " + getAdditions()); - break; // No more retries. + timerThread.start(); + lock.lock(LOCK_TIMEOUT); + + Category category = getModel1Factory().createCategory(); + company.getCategories().add(category); + + try + { + int version = cdoObject.cdoRevision().getVersion() + 1; + System.out.println(getName() + ": committing version " + version); + + transaction.setCommitComment(getName() + ": version " + version); + transaction.commit(); + + ++additions; + msg("Category added " + getAdditions()); + break; // No more retries. + } + catch (Exception ex) + { + exception = ex; + return; + } } - catch (Exception ex) + catch (TimeoutException ex) { + msg("Lock timed out."); + exception = ex; - return; - } - } - catch (TimeoutException ex) - { - msg("Lock timed out."); + if (retry == RETRIES - 1) + { + msg("Exhausted!"); + return; + } - exception = ex; - if (retry == RETRIES - 1) + msg("Trying again..."); + } + finally { - msg("Exhausted!"); - return; + timerThread.done(); } - - msg("Trying again..."); - } - finally - { - timerThread.done(); } } + finally + { + transaction.unlockView(); + } } } finally diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250910_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250910_Test.java index 1f4e516401..2a4b732ecf 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250910_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250910_Test.java @@ -20,11 +20,13 @@ import org.eclipse.emf.cdo.tests.util.TestAdapter; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; +import java.util.concurrent.Callable; + /** * 250910: IllegalArgumentException: created > revised * <p> * See bug 250910 - * + * * @author Simon McDuff */ public class Bugzilla_250910_Test extends AbstractCDOTest @@ -33,7 +35,7 @@ public class Bugzilla_250910_Test extends AbstractCDOTest { CDOSession session = openSession(); - CDOTransaction transaction1 = session.openTransaction(); + final CDOTransaction transaction1 = session.openTransaction(); String resourcePath = "/test1"; CDOResource res = transaction1.createResource(getResourcePath(resourcePath)); Company company = getModel1Factory().createCompany(); @@ -41,24 +43,28 @@ public class Bugzilla_250910_Test extends AbstractCDOTest res.getContents().add(company); transaction1.commit(); - CDOID id = CDOUtil.getCDOObject(company).cdoID(); + final CDOID id = CDOUtil.getCDOObject(company).cdoID(); for (int i = 0; i < 20; i++) { - TestAdapter testAdapter = new TestAdapter(); + final TestAdapter testAdapter = new TestAdapter(); CDOSession session2 = openSession(); - CDOTransaction transaction2 = session2.openTransaction(); + final CDOTransaction transaction2 = session2.openTransaction(); company.setName(String.valueOf(i)); - Company company2; - synchronized (transaction2) + Company company2 = transaction2.syncExec(new Callable<Company>() { - transaction1.commit(); + public Company call() throws Exception + { + transaction1.commit(); + + transaction2.options().setInvalidationNotificationEnabled(true); + Company company2 = (Company)CDOUtil.getEObject(transaction2.getObject(id, true)); + company2.eAdapters().add(testAdapter); - transaction2.options().setInvalidationNotificationEnabled(true); - company2 = (Company)CDOUtil.getEObject(transaction2.getObject(id, true)); - company2.eAdapters().add(testAdapter); - } + return company2; + } + }); assertEquals(String.valueOf(i), company2.getName()); // Need a way to test if an error occured in the invalidation process. diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java index 466e930006..e0c54d53fc 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_316444_Test.java @@ -24,6 +24,7 @@ import org.eclipse.emf.cdo.tests.model3.NodeB; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.util.CommitException; +import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.net4j.util.WrappedException; @@ -32,6 +33,7 @@ import org.eclipse.emf.ecore.resource.Resource; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -584,48 +586,57 @@ public class Bugzilla_316444_Test extends AbstractCDOTest return y; } - private NodeB getElementFromGraphNodeB(NodeB node, String name) + private NodeB getElementFromGraphNodeB(final NodeB node, final String name) throws Exception { if (node.getName().equals(name)) { return node; } - synchronized (CDOUtil.getView(node)) + CDOView view = CDOUtil.getView(node); + return view.syncExec(new Callable<NodeB>() { - for (NodeB child : node.getChildren()) + public NodeB call() throws Exception { - NodeB elementFromGraph = getElementFromGraphNodeB(child, name); - if (elementFromGraph != null) + for (NodeB child : node.getChildren()) { - return elementFromGraph; + NodeB elementFromGraph = getElementFromGraphNodeB(child, name); + if (elementFromGraph != null) + { + return elementFromGraph; + } } - } - } - return null; + return null; + } + }); } @SuppressWarnings("unused") - private NodeA getElementFromGraphNodeA(NodeA node, String name) + private NodeA getElementFromGraphNodeA(final NodeA node, final String name) throws Exception { if (node.getName().equals(name)) { return node; } - synchronized (CDOUtil.getView(node)) + CDOView view = CDOUtil.getView(node); + return view.syncExec(new Callable<NodeA>() { - for (NodeA child : node.getChildren()) + public NodeA call() throws Exception { - NodeA elementFromGraph = getElementFromGraphNodeA(child, name); - if (elementFromGraph != null) + for (NodeA child : node.getChildren()) { - return elementFromGraph; + NodeA elementFromGraph = getElementFromGraphNodeA(child, name); + if (elementFromGraph != null) + { + return elementFromGraph; + } } + + return null; } - } - return null; + }); } /* diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_368223_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_368223_Test.java index 5a3bb5c493..43f107f443 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_368223_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_368223_Test.java @@ -29,6 +29,7 @@ import org.eclipse.emf.ecore.EObject; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; /** @@ -134,41 +135,46 @@ public class Bugzilla_368223_Test extends AbstractCDOTest protected void runSafe(AtomicReference<Throwable> exception) throws Exception { CDOSession session = openSession(); - CDOTransaction transaction = session.openTransaction(); + final CDOTransaction transaction = session.openTransaction(); transaction.options().setInvalidationPolicy(CDOInvalidationPolicy.STRICT); transaction.options().setStaleReferencePolicy(CDOStaleReferencePolicy.EXCEPTION); - CDOResource resource = transaction.getResource(getResourcePath("/test1")); - List<Company> listOfCompanies = new ArrayList<Company>(); + final CDOResource resource = transaction.getResource(getResourcePath("/test1")); + final List<Company> listOfCompanies = new ArrayList<Company>(); int loop = 5; while (exception.get() == null && --loop != 0) { - synchronized (transaction) + transaction.syncExec(new Callable<Object>() { - for (int i = 0; i < 20; i++) + public Object call() throws Exception { - Company company = createCompanyWithCategories(resource); - listOfCompanies.add(company); - } - - transaction.commit(); + for (int i = 0; i < 20; i++) + { + Company company = createCompanyWithCategories(resource); + listOfCompanies.add(company); + } - while (!listOfCompanies.isEmpty()) - { - Company company = listOfCompanies.remove(0); + transaction.commit(); - EList<Category> categories = company.getCategories(); - while (!categories.isEmpty()) + while (!listOfCompanies.isEmpty()) { - categories.remove(0); + Company company = listOfCompanies.remove(0); + + EList<Category> categories = company.getCategories(); + while (!categories.isEmpty()) + { + categories.remove(0); + transaction.commit(); + } + + resource.getContents().remove(company); transaction.commit(); } - resource.getContents().remove(company); - transaction.commit(); + return null; } - } + }); } throw new Success(); @@ -211,25 +217,30 @@ public class Bugzilla_368223_Test extends AbstractCDOTest transaction.options().setInvalidationPolicy(CDOInvalidationPolicy.STRICT); transaction.options().setFeatureAnalyzer(CDOUtil.createModelBasedFeatureAnalyzer()); - CDOResource resource = transaction.getResource(getResourcePath("/test1")); + final CDOResource resource = transaction.getResource(getResourcePath("/test1")); while (exception.get() == null) { try { - synchronized (transaction) + transaction.syncExec(new Callable<Object>() { - for (EObject object : resource.getContents()) + public Object call() throws Exception { - Company company = (Company)object; - EList<Category> categories = company.getCategories(); - if (categories.size() > 0) + for (EObject object : resource.getContents()) { - Category category = categories.get(0); - msg(category); + Company company = (Company)object; + EList<Category> categories = company.getCategories(); + if (categories.size() > 0) + { + Category category = categories.get(0); + msg(category); + } } + + return null; } - } + }); } catch (InvalidObjectException ex) { 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 index c8104e2aee..834259a989 100644 --- 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 @@ -21,6 +21,7 @@ import org.eclipse.net4j.util.concurrent.ConcurrencyUtil; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -88,22 +89,28 @@ public class Bugzilla_390185_Test extends AbstractCDOTest latch.countDown(); } - private void attemptCommit(CDOTransaction transaction) + private void attemptCommit(final CDOTransaction transaction) { for (;;) { - Category category = getModel1Factory().createCategory(); + final Category category = getModel1Factory().createCategory(); category.setName("category-" + System.currentTimeMillis()); try { - synchronized (transaction) + transaction.syncExec(new Callable<Object>() { - CDOResource res = transaction.getOrCreateResource(getResourcePath("/res-" + nr)); - res.getContents().add(category); - transaction.commit(); - break; - } + public Object call() throws Exception + { + CDOResource res = transaction.getOrCreateResource(getResourcePath("/res-" + nr)); + res.getContents().add(category); + transaction.commit(); + + return null; + } + }); + + break; } catch (CommitConflictException ex) { diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java index ea6c00c384..1d2ebc7c1e 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java @@ -278,6 +278,7 @@ public abstract class SessionConfig extends Config implements ISessionConfig { final File lobCache = getCurrentTest().createTempFolder("lobs_" + new Date().getTime() + "_", ".tmp"); session.options().setLobCache(new CDOLobStoreImpl(lobCache)); + session.options().setDelegableViewLockEnabled(true); session.addListener(new LifecycleEventAdapter() { @Override diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java index ce9ac462eb..b9c612437b 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSession.java @@ -31,12 +31,15 @@ import org.eclipse.emf.cdo.session.remote.CDORemoteSessionManager; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.transaction.CDOTransactionContainer; import org.eclipse.emf.cdo.util.CDOUpdatable; +import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.view.CDOFetchRuleManager; import org.eclipse.emf.cdo.view.CDOView; +import org.eclipse.net4j.util.concurrent.DelegableReentrantLock; import org.eclipse.net4j.util.options.IOptionsEvent; import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; +import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EPackage.Registry; @@ -44,6 +47,8 @@ import org.eclipse.emf.spi.cdo.CDOPermissionUpdater; import org.eclipse.emf.spi.cdo.CDOSessionProtocol; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.RefreshSessionResult; +import java.util.concurrent.locks.Lock; + /** * Represents and controls the connection to a model repository in addition to the inherited {@link CDOView view} * management functions. @@ -293,6 +298,21 @@ public interface CDOSession public void setPermissionUpdater(CDOPermissionUpdater permissionUpdater); /** + * @since 4.5 + */ + public boolean isDelegableViewLockEnabled(); + + /** + * This method is useful, for example, if EMF {@link Adapter adapters} call <code>Display.syncExec()</code> in response to CDO notifications. + * In these cases a {@link DelegableReentrantLock} can be injected into the new {@link CDOView view}, + * which does not deadlock when both CDO's invalidation thread and the display thread acquire the view lock. + * + * @see CDOUtil#setNextViewLock(Lock) + * @since 4.5 + */ + public void setDelegableViewLockEnabled(boolean delegableViewLockEnabled); + + /** * An {@link IOptionsEvent options event} fired when the * {@link Options#setGeneratedPackageEmulationEnabled(boolean) generated package emulation enabled} option of a * {@link CDOSession session} has changed. @@ -343,6 +363,19 @@ public interface CDOSession public interface PermissionUpdaterEvent extends IOptionsEvent { } + + /** + * An {@link IOptionsEvent options event} fired when the {@link Options#setDelegableViewLockEnabled(boolean) delegable view lock enabled} + * option of a {@link CDOSession session} has changed. + * + * @author Eike Stepper + * @since 4.5 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + public interface DelegableViewLockEvent extends IOptionsEvent + { + } } /** diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java index c7f02d0f3d..13ef778aaf 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java @@ -67,6 +67,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.locks.Lock; /** * A {@link CDOTransaction transaction} that persists changes to the object graph locally on commit and can later load @@ -676,6 +678,30 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction return delegate.getViewSet(); } + /** + * @since 4.5 + */ + public Lock getViewLock() + { + return delegate.getViewLock(); + } + + /** + * @since 4.5 + */ + public void syncExec(Runnable runnable) + { + delegate.syncExec(runnable); + } + + /** + * @since 4.5 + */ + public <V> V syncExec(Callable<V> callable) throws Exception + { + return delegate.syncExec(callable); + } + public boolean hasConflict() { return delegate.hasConflict(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java index 7c815a3b22..d59486c1b0 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOUserTransaction.java @@ -45,24 +45,23 @@ public interface CDOUserTransaction * write robust transactions: * <pre> CDOTransaction transaction = null; - + try { transaction = session.openTransaction(); - + for (;;) { + transaction.getViewLock().lock(); + try { - synchronized (transaction) - { - CDOResource resource = transaction.getResource("/stock/resource1"); + CDOResource resource = transaction.getResource("/stock/resource1"); - // Modify the model here... + // Modify the model here... - transaction.commit(); - break; - } + transaction.commit(); + break; } catch (ConcurrentAccessException ex) { @@ -72,6 +71,10 @@ public interface CDOUserTransaction { throw ex.wrap(); } + finally + { + transaction.getViewLock().unlock(); + } } } finally diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java index 3d0812d23b..d39a736e96 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java @@ -32,16 +32,19 @@ import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl; import org.eclipse.emf.cdo.session.CDOCollectionLoadingPolicy; import org.eclipse.emf.cdo.session.CDORepositoryInfo; import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.session.CDOSession.Options; import org.eclipse.emf.cdo.session.remote.CDORemoteSessionManager; import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.transaction.CDOTransactionCommentator; +import org.eclipse.emf.cdo.transaction.CDOTransactionContainer; import org.eclipse.emf.cdo.transaction.CDOXATransaction; import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer; import org.eclipse.emf.cdo.view.CDOFetchRuleManager; import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy; import org.eclipse.emf.cdo.view.CDOStaleObject; import org.eclipse.emf.cdo.view.CDOView; +import org.eclipse.emf.cdo.view.CDOViewContainer; import org.eclipse.emf.cdo.view.CDOViewProviderRegistry; import org.eclipse.emf.cdo.view.CDOViewSet; @@ -56,11 +59,13 @@ import org.eclipse.emf.internal.cdo.object.CDOObjectWrapper; import org.eclipse.emf.internal.cdo.session.CDOCollectionLoadingPolicyImpl; import org.eclipse.emf.internal.cdo.transaction.CDOXATransactionImpl; import org.eclipse.emf.internal.cdo.transaction.CDOXATransactionImpl.CDOXAInternalAdapter; +import org.eclipse.emf.internal.cdo.view.AbstractCDOView; import org.eclipse.emf.internal.cdo.view.CDORevisionPrefetchingPolicyImpl; import org.eclipse.emf.internal.cdo.view.CDOStateMachine; import org.eclipse.emf.internal.cdo.view.CDOStoreImpl; import org.eclipse.net4j.util.AdapterUtil; +import org.eclipse.net4j.util.concurrent.DelegableReentrantLock; import org.eclipse.net4j.util.container.IPluginContainer; import org.eclipse.net4j.util.om.OMPlatform; import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; @@ -86,6 +91,7 @@ import org.eclipse.emf.spi.cdo.InternalCDOView; import java.util.Collection; import java.util.Iterator; import java.util.Map; +import java.util.concurrent.locks.Lock; /** * Various static methods that may help in CDO client applications. @@ -232,6 +238,25 @@ public final class CDOUtil } /** + * Sets the {@link CDOView#getViewLock() lock} to be used for the next view that is opened in the context of the current thread. + * <p> + * This method is useful, for example, if EMF {@link Adapter adapters} call <code>Display.syncExec()</code> in response to CDO notifications. + * In these cases a {@link DelegableReentrantLock} can be injected into the new {@link CDOView view}, + * which does not deadlock when both CDO's invalidation thread and the display thread acquire the view lock. + * <p> + * This method involves a {@link ThreadLocal} variable to avoid method explosion in {@link CDOViewContainer} and {@link CDOTransactionContainer}. + * After calling this method make sure to either open a new {@link CDOView view} from the current thread or call <code>setNextViewLock(null)</code> + * to clear the {@link ThreadLocal} variable. + * + * @see Options#setDelegableViewLockEnabled(boolean) + * @since 4.5 + */ + public static void setNextViewLock(Lock viewLock) + { + AbstractCDOView.setNextViewLock(viewLock); + } + + /** * @since 4.4 */ public static void configureView(CDOView view) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java index 025f1b7898..6868e61e1a 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java @@ -24,17 +24,16 @@ import org.eclipse.net4j.util.transaction.TransactionException; for (;;) { + transaction.getViewLock().lock(); + try { - synchronized (transaction) - { - CDOResource resource = transaction.getResource("/stock/resource1"); + CDOResource resource = transaction.getResource("/stock/resource1"); - // Modify the model here... + // Modify the model here... - transaction.commit(); - break; - } + transaction.commit(); + break; } catch (ConcurrentAccessException ex) { @@ -44,6 +43,10 @@ import org.eclipse.net4j.util.transaction.TransactionException; { throw ex.wrap(); } + finally + { + transaction.getViewLock().unlock(); + } } * </pre> * diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java index 5cb4d9c9ae..223ced6a12 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java @@ -57,6 +57,8 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.locks.Lock; /** * A read-only view to the state of the object graph in the repository of the underlying {@link CDOSession session} at a @@ -127,6 +129,21 @@ public interface CDOView extends CDOCommonView, CDOUpdatable, CDOCommitHistory.P public CDOViewSet getViewSet(); /** + * @since 4.5 + */ + public Lock getViewLock(); + + /** + * @since 4.5 + */ + public void syncExec(Runnable runnable); + + /** + * @since 4.5 + */ + public <V> V syncExec(Callable<V> callable) throws Exception; + + /** * Returns the {@link ResourceSet resource set} this view is associated with. * <p> * Same as calling <tt>getViewSet().getResourceSet()</tt>. 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 5643db22a1..359388673a 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 @@ -1392,6 +1392,8 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl private CDOPermissionUpdater permissionUpdater = CDOPermissionUpdater.SERVER; + private boolean delegableViewLockEnabled; + public OptionsImpl() { setCollectionLoadingPolicy(null); // Init default @@ -1621,6 +1623,37 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl } } + public boolean isDelegableViewLockEnabled() + { + synchronized (this) + { + return delegableViewLockEnabled; + } + } + + public void setDelegableViewLockEnabled(boolean delegableViewLockEnabled) + { + IListener[] listeners = getListeners(); + IEvent event = null; + + synchronized (this) + { + if (this.delegableViewLockEnabled != delegableViewLockEnabled) + { + this.delegableViewLockEnabled = delegableViewLockEnabled; + if (listeners != null) + { + event = new DelegableViewLockEventImpl(); + } + } + } + + if (event != null) + { + fireEvent(event, listeners); + } + } + /** * @author Eike Stepper */ @@ -1746,6 +1779,19 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl super(OptionsImpl.this); } } + + /** + * @author Eike Stepper + */ + private final class DelegableViewLockEventImpl extends OptionsEvent implements DelegableViewLockEvent + { + private static final long serialVersionUID = 1L; + + public DelegableViewLockEventImpl() + { + super(OptionsImpl.this); + } + } } /** diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOTransactionContainerImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOTransactionContainerImpl.java index 6f386d4c41..49ed6654e7 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOTransactionContainerImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOTransactionContainerImpl.java @@ -17,6 +17,7 @@ package org.eclipse.emf.internal.cdo.session; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.transaction.CDOTransactionContainer; import org.eclipse.emf.cdo.view.CDOView; @@ -115,7 +116,7 @@ public abstract class CDOTransactionContainerImpl extends CDOViewContainerImpl i */ protected InternalCDOTransaction createTransaction(CDOBranch branch) { - return new CDOTransactionImpl(branch); + return new CDOTransactionImpl((CDOSession)this, branch); } /** @@ -123,6 +124,6 @@ public abstract class CDOTransactionContainerImpl extends CDOViewContainerImpl i */ protected InternalCDOTransaction createTransaction(String durableLockingID) { - return new CDOTransactionImpl(durableLockingID); + return new CDOTransactionImpl((CDOSession)this, durableLockingID); } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOViewContainerImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOViewContainerImpl.java index 86d00dd9ff..270f3e3a53 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOViewContainerImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOViewContainerImpl.java @@ -17,6 +17,7 @@ package org.eclipse.emf.internal.cdo.session; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.cdo.view.CDOViewContainer; import org.eclipse.emf.cdo.view.CDOViewProvider; @@ -41,7 +42,7 @@ import java.util.Set; /** * @author Eike Stepper */ -public abstract class CDOViewContainerImpl extends Container<CDOView>implements CDOViewContainer +public abstract class CDOViewContainerImpl extends Container<CDOView> implements CDOViewContainer { public static final ThreadLocal<CDOViewProvider> VIEW_PROVIDER = new ThreadLocal<CDOViewProvider>(); @@ -211,7 +212,7 @@ public abstract class CDOViewContainerImpl extends Container<CDOView>implements */ protected InternalCDOView createView(CDOBranch branch, long timeStamp) { - return new CDOViewImpl(branch, timeStamp); + return new CDOViewImpl((CDOSession)this, branch, timeStamp); } /** @@ -219,7 +220,7 @@ public abstract class CDOViewContainerImpl extends Container<CDOView>implements */ protected InternalCDOView createView(String durableLockingID) { - return new CDOViewImpl(durableLockingID); + return new CDOViewImpl((CDOSession)this, durableLockingID); } protected ResourceSet createResourceSet() diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java index d6050b513a..b52f8d1f92 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java @@ -65,14 +65,23 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD @Override public CDOObject put(CDOID key, CDOObject object) { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - baseNewObjects.remove(key); - newObjects.remove(key); - reattachedObjects.remove(key); - dirtyObjects.remove(key); - revisionDeltas.remove(key); - return super.put(key, object); + transaction.lockView(); + + try + { + baseNewObjects.remove(key); + newObjects.remove(key); + reattachedObjects.remove(key); + dirtyObjects.remove(key); + revisionDeltas.remove(key); + return super.put(key, object); + } + finally + { + transaction.unlockView(); + } } } }; @@ -115,40 +124,76 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD @Override public InternalCDOSavepoint getFirstSavePoint() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - return (InternalCDOSavepoint)super.getFirstSavePoint(); + transaction.lockView(); + + try + { + return (InternalCDOSavepoint)super.getFirstSavePoint(); + } + finally + { + transaction.unlockView(); + } } } @Override public InternalCDOSavepoint getPreviousSavepoint() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - return (InternalCDOSavepoint)super.getPreviousSavepoint(); + transaction.lockView(); + + try + { + return (InternalCDOSavepoint)super.getPreviousSavepoint(); + } + finally + { + transaction.unlockView(); + } } } @Override public InternalCDOSavepoint getNextSavepoint() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - return (InternalCDOSavepoint)super.getNextSavepoint(); + transaction.lockView(); + + try + { + return (InternalCDOSavepoint)super.getNextSavepoint(); + } + finally + { + transaction.unlockView(); + } } } public void clear() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - newObjects.clear(); - dirtyObjects.clear(); - revisionDeltas.clear(); - baseNewObjects.clear(); - detachedObjects.clear(); - reattachedObjects.clear(); + transaction.lockView(); + + try + { + newObjects.clear(); + dirtyObjects.clear(); + revisionDeltas.clear(); + baseNewObjects.clear(); + detachedObjects.clear(); + reattachedObjects.clear(); + } + finally + { + transaction.unlockView(); + } } } @@ -296,17 +341,35 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD public CDOChangeSetData getChangeSetData() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - return createChangeSetData(newObjects, revisionDeltas, detachedObjects); + transaction.lockView(); + + try + { + return createChangeSetData(newObjects, revisionDeltas, detachedObjects); + } + finally + { + transaction.unlockView(); + } } } public CDOChangeSetData getAllChangeSetData() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - return createChangeSetData(getAllNewObjects(), getAllRevisionDeltas(), getAllDetachedObjects()); + transaction.lockView(); + + try + { + return createChangeSetData(getAllNewObjects(), getAllRevisionDeltas(), getAllDetachedObjects()); + } + finally + { + transaction.unlockView(); + } } } @@ -344,20 +407,29 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD */ public Map<CDOID, CDOObject> getAllDirtyObjects() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - if (getPreviousSavepoint() == null) + transaction.lockView(); + + try { - return Collections.unmodifiableMap(getDirtyObjects()); - } + if (getPreviousSavepoint() == null) + { + return Collections.unmodifiableMap(getDirtyObjects()); + } - MultiMap.ListBased<CDOID, CDOObject> dirtyObjects = new MultiMap.ListBased<CDOID, CDOObject>(); - for (InternalCDOSavepoint savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint()) + MultiMap.ListBased<CDOID, CDOObject> dirtyObjects = new MultiMap.ListBased<CDOID, CDOObject>(); + for (InternalCDOSavepoint savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint()) + { + dirtyObjects.getDelegates().add(savepoint.getDirtyObjects()); + } + + return dirtyObjects; + } + finally { - dirtyObjects.getDelegates().add(savepoint.getDirtyObjects()); + transaction.unlockView(); } - - return dirtyObjects; } } @@ -366,25 +438,34 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD */ public Map<CDOID, CDOObject> getAllNewObjects() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - if (getPreviousSavepoint() == null) - { - return Collections.unmodifiableMap(getNewObjects()); - } + transaction.lockView(); - Map<CDOID, CDOObject> newObjects = CDOIDUtil.createMap(); - for (InternalCDOSavepoint savepoint = getFirstSavePoint(); savepoint != null; savepoint = savepoint - .getNextSavepoint()) + try { - newObjects.putAll(savepoint.getNewObjects()); - for (CDOID removedID : savepoint.getDetachedObjects().keySet()) + if (getPreviousSavepoint() == null) { - newObjects.remove(removedID); + return Collections.unmodifiableMap(getNewObjects()); } - } - return newObjects; + Map<CDOID, CDOObject> newObjects = CDOIDUtil.createMap(); + for (InternalCDOSavepoint savepoint = getFirstSavePoint(); savepoint != null; savepoint = savepoint + .getNextSavepoint()) + { + newObjects.putAll(savepoint.getNewObjects()); + for (CDOID removedID : savepoint.getDetachedObjects().keySet()) + { + newObjects.remove(removedID); + } + } + + return newObjects; + } + finally + { + transaction.unlockView(); + } } } @@ -393,20 +474,29 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD */ public Map<CDOID, CDORevision> getAllBaseNewObjects() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - if (getPreviousSavepoint() == null) + transaction.lockView(); + + try { - return Collections.unmodifiableMap(getBaseNewObjects()); - } + if (getPreviousSavepoint() == null) + { + return Collections.unmodifiableMap(getBaseNewObjects()); + } + + MultiMap.ListBased<CDOID, CDORevision> newObjects = new MultiMap.ListBased<CDOID, CDORevision>(); + for (InternalCDOSavepoint savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint()) + { + newObjects.getDelegates().add(savepoint.getBaseNewObjects()); + } - MultiMap.ListBased<CDOID, CDORevision> newObjects = new MultiMap.ListBased<CDOID, CDORevision>(); - for (InternalCDOSavepoint savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint()) + return newObjects; + } + finally { - newObjects.getDelegates().add(savepoint.getBaseNewObjects()); + transaction.unlockView(); } - - return newObjects; } } @@ -415,83 +505,101 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD */ public Map<CDOID, CDORevisionDelta> getAllRevisionDeltas() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - if (getPreviousSavepoint() == null) - { - return Collections.unmodifiableMap(getRevisionDeltas2()); - } + transaction.lockView(); - // We need to combined the result for all delta in different Savepoint - Map<CDOID, CDORevisionDelta> allRevisionDeltas = CDOIDUtil.createMap(); - for (InternalCDOSavepoint savepoint = getFirstSavePoint(); savepoint != null; savepoint = savepoint - .getNextSavepoint()) + try { - for (CDORevisionDelta revisionDelta : savepoint.getRevisionDeltas2().values()) + if (getPreviousSavepoint() == null) { - CDOID id = revisionDelta.getID(); - if (!isNewObject(id)) + return Collections.unmodifiableMap(getRevisionDeltas2()); + } + + // We need to combined the result for all delta in different Savepoint + Map<CDOID, CDORevisionDelta> allRevisionDeltas = CDOIDUtil.createMap(); + for (InternalCDOSavepoint savepoint = getFirstSavePoint(); savepoint != null; savepoint = savepoint + .getNextSavepoint()) + { + for (CDORevisionDelta revisionDelta : savepoint.getRevisionDeltas2().values()) { - CDORevisionDeltaImpl oldRevisionDelta = (CDORevisionDeltaImpl)allRevisionDeltas.get(id); - if (oldRevisionDelta == null) - { - allRevisionDeltas.put(id, revisionDelta.copy()); - } - else + CDOID id = revisionDelta.getID(); + if (!isNewObject(id)) { - for (CDOFeatureDelta delta : revisionDelta.getFeatureDeltas()) + CDORevisionDeltaImpl oldRevisionDelta = (CDORevisionDeltaImpl)allRevisionDeltas.get(id); + if (oldRevisionDelta == null) { - CDOFeatureDelta copy = ((InternalCDOFeatureDelta)delta).copy(); - oldRevisionDelta.addFeatureDelta(copy, null); + allRevisionDeltas.put(id, revisionDelta.copy()); + } + else + { + for (CDOFeatureDelta delta : revisionDelta.getFeatureDeltas()) + { + CDOFeatureDelta copy = ((InternalCDOFeatureDelta)delta).copy(); + oldRevisionDelta.addFeatureDelta(copy, null); + } } } } - } - Set<CDOID> reattachedObjects = savepoint.getReattachedObjects().keySet(); - for (CDOID detachedID : savepoint.getDetachedObjects().keySet()) - { - if (!reattachedObjects.contains(detachedID)) + Set<CDOID> reattachedObjects = savepoint.getReattachedObjects().keySet(); + for (CDOID detachedID : savepoint.getDetachedObjects().keySet()) { - allRevisionDeltas.remove(detachedID); + if (!reattachedObjects.contains(detachedID)) + { + allRevisionDeltas.remove(detachedID); + } } } - } - return Collections.unmodifiableMap(allRevisionDeltas); + return Collections.unmodifiableMap(allRevisionDeltas); + } + finally + { + transaction.unlockView(); + } } } public Map<CDOID, CDOObject> getAllDetachedObjects() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - if (getPreviousSavepoint() == null && reattachedObjects.isEmpty()) - { - return Collections.unmodifiableMap(getDetachedObjects()); - } + transaction.lockView(); - Map<CDOID, CDOObject> detachedObjects = CDOIDUtil.createMap(); - for (InternalCDOSavepoint savepoint = getFirstSavePoint(); savepoint != null; savepoint = savepoint - .getNextSavepoint()) + try { - for (Entry<CDOID, CDOObject> entry : savepoint.getDetachedObjects().entrySet()) + if (getPreviousSavepoint() == null && reattachedObjects.isEmpty()) { - CDOID detachedID = entry.getKey(); - if (!isNewObject(detachedID)) - { - CDOObject detachedObject = entry.getValue(); - detachedObjects.put(detachedID, detachedObject); - } + return Collections.unmodifiableMap(getDetachedObjects()); } - for (CDOID reattachedID : savepoint.getReattachedObjects().keySet()) + Map<CDOID, CDOObject> detachedObjects = CDOIDUtil.createMap(); + for (InternalCDOSavepoint savepoint = getFirstSavePoint(); savepoint != null; savepoint = savepoint + .getNextSavepoint()) { - detachedObjects.remove(reattachedID); + for (Entry<CDOID, CDOObject> entry : savepoint.getDetachedObjects().entrySet()) + { + CDOID detachedID = entry.getKey(); + if (!isNewObject(detachedID)) + { + CDOObject detachedObject = entry.getValue(); + detachedObjects.put(detachedID, detachedObject); + } + } + + for (CDOID reattachedID : savepoint.getReattachedObjects().keySet()) + { + detachedObjects.remove(reattachedID); + } } - } - return detachedObjects; + return detachedObjects; + } + finally + { + transaction.unlockView(); + } } } @@ -502,15 +610,24 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD return true; } - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - for (InternalCDOSavepoint savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint()) + transaction.lockView(); + + try { - if (savepoint.getNewObjects().containsKey(id)) + for (InternalCDOSavepoint savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint()) { - return true; + if (savepoint.getNewObjects().containsKey(id)) + { + return true; + } } } + finally + { + transaction.unlockView(); + } } return false; @@ -526,7 +643,7 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD // // boolean isNew = false; // boolean wasNew = false; - // synchronized (transaction) + // synchronized (transaction) // TODO synchronized -> transaction.getViewLock().lock() // { // for (InternalCDOSavepoint savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint()) // { @@ -553,13 +670,22 @@ public class CDOSavepointImpl extends CDOUserSavepointImpl implements InternalCD public void rollback() { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - InternalCDOTransaction transaction = getTransaction(); - LifecycleUtil.checkActive(transaction); + transaction.lockView(); + + try + { + InternalCDOTransaction transaction = getTransaction(); + LifecycleUtil.checkActive(transaction); - CDOTransactionStrategy transactionStrategy = transaction.getTransactionStrategy(); - transactionStrategy.rollback(transaction, this); + CDOTransactionStrategy transactionStrategy = transaction.getTransactionStrategy(); + transactionStrategy.rollback(transaction, this); + } + finally + { + transaction.unlockView(); + } } } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java index 9aee7a2fd6..925ae9391f 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java @@ -71,6 +71,7 @@ import org.eclipse.emf.cdo.eresource.impl.CDOResourceNodeImpl; import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo; import org.eclipse.emf.cdo.internal.common.revision.CDOListWithElementProxiesImpl; import org.eclipse.emf.cdo.session.CDORepositoryInfo; +import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil; import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; @@ -254,14 +255,14 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa */ private Map<InternalCDOObject, InternalCDORevision> cleanRevisions = new CleanRevisionsMap(); - public CDOTransactionImpl(CDOBranch branch) + public CDOTransactionImpl(CDOSession session, CDOBranch branch) { - super(branch, UNSPECIFIED_DATE); + super(session, branch, UNSPECIFIED_DATE); } - public CDOTransactionImpl(String durableLockingID) + public CDOTransactionImpl(CDOSession session, String durableLockingID) { - super(durableLockingID); + super(session, durableLockingID); } /** @@ -289,19 +290,31 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } @Override - public synchronized boolean setBranchPoint(CDOBranchPoint branchPoint) + public boolean setBranchPoint(CDOBranchPoint branchPoint) { - if (branchPoint.getTimeStamp() != UNSPECIFIED_DATE) + synchronized (getViewMonitor()) { - throw new IllegalArgumentException("Changing the target time is not supported by transactions"); - } + lockView(); - if (isDirty() && !getBranch().equals(branchPoint.getBranch())) - { - throw new IllegalStateException("Changing the target branch is impossible while transaction is dirty"); - } + try + { + if (branchPoint.getTimeStamp() != UNSPECIFIED_DATE) + { + throw new IllegalArgumentException("Changing the target time is not supported by transactions"); + } + + if (isDirty() && !getBranch().equals(branchPoint.getBranch())) + { + throw new IllegalStateException("Changing the target branch is impossible while transaction is dirty"); + } - return super.setBranchPoint(branchPoint); + return super.setBranchPoint(branchPoint); + } + finally + { + unlockView(); + } + } } public void addTransactionHandler(CDOTransactionHandlerBase handler) @@ -421,10 +434,19 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa public void setConflict(InternalCDOObject object) { IEvent event = null; - synchronized (this) + synchronized (getViewMonitor()) { - event = new ConflictEvent(object, conflict == 0); - ++conflict; + lockView(); + + try + { + event = new ConflictEvent(object, conflict == 0); + ++conflict; + } + finally + { + unlockView(); + } } fireEvent(event); @@ -432,11 +454,20 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa public void removeConflict(InternalCDOObject object) { - synchronized (this) + synchronized (getViewMonitor()) { - if (conflict > 0) + lockView(); + + try { - --conflict; + if (conflict > 0) + { + --conflict; + } + } + finally + { + unlockView(); } } } @@ -444,79 +475,115 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized Set<CDOObject> getConflicts() + public Set<CDOObject> getConflicts() { - Set<CDOObject> conflicts = new HashSet<CDOObject>(); - for (CDOObject object : getDirtyObjects().values()) + synchronized (getViewMonitor()) { - if (object.cdoConflict()) + lockView(); + + try { - conflicts.add(object); - } - } + Set<CDOObject> conflicts = new HashSet<CDOObject>(); + for (CDOObject object : getDirtyObjects().values()) + { + if (object.cdoConflict()) + { + conflicts.add(object); + } + } - for (CDOObject object : getDetachedObjects().values()) - { - if (object.cdoConflict()) + for (CDOObject object : getDetachedObjects().values()) + { + if (object.cdoConflict()) + { + conflicts.add(object); + } + } + + return conflicts; + } + finally { - conflicts.add(object); + unlockView(); } } - - return conflicts; } - public synchronized CDOChangeSetData getChangeSetData() + public CDOChangeSetData getChangeSetData() { checkActive(); - return lastSavepoint.getAllChangeSetData(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return lastSavepoint.getAllChangeSetData(); + } + finally + { + unlockView(); + } + } } - public synchronized CDOChangeSetData merge(CDOBranchPoint source, CDOMerger merger) + public CDOChangeSetData merge(CDOBranchPoint source, CDOMerger merger) { return merge(source, null, merger); } - public synchronized CDOChangeSetData merge(CDOBranchPoint source, CDOBranchPoint sourceBase, CDOMerger merger) + public CDOChangeSetData merge(CDOBranchPoint source, CDOBranchPoint sourceBase, CDOMerger merger) { - if (isDirty()) + synchronized (getViewMonitor()) { - throw new IllegalStateException("Merging into dirty transactions not yet supported"); - } + lockView(); - long now = getLastUpdateTime(); - CDOBranchPoint target = getBranch().getPoint(now); + try + { + if (isDirty()) + { + throw new IllegalStateException("Merging into dirty transactions not yet supported"); + } - if (source.getTimeStamp() == UNSPECIFIED_DATE) - { - source = source.getBranch().getPoint(now); - } + long now = getLastUpdateTime(); + CDOBranchPoint target = getBranch().getPoint(now); - if (CDOBranchUtil.isContainedBy(source, target)) - { - throw new IllegalArgumentException("Source is already contained in " + target); - } + if (source.getTimeStamp() == UNSPECIFIED_DATE) + { + source = source.getBranch().getPoint(now); + } - if (sourceBase != null && !CDOBranchUtil.isContainedBy(sourceBase, source)) - { - throw new IllegalArgumentException("Source base is not contained in " + source); - } + if (CDOBranchUtil.isContainedBy(source, target)) + { + throw new IllegalArgumentException("Source is already contained in " + target); + } - InternalCDOSession session = getSession(); - MergeData mergeData = session.getMergeData(target, source, sourceBase, true); + if (sourceBase != null && !CDOBranchUtil.isContainedBy(sourceBase, source)) + { + throw new IllegalArgumentException("Source base is not contained in " + source); + } - CDOChangeSet targetChanges = mergeData.getTargetChanges(); - CDOChangeSet sourceChanges = mergeData.getSourceChanges(); - CDOChangeSetData result = merger.merge(targetChanges, sourceChanges); - if (result == null) - { - return null; - } + InternalCDOSession session = getSession(); + MergeData mergeData = session.getMergeData(target, source, sourceBase, true); + + CDOChangeSet targetChanges = mergeData.getTargetChanges(); + CDOChangeSet sourceChanges = mergeData.getSourceChanges(); + CDOChangeSetData result = merger.merge(targetChanges, sourceChanges); + if (result == null) + { + return null; + } - CDORevisionAvailabilityInfo ancestorInfo = mergeData.getAncestorInfo(); - CDORevisionAvailabilityInfo targetInfo = mergeData.getTargetInfo(); - ApplyChangeSetResult changeSet = applyChangeSet(result, ancestorInfo, targetInfo, source, false); - return changeSet.getChangeSetData(); + CDORevisionAvailabilityInfo ancestorInfo = mergeData.getAncestorInfo(); + CDORevisionAvailabilityInfo targetInfo = mergeData.getTargetInfo(); + ApplyChangeSetResult changeSet = applyChangeSet(result, ancestorInfo, targetInfo, source, false); + return changeSet.getChangeSetData(); + } + finally + { + unlockView(); + } + } } @Deprecated @@ -526,40 +593,51 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa throw new UnsupportedOperationException(); } - public synchronized ApplyChangeSetResult applyChangeSet(CDOChangeSetData changeSetData, - CDORevisionProvider ancestorProvider, CDORevisionProvider targetProvider, CDOBranchPoint source, - boolean keepVersions) throws ChangeSetOutdatedException + public ApplyChangeSetResult applyChangeSet(CDOChangeSetData changeSetData, CDORevisionProvider ancestorProvider, + CDORevisionProvider targetProvider, CDOBranchPoint source, boolean keepVersions) throws ChangeSetOutdatedException { - ApplyChangeSetResult result = new ApplyChangeSetResult(); - - // Merges from local offline branches may require additional ID mappings: localID -> tempID - if (source != null && source.getBranch().isLocal() - && getSession().getRepositoryInfo().getIDGenerationLocation() == CDOCommonRepository.IDGenerationLocation.STORE) + synchronized (getViewMonitor()) { - applyLocalIDMapping(changeSetData, result); - } + lockView(); - CDOChangeSetData resultData = result.getChangeSetData(); + try + { + ApplyChangeSetResult result = new ApplyChangeSetResult(); - // New objects - applyNewObjects(changeSetData.getNewObjects(), resultData.getNewObjects()); + // Merges from local offline branches may require additional ID mappings: localID -> tempID + if (source != null && source.getBranch().isLocal() && getSession().getRepositoryInfo() + .getIDGenerationLocation() == CDOCommonRepository.IDGenerationLocation.STORE) + { + applyLocalIDMapping(changeSetData, result); + } - // Detached objects - Set<CDOObject> detachedSet = applyDetachedObjects(changeSetData.getDetachedObjects(), - resultData.getDetachedObjects()); + CDOChangeSetData resultData = result.getChangeSetData(); - // Changed objects - Map<CDOID, InternalCDORevision> oldRevisions = applyChangedObjects(changeSetData.getChangedObjects(), - ancestorProvider, targetProvider, keepVersions, resultData.getChangedObjects()); + // New objects + applyNewObjects(changeSetData.getNewObjects(), resultData.getNewObjects()); - // Delta notifications - Collection<CDORevisionDelta> notificationDeltas = lastSavepoint.getRevisionDeltas2().values(); - if (!notificationDeltas.isEmpty() || !detachedSet.isEmpty()) - { - sendDeltaNotifications(notificationDeltas, detachedSet, oldRevisions); - } + // Detached objects + Set<CDOObject> detachedSet = applyDetachedObjects(changeSetData.getDetachedObjects(), + resultData.getDetachedObjects()); - return result; + // Changed objects + Map<CDOID, InternalCDORevision> oldRevisions = applyChangedObjects(changeSetData.getChangedObjects(), + ancestorProvider, targetProvider, keepVersions, resultData.getChangedObjects()); + + // Delta notifications + Collection<CDORevisionDelta> notificationDeltas = lastSavepoint.getRevisionDeltas2().values(); + if (!notificationDeltas.isEmpty() || !detachedSet.isEmpty()) + { + sendDeltaNotifications(notificationDeltas, detachedSet, oldRevisions); + } + + return result; + } + finally + { + unlockView(); + } + } } private void applyLocalIDMapping(CDOChangeSetData changeSetData, ApplyChangeSetResult result) @@ -752,90 +830,102 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa * Synchronized through InvalidationRunnable.run() */ @Override - protected synchronized void handleConflicts(long lastUpdateTime, - Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts, List<CDORevisionDelta> deltas) + protected void handleConflicts(long lastUpdateTime, Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts, + List<CDORevisionDelta> deltas) { - CDOConflictResolver[] resolvers = options().getConflictResolvers(); - if (resolvers.length == 0) + synchronized (getViewMonitor()) { - return; - } + lockView(); - if (conflicts == null) - { - for (CDOConflictResolver resolver : resolvers) + try { - if (resolver instanceof CDOConflictResolver.NonConflictAware) + CDOConflictResolver[] resolvers = options().getConflictResolvers(); + if (resolvers.length == 0) { - ((CDOConflictResolver.NonConflictAware)resolver).handleNonConflict(lastUpdateTime); + return; } - } - - return; - } - // Remember original state to be able to restore it after an exception - List<CDOState> states = new ArrayList<CDOState>(conflicts.size()); - List<CDORevision> revisions = new ArrayList<CDORevision>(conflicts.size()); - for (CDOObject conflict : conflicts.keySet()) - { - states.add(conflict.cdoState()); - revisions.add(conflict.cdoRevision()); - } + if (conflicts == null) + { + for (CDOConflictResolver resolver : resolvers) + { + if (resolver instanceof CDOConflictResolver.NonConflictAware) + { + ((CDOConflictResolver.NonConflictAware)resolver).handleNonConflict(lastUpdateTime); + } + } - int resolved = 0; + return; + } - try - { - Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> remaining = new HashMap<CDOObject, Pair<CDORevision, CDORevisionDelta>>( - conflicts); - for (CDOConflictResolver resolver : resolvers) - { - if (resolver instanceof CDOConflictResolver2) + // Remember original state to be able to restore it after an exception + List<CDOState> states = new ArrayList<CDOState>(conflicts.size()); + List<CDORevision> revisions = new ArrayList<CDORevision>(conflicts.size()); + for (CDOObject conflict : conflicts.keySet()) { - ((CDOConflictResolver2)resolver).resolveConflicts(Collections.unmodifiableMap(remaining), deltas); + states.add(conflict.cdoState()); + revisions.add(conflict.cdoRevision()); } - else + + int resolved = 0; + + try { - resolver.resolveConflicts(Collections.unmodifiableSet(remaining.keySet())); - } + Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> remaining = new HashMap<CDOObject, Pair<CDORevision, CDORevisionDelta>>( + conflicts); + for (CDOConflictResolver resolver : resolvers) + { + if (resolver instanceof CDOConflictResolver2) + { + ((CDOConflictResolver2)resolver).resolveConflicts(Collections.unmodifiableMap(remaining), deltas); + } + else + { + resolver.resolveConflicts(Collections.unmodifiableSet(remaining.keySet())); + } - for (Iterator<CDOObject> it = remaining.keySet().iterator(); it.hasNext();) + for (Iterator<CDOObject> it = remaining.keySet().iterator(); it.hasNext();) + { + CDOObject object = it.next(); + if (!object.cdoConflict()) + { + ++resolved; + it.remove(); + } + } + } + } + catch (Exception ex) { - CDOObject object = it.next(); - if (!object.cdoConflict()) + // Restore original state + Iterator<CDOState> state = states.iterator(); + Iterator<CDORevision> revision = revisions.iterator(); + for (CDOObject object : conflicts.keySet()) { - ++resolved; - it.remove(); + ((InternalCDOObject)object).cdoInternalSetRevision(revision.next()); + ((InternalCDOObject)object).cdoInternalSetState(state.next()); } + + throw WrappedException.wrap(ex); } + + conflict -= resolved; + + Map<CDOID, CDOObject> dirtyObjects = getDirtyObjects(); + setDirty(!dirtyObjects.isEmpty()); } - } - catch (Exception ex) - { - // Restore original state - Iterator<CDOState> state = states.iterator(); - Iterator<CDORevision> revision = revisions.iterator(); - for (CDOObject object : conflicts.keySet()) + finally { - ((InternalCDOObject)object).cdoInternalSetRevision(revision.next()); - ((InternalCDOObject)object).cdoInternalSetState(state.next()); + unlockView(); } - - throw WrappedException.wrap(ex); } - - conflict -= resolved; - - Map<CDOID, CDOObject> dirtyObjects = getDirtyObjects(); - setDirty(!dirtyObjects.isEmpty()); } /** * @deprecated {@link #createIDForNewObject(EObject object)} is called since 4.1. */ @Deprecated - public synchronized CDOIDTemp getNextTemporaryID() + public CDOIDTemp getNextTemporaryID() { throw new UnsupportedOperationException(); } @@ -845,145 +935,228 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return idGenerator.generateCDOID(object); } - public synchronized CDOResourceFolder createResourceFolder(String path) + public CDOResourceFolder createResourceFolder(String path) { - if (path.endsWith(CDOURIUtil.SEGMENT_SEPARATOR)) + synchronized (getViewMonitor()) { - path = path.substring(0, path.length() - 1); - } + lockView(); - CDOResourceFolder folder = EresourceFactory.eINSTANCE.createCDOResourceFolder(); - int pos = path.lastIndexOf(CDOURIUtil.SEGMENT_SEPARATOR_CHAR); - if (pos <= 0) - { - String name = path.substring(pos == 0 ? 1 : 0); - folder.setName(name); + try + { + if (path.endsWith(CDOURIUtil.SEGMENT_SEPARATOR)) + { + path = path.substring(0, path.length() - 1); + } - getRootResource().getContents().add(folder); - } - else - { - String name = path.substring(pos + 1); - folder.setName(name); + CDOResourceFolder folder = EresourceFactory.eINSTANCE.createCDOResourceFolder(); + int pos = path.lastIndexOf(CDOURIUtil.SEGMENT_SEPARATOR_CHAR); + if (pos <= 0) + { + String name = path.substring(pos == 0 ? 1 : 0); + folder.setName(name); - path = path.substring(0, pos); - CDOResourceNode parent = null; + getRootResource().getContents().add(folder); + } + else + { + String name = path.substring(pos + 1); + folder.setName(name); - try - { - parent = getResourceNode(path); + path = path.substring(0, pos); + CDOResourceNode parent = null; + + try + { + parent = getResourceNode(path); + } + catch (Exception ex) + { + parent = createResourceFolder(path); + } + + if (parent instanceof CDOResourceFolder) + { + ((CDOResourceFolder)parent).getNodes().add(folder); + } + else + { + throw new CDOException("Parent is not a folder: " + parent); + } + } + + return folder; } - catch (Exception ex) + finally { - parent = createResourceFolder(path); + unlockView(); } + } + } + + public CDOResource createResource(String path) + { + checkActive(); + synchronized (getViewMonitor()) + { + lockView(); - if (parent instanceof CDOResourceFolder) + try { - ((CDOResourceFolder)parent).getNodes().add(folder); + URI uri = CDOURIUtil.createResourceURI(this, path); + return (CDOResource)getResourceSet().createResource(uri); } - else + finally { - throw new CDOException("Parent is not a folder: " + parent); + unlockView(); } } - - return folder; } - public synchronized CDOResource createResource(String path) + public CDOResource getOrCreateResource(String path) { checkActive(); - URI uri = CDOURIUtil.createResourceURI(this, path); - return (CDOResource)getResourceSet().createResource(uri); - } + synchronized (getViewMonitor()) + { + lockView(); - public synchronized CDOResource getOrCreateResource(String path) - { - checkActive(); + try + { + try + { + CDOID id = getResourceNodeID(path); + if (!CDOIDUtil.isNull(id)) + { + return (CDOResource)getObject(id); + } + } + catch (TransactionException e) + { + // A TimeoutException or another exception due to client/server communication issue does not allow to know if + // resource exists + throw e; + } + catch (CDOException ignore) + { + // Just create the missing resource + } - try - { - CDOID id = getResourceNodeID(path); - if (!CDOIDUtil.isNull(id)) + return createResource(path); + } + finally { - return (CDOResource)getObject(id); + unlockView(); } } - catch (TransactionException e) - { - // A TimeoutException or another exception due to client/server communication issue does not allow to know if - // resource exists - throw e; - } - catch (CDOException ignore) - { - // Just create the missing resource - } - - return createResource(path); } - public synchronized CDOTextResource createTextResource(String path) + public CDOTextResource createTextResource(String path) { - CDOTextResource resource = EresourceFactory.eINSTANCE.createCDOTextResource(); - createFileResource(path, resource); - return resource; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOTextResource resource = EresourceFactory.eINSTANCE.createCDOTextResource(); + createFileResource(path, resource); + return resource; + } + finally + { + unlockView(); + } + } } - public synchronized CDOTextResource getOrCreateTextResource(String path) + public CDOTextResource getOrCreateTextResource(String path) { - try + synchronized (getViewMonitor()) { - CDOID id = getResourceNodeID(path); - if (!CDOIDUtil.isNull(id)) + lockView(); + + try + { + try + { + CDOID id = getResourceNodeID(path); + if (!CDOIDUtil.isNull(id)) + { + return (CDOTextResource)getObject(id); + } + } + catch (TransactionException e) + { + // A TimeoutException or another exception due to client/server communication issue does not allow to know if + // resource exists + throw e; + } + catch (CDOException ignore) + { + // Just create the missing resource + } + + return createTextResource(path); + } + finally { - return (CDOTextResource)getObject(id); + unlockView(); } } - catch (TransactionException e) - { - // A TimeoutException or another exception due to client/server communication issue does not allow to know if - // resource exists - throw e; - } - catch (CDOException ignore) - { - // Just create the missing resource - } - - return createTextResource(path); } - public synchronized CDOBinaryResource createBinaryResource(String path) + public CDOBinaryResource createBinaryResource(String path) { - CDOBinaryResource resource = EresourceFactory.eINSTANCE.createCDOBinaryResource(); - createFileResource(path, resource); - return resource; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOBinaryResource resource = EresourceFactory.eINSTANCE.createCDOBinaryResource(); + createFileResource(path, resource); + return resource; + } + finally + { + unlockView(); + } + } } - public synchronized CDOBinaryResource getOrCreateBinaryResource(String path) + public CDOBinaryResource getOrCreateBinaryResource(String path) { - try + synchronized (getViewMonitor()) { - CDOID id = getResourceNodeID(path); - if (!CDOIDUtil.isNull(id)) + lockView(); + + try + { + try + { + CDOID id = getResourceNodeID(path); + if (!CDOIDUtil.isNull(id)) + { + return (CDOBinaryResource)getObject(id); + } + } + catch (TransactionException e) + { + // A TimeoutException or another exception due to client/server communication issue does not allow to know if + // resource exists + throw e; + } + catch (CDOException ignore) + { + // Just create the missing resource + } + + return createBinaryResource(path); + } + finally { - return (CDOBinaryResource)getObject(id); + unlockView(); } } - catch (TransactionException e) - { - // A TimeoutException or another exception due to client/server communication issue does not allow to know if - // resource exists - throw e; - } - catch (CDOException ignore) - { - // Just create the missing resource - } - - return createBinaryResource(path); } private void createFileResource(String path, CDOFileResource<?> resource) @@ -1007,16 +1180,28 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa * @since 2.0 */ @Override - public synchronized void attachResource(CDOResourceImpl resource) + public void attachResource(CDOResourceImpl resource) { - if (resource.isExisting()) + synchronized (getViewMonitor()) { - super.attachResource(resource); - } - else - { - // ResourceSet.createResource(uri) was called!! - attachNewResource(resource); + lockView(); + + try + { + if (resource.isExisting()) + { + super.attachResource(resource); + } + else + { + // ResourceSet.createResource(uri) was called!! + attachNewResource(resource); + } + } + finally + { + unlockView(); + } } } @@ -1030,65 +1215,88 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa attachNewResourceNode(folder, resourceName, resource); } - public synchronized CDOResourceFolder getOrCreateResourceFolder(String path) + public CDOResourceFolder getOrCreateResourceFolder(String path) { checkActive(); - - try + synchronized (getViewMonitor()) { - CDOID id = getResourceNodeID(path); - if (!CDOIDUtil.isNull(id)) + lockView(); + + try + { + try + { + CDOID id = getResourceNodeID(path); + if (!CDOIDUtil.isNull(id)) + { + return (CDOResourceFolder)getObject(id); + } + } + catch (TransactionException e) + { + // A TimeoutException or another exception due to client/server communication issue does not allow to know if + // resource exists + throw e; + } + catch (CDOException ignore) + { + // Just create the missing resource + } + + return createResourceFolder(path); + } + finally { - return (CDOResourceFolder)getObject(id); + unlockView(); } } - catch (TransactionException e) - { - // A TimeoutException or another exception due to client/server communication issue does not allow to know if - // resource exists - throw e; - } - catch (CDOException ignore) - { - // Just create the missing resource - } - - return createResourceFolder(path); } /** * @return never <code>null</code>; * @since 2.0 */ - public synchronized CDOResourceFolder getOrCreateResourceFolder(List<String> names) + public CDOResourceFolder getOrCreateResourceFolder(List<String> names) { - CDOResourceFolder folder = null; - for (String name : names) + synchronized (getViewMonitor()) { - CDOResourceNode node; + lockView(); try { - CDOID folderID = folder == null ? null : folder.cdoID(); - node = getResourceNode(folderID, name); - } - catch (CDOException ex) - { - node = EresourceFactory.eINSTANCE.createCDOResourceFolder(); - attachNewResourceNode(folder, name, node); - } + CDOResourceFolder folder = null; + for (String name : names) + { + CDOResourceNode node; - if (node instanceof CDOResourceFolder) - { - folder = (CDOResourceFolder)node; + try + { + CDOID folderID = folder == null ? null : folder.cdoID(); + node = getResourceNode(folderID, name); + } + catch (CDOException ex) + { + node = EresourceFactory.eINSTANCE.createCDOResourceFolder(); + attachNewResourceNode(folder, name, node); + } + + if (node instanceof CDOResourceFolder) + { + folder = (CDOResourceFolder)node; + } + else + { + throw new CDOException(MessageFormat.format(Messages.getString("CDOTransactionImpl.0"), node)); //$NON-NLS-1$ + } + } + + return folder; } - else + finally { - throw new CDOException(MessageFormat.format(Messages.getString("CDOTransactionImpl.0"), node)); //$NON-NLS-1$ + unlockView(); } } - - return folder; } private void attachNewResourceNode(CDOResourceFolder folder, String name, CDOResourceNode newNode) @@ -1115,9 +1323,21 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized void detach(CDOResourceImpl cdoResource) + public void detach(CDOResourceImpl cdoResource) { - CDOStateMachine.INSTANCE.detach(cdoResource); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOStateMachine.INSTANCE.detach(cdoResource); + } + finally + { + unlockView(); + } + } } /** @@ -1131,7 +1351,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized InternalCDOSavepoint getLastSavepoint() + public InternalCDOSavepoint getLastSavepoint() { checkActive(); return lastSavepoint; @@ -1140,32 +1360,56 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized CDOTransactionStrategy getTransactionStrategy() + public CDOTransactionStrategy getTransactionStrategy() { - if (transactionStrategy == null) + synchronized (getViewMonitor()) { - transactionStrategy = CDOTransactionStrategy.DEFAULT; - transactionStrategy.setTarget(this); - } + lockView(); + + try + { + if (transactionStrategy == null) + { + transactionStrategy = CDOTransactionStrategy.DEFAULT; + transactionStrategy.setTarget(this); + } - return transactionStrategy; + return transactionStrategy; + } + finally + { + unlockView(); + } + } } /** * @since 2.0 */ - public synchronized void setTransactionStrategy(CDOTransactionStrategy transactionStrategy) + public void setTransactionStrategy(CDOTransactionStrategy transactionStrategy) { - if (this.transactionStrategy != null) + synchronized (getViewMonitor()) { - this.transactionStrategy.unsetTarget(this); - } + lockView(); - this.transactionStrategy = transactionStrategy; + try + { + if (this.transactionStrategy != null) + { + this.transactionStrategy.unsetTarget(this); + } - if (this.transactionStrategy != null) - { - this.transactionStrategy.setTarget(this); + this.transactionStrategy = transactionStrategy; + + if (this.transactionStrategy != null) + { + this.transactionStrategy.setTarget(this); + } + } + finally + { + unlockView(); + } } } @@ -1173,30 +1417,42 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa * @since 2.0 */ @Override - protected synchronized CDOID getRootOrTopLevelResourceNodeID(String name) + protected CDOID getRootOrTopLevelResourceNodeID(String name) { - if (dirty) + synchronized (getViewMonitor()) { - CDOResourceNode node = getRootResourceNode(name, getDirtyObjects().values()); - if (node != null) + lockView(); + + try { - return node.cdoID(); - } + if (dirty) + { + CDOResourceNode node = getRootResourceNode(name, getDirtyObjects().values()); + if (node != null) + { + return node.cdoID(); + } + + node = getRootResourceNode(name, getNewObjects().values()); + if (node != null) + { + return node.cdoID(); + } + } + + CDOID id = super.getRootOrTopLevelResourceNodeID(name); + if (getLastSavepoint().getAllDetachedObjects().containsKey(id) || getDirtyObjects().containsKey(id)) + { + throw new CDOException(MessageFormat.format(Messages.getString("CDOTransactionImpl.1"), name)); //$NON-NLS-1$ + } - node = getRootResourceNode(name, getNewObjects().values()); - if (node != null) + return id; + } + finally { - return node.cdoID(); + unlockView(); } } - - CDOID id = super.getRootOrTopLevelResourceNodeID(name); - if (getLastSavepoint().getAllDetachedObjects().containsKey(id) || getDirtyObjects().containsKey(id)) - { - throw new CDOException(MessageFormat.format(Messages.getString("CDOTransactionImpl.1"), name)); //$NON-NLS-1$ - } - - return id; } private CDOResourceNode getRootResourceNode(String name, Collection<? extends CDOObject> objects) @@ -1220,20 +1476,32 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa * @since 2.0 */ @Override - public synchronized InternalCDOObject getObject(CDOID id, boolean loadOnDemand) + public InternalCDOObject getObject(CDOID id, boolean loadOnDemand) { checkActive(); - if (CDOIDUtil.isNull(id)) + synchronized (getViewMonitor()) { - return null; - } + lockView(); - if (isObjectNew(id) && isObjectDetached(id)) - { - throw new ObjectNotFoundException(id, this); - } + try + { + if (CDOIDUtil.isNull(id)) + { + return null; + } + + if (isObjectNew(id) && isObjectDetached(id)) + { + throw new ObjectNotFoundException(id, this); + } - return super.getObject(id, loadOnDemand); + return super.getObject(id, loadOnDemand); + } + finally + { + unlockView(); + } + } } @Override @@ -1250,12 +1518,24 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized InternalCDOCommitContext createCommitContext() + public InternalCDOCommitContext createCommitContext() { - return new CDOCommitContextImpl(this); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return new CDOCommitContextImpl(this); + } + finally + { + unlockView(); + } + } } - public/* synchronized */CDOCommitInfo commit() throws CommitException + public CDOCommitInfo commit() throws CommitException { return commit(null); } @@ -1263,7 +1543,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public/* synchronized */CDOCommitInfo commit(IProgressMonitor progressMonitor) throws CommitException + public CDOCommitInfo commit(IProgressMonitor progressMonitor) throws CommitException { CDOConflictResolver[] conflictResolvers = options().getConflictResolvers(); if (conflictResolvers.length != 0) @@ -1305,79 +1585,93 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return info; } - private synchronized CDOCommitInfo commitSynced(IProgressMonitor progressMonitor) + private CDOCommitInfo commitSynced(IProgressMonitor progressMonitor) throws DanglingIntegrityException, CommitException { - InternalCDOSession session = getSession(); - - try + synchronized (getViewMonitor()) { - checkActive(); - if (hasConflict()) - { - throw new LocalCommitConflictException(Messages.getString("CDOTransactionImpl.2")); //$NON-NLS-1$ - } - - commitToken = (CommitToken)session.startLocalCommit(); + lockView(); - CDOTransactionStrategy transactionStrategy = getTransactionStrategy(); - CDOCommitInfo info = transactionStrategy.commit(this, progressMonitor); - if (info != null) - { - lastCommitTime = info.getTimeStamp(); - } - - return info; - } - catch (DanglingReferenceException ex) - { - throw new DanglingIntegrityException(ex); - } - catch (CommitException ex) - { - throw ex; - } - catch (Throwable t) - { try { - // The commit may have succeeded on the server, but after that fact network problems or timeouts have hit us. - // Let's see if we can recover... - CDOCommitInfo info = session.getSessionProtocol().resetTransaction(getViewID(), commitToken.getCommitNumber()); - if (info != null) + InternalCDOSession session = getSession(); + + try { - lastCommitTime = info.getTimeStamp(); - session.invalidate(info, this, true, CDOProtocol.CommitNotificationInfo.IMPACT_NONE, null); + checkActive(); + if (hasConflict()) + { + throw new LocalCommitConflictException(Messages.getString("CDOTransactionImpl.2")); //$NON-NLS-1$ + } + + commitToken = (CommitToken)session.startLocalCommit(); - // At this point the session (invalidator) is recovered. - // Continue to rethrow the exception and let the client call rollback()... + CDOTransactionStrategy transactionStrategy = getTransactionStrategy(); + CDOCommitInfo info = transactionStrategy.commit(this, progressMonitor); + if (info != null) + { + lastCommitTime = info.getTimeStamp(); + } + + return info; } - } - catch (Throwable ex) - { - if (TRACER.isEnabled()) + catch (DanglingReferenceException ex) { - TRACER.trace(ex); + throw new DanglingIntegrityException(ex); } - } - - Throwable cause = t.getCause(); - if (cause instanceof MonitorCanceledException) - { - if (!(cause.getCause() instanceof TimeoutRuntimeException)) + catch (CommitException ex) { - throw new OperationCanceledException("CDOTransactionImpl.7");//$NON-NLS-1$ + throw ex; } - } + catch (Throwable t) + { + try + { + // The commit may have succeeded on the server, but after that fact network problems or timeouts have hit + // us. + // Let's see if we can recover... + CDOCommitInfo info = session.getSessionProtocol().resetTransaction(getViewID(), + commitToken.getCommitNumber()); + if (info != null) + { + lastCommitTime = info.getTimeStamp(); + session.invalidate(info, this, true, CDOProtocol.CommitNotificationInfo.IMPACT_NONE, null); - throw new CommitException(t); - } - finally - { - session.endLocalCommit(commitToken); - commitToken = null; + // At this point the session (invalidator) is recovered. + // Continue to rethrow the exception and let the client call rollback()... + } + } + catch (Throwable ex) + { + if (TRACER.isEnabled()) + { + TRACER.trace(ex); + } + } + + Throwable cause = t.getCause(); + if (cause instanceof MonitorCanceledException) + { + if (!(cause.getCause() instanceof TimeoutRuntimeException)) + { + throw new OperationCanceledException("CDOTransactionImpl.7");//$NON-NLS-1$ + } + } - clearResourcePathCacheIfNecessary(null); + throw new CommitException(t); + } + finally + { + session.endLocalCommit(commitToken); + commitToken = null; + + clearResourcePathCacheIfNecessary(null); + } + } + finally + { + unlockView(); + } } } @@ -1389,14 +1683,25 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized void rollback() + public void rollback() { checkActive(); + synchronized (getViewMonitor()) + { + lockView(); - CDOTransactionStrategy strategy = getTransactionStrategy(); - strategy.rollback(this, firstSavepoint); + try + { + CDOTransactionStrategy strategy = getTransactionStrategy(); + strategy.rollback(this, firstSavepoint); - cleanUp(null); + cleanUp(null); + } + finally + { + unlockView(); + } + } } private void removeObject(CDOID id, final CDOObject object) @@ -1641,53 +1946,65 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized void detachObject(InternalCDOObject object) + public void detachObject(InternalCDOObject object) { - CDOTransactionHandler1[] handlers = getTransactionHandlers1(); - for (int i = 0; i < handlers.length; i++) - { - CDOTransactionHandler1 handler = handlers[i]; - handler.detachingObject(this, object); - } - - // deregister object - CDOID id = object.cdoID(); - if (object.cdoState() == CDOState.NEW) + synchronized (getViewMonitor()) { - Map<CDOID, CDOObject> map = lastSavepoint.getNewObjects(); + lockView(); - // Determine if we added object - if (map.containsKey(id)) - { - map.remove(id); - } - else + try { - lastSavepoint.getDetachedObjects().put(id, object); - } + CDOTransactionHandler1[] handlers = getTransactionHandlers1(); + for (int i = 0; i < handlers.length; i++) + { + CDOTransactionHandler1 handler = handlers[i]; + handler.detachingObject(this, object); + } - // deregister object - deregisterObject(object); - } - else - { - if (!cleanRevisions.containsKey(object)) - { - cleanRevisions.put(object, object.cdoRevision()); - } + // deregister object + CDOID id = object.cdoID(); + if (object.cdoState() == CDOState.NEW) + { + Map<CDOID, CDOObject> map = lastSavepoint.getNewObjects(); + + // Determine if we added object + if (map.containsKey(id)) + { + map.remove(id); + } + else + { + lastSavepoint.getDetachedObjects().put(id, object); + } + + // deregister object + deregisterObject(object); + } + else + { + if (!cleanRevisions.containsKey(object)) + { + cleanRevisions.put(object, object.cdoRevision()); + } - lastSavepoint.getDetachedObjects().put(id, object); + lastSavepoint.getDetachedObjects().put(id, object); - // Object may have been reattached previously, in which case it must - // here be removed from the collection of reattached objects - lastSavepoint.getReattachedObjects().remove(id); + // Object may have been reattached previously, in which case it must + // here be removed from the collection of reattached objects + lastSavepoint.getReattachedObjects().remove(id); + } + } + finally + { + unlockView(); + } } } /** * @since 2.0 */ - public synchronized void handleRollback(InternalCDOSavepoint savepoint) + public void handleRollback(InternalCDOSavepoint savepoint) { if (savepoint == null) { @@ -1709,114 +2026,135 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa TRACER.trace("handleRollback()"); //$NON-NLS-1$ } - try + synchronized (getViewMonitor()) { - // Remember current revisions - Map<CDOObject, CDORevision> oldRevisions = new HashMap<CDOObject, CDORevision>(); - for (CDOObject object : getDirtyObjects().values()) + lockView(); + + try { - CDORevision oldRevision = object.cdoRevision(); - if (oldRevision != null) + // Remember current revisions + Map<CDOObject, CDORevision> oldRevisions = new HashMap<CDOObject, CDORevision>(); + for (CDOObject object : getDirtyObjects().values()) { - oldRevisions.put(object, oldRevision); + CDORevision oldRevision = object.cdoRevision(); + if (oldRevision != null) + { + oldRevisions.put(object, oldRevision); + } } - } - // Rollback objects - Set<CDOID> idsOfNewObjectWithDeltas = rollbackCompletely(savepoint); + // Rollback objects + Set<CDOID> idsOfNewObjectWithDeltas = rollbackCompletely(savepoint); - lastSavepoint = savepoint; - lastSavepoint.setNextSavepoint(null); - lastSavepoint.clear(); + lastSavepoint = savepoint; + lastSavepoint.setNextSavepoint(null); + lastSavepoint.clear(); - // Load from first savepoint up to current savepoint - loadSavepoint(lastSavepoint, idsOfNewObjectWithDeltas); + // Load from first savepoint up to current savepoint + loadSavepoint(lastSavepoint, idsOfNewObjectWithDeltas); - if (lastSavepoint == firstSavepoint && options().isAutoReleaseLocksEnabled()) - { - CDORepositoryInfo repositoryInfo = getSession().getRepositoryInfo(); - if (isDurableView() && repositoryInfo.getState() == CDOCommonRepository.State.ONLINE - || repositoryInfo.getType() == CDOCommonRepository.Type.MASTER) + if (lastSavepoint == firstSavepoint && options().isAutoReleaseLocksEnabled()) { - // Unlock all objects - unlockObjects(null, null); + CDORepositoryInfo repositoryInfo = getSession().getRepositoryInfo(); + if (isDurableView() && repositoryInfo.getState() == CDOCommonRepository.State.ONLINE + || repositoryInfo.getType() == CDOCommonRepository.Type.MASTER) + { + // Unlock all objects + unlockObjects(null, null); + } } - } - // Send notifications - for (Entry<CDOObject, CDORevision> entry : oldRevisions.entrySet()) - { - InternalCDOObject object = (InternalCDOObject)entry.getKey(); - if (FSMUtil.isTransient(object)) + // Send notifications + for (Entry<CDOObject, CDORevision> entry : oldRevisions.entrySet()) { - continue; + InternalCDOObject object = (InternalCDOObject)entry.getKey(); + if (FSMUtil.isTransient(object)) + { + continue; + } + + InternalCDORevision oldRevision = (InternalCDORevision)entry.getValue(); + InternalCDORevision newRevision = object.cdoRevision(); + if (newRevision == null) + { + newRevision = getRevision(oldRevision.getID(), true); + object.cdoInternalSetRevision(newRevision); + object.cdoInternalSetState(CDOState.CLEAN); + } + + if (newRevision != null) + { + InternalCDORevisionDelta delta = newRevision.compare(oldRevision); + if (!delta.isEmpty()) + { + Set<CDOObject> detachedObjects = Collections.emptySet(); + + CDONotificationBuilder builder = new CDONotificationBuilder(this); + NotificationChain notification = builder.buildNotification(object, oldRevision, delta, detachedObjects); + if (notification != null) + { + notification.dispatch(); + } + } + } } - InternalCDORevision oldRevision = (InternalCDORevision)entry.getValue(); - InternalCDORevision newRevision = object.cdoRevision(); - if (newRevision == null) + IListener[] listeners = getListeners(); + if (listeners != null) { - newRevision = getRevision(oldRevision.getID(), true); - object.cdoInternalSetRevision(newRevision); - object.cdoInternalSetState(CDOState.CLEAN); + fireEvent(new FinishedEvent(true), listeners); } - if (newRevision != null) + CDOTransactionHandler2[] handlers = getTransactionHandlers2(); + for (int i = 0; i < handlers.length; i++) { - InternalCDORevisionDelta delta = newRevision.compare(oldRevision); - if (!delta.isEmpty()) - { - Set<CDOObject> detachedObjects = Collections.emptySet(); + CDOTransactionHandler2 handler = handlers[i]; - CDONotificationBuilder builder = new CDONotificationBuilder(this); - NotificationChain notification = builder.buildNotification(object, oldRevision, delta, detachedObjects); - if (notification != null) - { - notification.dispatch(); - } + try + { + handler.rolledBackTransaction(this); + } + catch (RuntimeException ex) + { + OM.LOG.error(ex); } } } - - IListener[] listeners = getListeners(); - if (listeners != null) + catch (RuntimeException ex) { - fireEvent(new FinishedEvent(true), listeners); + throw ex; } - - CDOTransactionHandler2[] handlers = getTransactionHandlers2(); - for (int i = 0; i < handlers.length; i++) + catch (Exception ex) { - CDOTransactionHandler2 handler = handlers[i]; - - try - { - handler.rolledBackTransaction(this); - } - catch (RuntimeException ex) - { - OM.LOG.error(ex); - } + throw new TransactionException(ex); + } + finally + { + unlockView(); } - } - catch (RuntimeException ex) - { - throw ex; - } - catch (Exception ex) - { - throw new TransactionException(ex); } } /** * @since 2.0 */ - public synchronized InternalCDOSavepoint handleSetSavepoint() + public InternalCDOSavepoint handleSetSavepoint() { - addToBase(lastSavepoint.getNewObjects()); - lastSavepoint = createSavepoint(lastSavepoint); - return lastSavepoint; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + addToBase(lastSavepoint.getNewObjects()); + lastSavepoint = createSavepoint(lastSavepoint); + return lastSavepoint; + } + finally + { + unlockView(); + } + } } private CDOSavepointImpl createSavepoint(InternalCDOSavepoint lastSavepoint) @@ -1827,10 +2165,22 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @since 2.0 */ - public synchronized InternalCDOSavepoint setSavepoint() + public InternalCDOSavepoint setSavepoint() { checkActive(); - return (InternalCDOSavepoint)getTransactionStrategy().setSavepoint(this); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return (InternalCDOSavepoint)getTransactionStrategy().setSavepoint(this); + } + finally + { + unlockView(); + } + } } public boolean hasMultipleSavepoints() @@ -1854,28 +2204,40 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return "CDOTransaction"; //$NON-NLS-1$ } - public synchronized void registerAttached(InternalCDOObject object, boolean isNew) + public void registerAttached(InternalCDOObject object, boolean isNew) { if (TRACER.isEnabled()) { TRACER.format("Registering new object {0}", object); //$NON-NLS-1$ } - if (isNew) + synchronized (getViewMonitor()) { - registerNewPackage(object.eClass().getEPackage()); - } + lockView(); - CDOTransactionHandler1[] handlers = getTransactionHandlers1(); - for (int i = 0; i < handlers.length; i++) - { - CDOTransactionHandler1 handler = handlers[i]; - handler.attachingObject(this, object); - } + try + { + if (isNew) + { + registerNewPackage(object.eClass().getEPackage()); + } - if (isNew) - { - registerNew(lastSavepoint.getNewObjects(), object); + CDOTransactionHandler1[] handlers = getTransactionHandlers1(); + for (int i = 0; i < handlers.length; i++) + { + CDOTransactionHandler1 handler = handlers[i]; + handler.attachingObject(this, object); + } + + if (isNew) + { + registerNew(lastSavepoint.getNewObjects(), object); + } + } + finally + { + unlockView(); + } } } @@ -1921,62 +2283,98 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * Receives notification for new and dirty objects */ - public synchronized void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta) + public void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta) { - registerFeatureDelta(object, featureDelta, null); - } - - public synchronized void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta, - InternalCDORevision cleanRevision) - { - CDOID id = object.cdoID(); - boolean needToSaveFeatureDelta = true; - - if (object.cdoState() == CDOState.NEW) + synchronized (getViewMonitor()) { - // Register Delta for new objects only if objectA doesn't belong to this savepoint - if (getLastSavepoint().getPreviousSavepoint() == null || featureDelta == null) + lockView(); + + try { - needToSaveFeatureDelta = false; + registerFeatureDelta(object, featureDelta, null); } - else + finally { - Map<CDOID, CDOObject> map = getLastSavepoint().getNewObjects(); - needToSaveFeatureDelta = !map.containsKey(id); + unlockView(); } } + } - if (needToSaveFeatureDelta) + public void registerFeatureDelta(InternalCDOObject object, CDOFeatureDelta featureDelta, + InternalCDORevision cleanRevision) + { + synchronized (getViewMonitor()) { - Map<CDOID, CDORevisionDelta> revisionDeltas = lastSavepoint.getRevisionDeltas2(); - InternalCDORevisionDelta revisionDelta = (InternalCDORevisionDelta)revisionDeltas.get(id); - if (revisionDelta == null) + lockView(); + + try { - InternalCDORevision revision = object.cdoRevision(); + CDOID id = object.cdoID(); + boolean needToSaveFeatureDelta = true; - revisionDelta = (InternalCDORevisionDelta)CDORevisionUtil.createDelta(revision); - revisionDeltas.put(id, revisionDelta); - } + if (object.cdoState() == CDOState.NEW) + { + // Register Delta for new objects only if objectA doesn't belong to this savepoint + if (getLastSavepoint().getPreviousSavepoint() == null || featureDelta == null) + { + needToSaveFeatureDelta = false; + } + else + { + Map<CDOID, CDOObject> map = getLastSavepoint().getNewObjects(); + needToSaveFeatureDelta = !map.containsKey(id); + } + } - CDOOriginSizeProvider originSizeProvider = getOriginSizeProvider(object, featureDelta, cleanRevision); - revisionDelta.addFeatureDelta(featureDelta, originSizeProvider); - } + if (needToSaveFeatureDelta) + { + Map<CDOID, CDORevisionDelta> revisionDeltas = lastSavepoint.getRevisionDeltas2(); + InternalCDORevisionDelta revisionDelta = (InternalCDORevisionDelta)revisionDeltas.get(id); + if (revisionDelta == null) + { + InternalCDORevision revision = object.cdoRevision(); - CDOTransactionHandler1[] handlers = getTransactionHandlers1(); - for (int i = 0; i < handlers.length; i++) - { - CDOTransactionHandler1 handler = handlers[i]; - handler.modifyingObject(this, object, featureDelta); + revisionDelta = (InternalCDORevisionDelta)CDORevisionUtil.createDelta(revision); + revisionDeltas.put(id, revisionDelta); + } + + CDOOriginSizeProvider originSizeProvider = getOriginSizeProvider(object, featureDelta, cleanRevision); + revisionDelta.addFeatureDelta(featureDelta, originSizeProvider); + } + + CDOTransactionHandler1[] handlers = getTransactionHandlers1(); + for (int i = 0; i < handlers.length; i++) + { + CDOTransactionHandler1 handler = handlers[i]; + handler.modifyingObject(this, object, featureDelta); + } + } + finally + { + unlockView(); + } } } - public synchronized void registerRevisionDelta(CDORevisionDelta revisionDelta) + public void registerRevisionDelta(CDORevisionDelta revisionDelta) { - Map<CDOID, CDORevisionDelta> revisionDeltas = lastSavepoint.getRevisionDeltas2(); - CDOID id = revisionDelta.getID(); - if (!revisionDeltas.containsKey(id)) + synchronized (getViewMonitor()) { - revisionDeltas.put(id, revisionDelta); + lockView(); + + try + { + Map<CDOID, CDORevisionDelta> revisionDeltas = lastSavepoint.getRevisionDeltas2(); + CDOID id = revisionDelta.getID(); + if (!revisionDeltas.containsKey(id)) + { + revisionDeltas.put(id, revisionDelta); + } + } + finally + { + unlockView(); + } } } @@ -2015,44 +2413,56 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa setDirty(true); } - public synchronized List<CDOPackageUnit> analyzeNewPackages() + public List<CDOPackageUnit> analyzeNewPackages() { - CDOPackageRegistry packageRegistry = getSession().getPackageRegistry(); - Set<EPackage> usedPackages = new HashSet<EPackage>(); - Set<EPackage> usedNewPackages = new HashSet<EPackage>(); - for (CDOObject object : getNewObjects().values()) + synchronized (getViewMonitor()) { - EPackage ePackage = object.eClass().getEPackage(); - if (usedPackages.add(ePackage)) + lockView(); + + try { - EPackage topLevelPackage = EMFUtil.getTopLevelPackage(ePackage); - if (ePackage == topLevelPackage || usedPackages.add(topLevelPackage)) + CDOPackageRegistry packageRegistry = getSession().getPackageRegistry(); + Set<EPackage> usedPackages = new HashSet<EPackage>(); + Set<EPackage> usedNewPackages = new HashSet<EPackage>(); + for (CDOObject object : getNewObjects().values()) { - // if (!CDOModelUtil.isSystemPackage(topLevelPackage)) + EPackage ePackage = object.eClass().getEPackage(); + if (usedPackages.add(ePackage)) { - CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(topLevelPackage); - if (packageUnit.getState() == CDOPackageUnit.State.NEW) + EPackage topLevelPackage = EMFUtil.getTopLevelPackage(ePackage); + if (ePackage == topLevelPackage || usedPackages.add(topLevelPackage)) { - usedNewPackages.add(topLevelPackage); + // if (!CDOModelUtil.isSystemPackage(topLevelPackage)) + { + CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(topLevelPackage); + if (packageUnit.getState() == CDOPackageUnit.State.NEW) + { + usedNewPackages.add(topLevelPackage); + } + } } } } - } - } - if (usedNewPackages.size() > 0) - { - Set<CDOPackageUnit> result = new HashSet<CDOPackageUnit>(); - for (EPackage usedNewPackage : analyzeNewPackages(usedNewPackages, packageRegistry)) + if (usedNewPackages.size() > 0) + { + Set<CDOPackageUnit> result = new HashSet<CDOPackageUnit>(); + for (EPackage usedNewPackage : analyzeNewPackages(usedNewPackages, packageRegistry)) + { + CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(usedNewPackage); + result.add(packageUnit); + } + + return new ArrayList<CDOPackageUnit>(result); + } + + return Collections.emptyList(); + } + finally { - CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(usedNewPackage); - result.add(packageUnit); + unlockView(); } - - return new ArrayList<CDOPackageUnit>(result); } - - return Collections.emptyList(); } private static List<EPackage> analyzeNewPackages(Collection<EPackage> usedTopLevelPackages, @@ -2160,195 +2570,219 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } } - public synchronized CDOSavepoint[] exportChanges(OutputStream stream) throws IOException + public CDOSavepoint[] exportChanges(OutputStream stream) throws IOException { - CDODataOutput out = new CDODataOutputImpl(new ExtendedDataOutputStream(stream)) + synchronized (getViewMonitor()) { - @Override - public CDOIDProvider getIDProvider() - { - return CDOTransactionImpl.this; - } + lockView(); - @Override - public CDOPackageRegistry getPackageRegistry() + try { - return getSession().getPackageRegistry(); - } + CDODataOutput out = new CDODataOutputImpl(new ExtendedDataOutputStream(stream)) + { + @Override + public CDOIDProvider getIDProvider() + { + return CDOTransactionImpl.this; + } - @Override - public CDORevisionUnchunker getRevisionUnchunker() - { - return getSession(); - } - }; + @Override + public CDOPackageRegistry getPackageRegistry() + { + return getSession().getPackageRegistry(); + } - List<CDOSavepoint> savepoints = new ArrayList<CDOSavepoint>(); - int totalNewObjects = 0; + @Override + public CDORevisionUnchunker getRevisionUnchunker() + { + return getSession(); + } + }; - InternalCDOSavepoint savepoint = firstSavepoint; - while (savepoint != null) - { - Collection<CDOObject> newObjects = savepoint.getNewObjects().values(); - totalNewObjects += newObjects.size(); + List<CDOSavepoint> savepoints = new ArrayList<CDOSavepoint>(); + int totalNewObjects = 0; - savepoint = savepoint.getNextSavepoint(); - } + InternalCDOSavepoint savepoint = firstSavepoint; + while (savepoint != null) + { + Collection<CDOObject> newObjects = savepoint.getNewObjects().values(); + totalNewObjects += newObjects.size(); - out.writeInt(totalNewObjects); + savepoint = savepoint.getNextSavepoint(); + } - savepoint = firstSavepoint; - while (savepoint != null) - { - Collection<CDOObject> newObjects = savepoint.getNewObjects().values(); - Collection<CDORevisionDelta> revisionDeltas = savepoint.getRevisionDeltas2().values(); - if (newObjects.isEmpty() && revisionDeltas.isEmpty()) - { - savepoint = savepoint.getNextSavepoint(); - continue; - } + out.writeInt(totalNewObjects); - savepoints.add(savepoint); - out.writeBoolean(true); + savepoint = firstSavepoint; + while (savepoint != null) + { + Collection<CDOObject> newObjects = savepoint.getNewObjects().values(); + Collection<CDORevisionDelta> revisionDeltas = savepoint.getRevisionDeltas2().values(); + if (newObjects.isEmpty() && revisionDeltas.isEmpty()) + { + savepoint = savepoint.getNextSavepoint(); + continue; + } - out.writeInt(newObjects.size()); - for (CDOObject newObject : newObjects) - { - out.writeCDORevision(newObject.cdoRevision(), CDORevision.UNCHUNKED); - } + savepoints.add(savepoint); + out.writeBoolean(true); + + out.writeInt(newObjects.size()); + for (CDOObject newObject : newObjects) + { + out.writeCDORevision(newObject.cdoRevision(), CDORevision.UNCHUNKED); + } + + out.writeInt(revisionDeltas.size()); + for (CDORevisionDelta revisionDelta : revisionDeltas) + { + out.writeCDORevisionDelta(revisionDelta); + } + + savepoint = savepoint.getNextSavepoint(); + } - out.writeInt(revisionDeltas.size()); - for (CDORevisionDelta revisionDelta : revisionDeltas) + out.writeBoolean(false); + return savepoints.toArray(new CDOSavepoint[savepoints.size()]); + } + finally { - out.writeCDORevisionDelta(revisionDelta); + unlockView(); } - - savepoint = savepoint.getNextSavepoint(); } - - out.writeBoolean(false); - return savepoints.toArray(new CDOSavepoint[savepoints.size()]); } - public synchronized CDOSavepoint[] importChanges(InputStream stream, boolean reconstructSavepoints) throws IOException + public CDOSavepoint[] importChanges(InputStream stream, boolean reconstructSavepoints) throws IOException { - List<CDOSavepoint> savepoints = new ArrayList<CDOSavepoint>(); - if (stream.available() > 0) + synchronized (getViewMonitor()) { - CDODataInput in = new CDODataInputImpl(new ExtendedDataInputStream(stream)) - { - public CDOPackageRegistry getPackageRegistry() - { - return getSession().getPackageRegistry(); - } + lockView(); - @Override - protected CDOBranchManager getBranchManager() - { - return getSession().getBranchManager(); - } - - @Override - protected CDOCommitInfoManager getCommitInfoManager() - { - return getSession().getCommitInfoManager(); - } - - @Override - protected CDORevisionFactory getRevisionFactory() + try + { + List<CDOSavepoint> savepoints = new ArrayList<CDOSavepoint>(); + if (stream.available() > 0) { - return getSession().getRevisionManager().getFactory(); - } + CDODataInput in = new CDODataInputImpl(new ExtendedDataInputStream(stream)) + { + public CDOPackageRegistry getPackageRegistry() + { + return getSession().getPackageRegistry(); + } - @Override - protected CDOLobStore getLobStore() - { - return getSession().getLobStore(); - } + @Override + protected CDOBranchManager getBranchManager() + { + return getSession().getBranchManager(); + } - @Override - protected CDOListFactory getListFactory() - { - return CDOListWithElementProxiesImpl.FACTORY; - } - }; + @Override + protected CDOCommitInfoManager getCommitInfoManager() + { + return getSession().getCommitInfoManager(); + } - // Increase the internal tempID counter to prevent ID collisions during mapping - int totalNewObjects = in.readInt(); - for (int i = 0; i < totalNewObjects; i++) - { - createIDForNewObject(null); - } + @Override + protected CDORevisionFactory getRevisionFactory() + { + return getSession().getRevisionManager().getFactory(); + } - Map<CDOID, CDOID> idMappings = CDOIDUtil.createMap(); - while (in.readBoolean()) - { - if (reconstructSavepoints) - { - InternalCDOSavepoint savepoint = setSavepoint(); - savepoints.add(savepoint); - } + @Override + protected CDOLobStore getLobStore() + { + return getSession().getLobStore(); + } - // Import revisions and deltas - List<InternalCDORevision> revisions = new ArrayList<InternalCDORevision>(); - importNewRevisions(in, revisions, idMappings); - List<InternalCDORevisionDelta> revisionDeltas = importRevisionDeltas(in); + @Override + protected CDOListFactory getListFactory() + { + return CDOListWithElementProxiesImpl.FACTORY; + } + }; - if (!idMappings.isEmpty()) - { - // Re-map temp IDs - CDOIDMapper idMapper = new CDOIDMapper(idMappings); - for (InternalCDORevision revision : revisions) + // Increase the internal tempID counter to prevent ID collisions during mapping + int totalNewObjects = in.readInt(); + for (int i = 0; i < totalNewObjects; i++) { - revision.adjustReferences(idMapper); + createIDForNewObject(null); } - for (InternalCDORevisionDelta delta : revisionDeltas) + Map<CDOID, CDOID> idMappings = CDOIDUtil.createMap(); + while (in.readBoolean()) { - delta.adjustReferences(idMapper); - } - } + if (reconstructSavepoints) + { + InternalCDOSavepoint savepoint = setSavepoint(); + savepoints.add(savepoint); + } - if (!revisions.isEmpty()) - { - // Create new objects - List<InternalCDOObject> newObjects = new ArrayList<InternalCDOObject>(); - for (InternalCDORevision revision : revisions) - { - InternalCDOObject object = newInstance(revision); - registerObject(object); - registerAttached(object, true); + // Import revisions and deltas + List<InternalCDORevision> revisions = new ArrayList<InternalCDORevision>(); + importNewRevisions(in, revisions, idMappings); + List<InternalCDORevisionDelta> revisionDeltas = importRevisionDeltas(in); - newObjects.add(object); - } + if (!idMappings.isEmpty()) + { + // Re-map temp IDs + CDOIDMapper idMapper = new CDOIDMapper(idMappings); + for (InternalCDORevision revision : revisions) + { + revision.adjustReferences(idMapper); + } - // Post-load new objects (important for legacy objects!) - for (InternalCDOObject object : newObjects) - { - object.cdoInternalPostLoad(); - } - } + for (InternalCDORevisionDelta delta : revisionDeltas) + { + delta.adjustReferences(idMapper); + } + } - // Apply deltas - CDOObjectMerger merger = new CDOObjectMerger(); - for (InternalCDORevisionDelta delta : revisionDeltas) - { - InternalCDOObject object = getObject(delta.getID()); - int oldVersion = object.cdoRevision().getVersion(); + if (!revisions.isEmpty()) + { + // Create new objects + List<InternalCDOObject> newObjects = new ArrayList<InternalCDOObject>(); + for (InternalCDORevision revision : revisions) + { + InternalCDOObject object = newInstance(revision); + registerObject(object); + registerAttached(object, true); - merger.merge(object, delta); - registerRevisionDelta(delta); - registerDirty(object, null); + newObjects.add(object); + } - if (delta.getVersion() < oldVersion) - { - setConflict(object); + // Post-load new objects (important for legacy objects!) + for (InternalCDOObject object : newObjects) + { + object.cdoInternalPostLoad(); + } + } + + // Apply deltas + CDOObjectMerger merger = new CDOObjectMerger(); + for (InternalCDORevisionDelta delta : revisionDeltas) + { + InternalCDOObject object = getObject(delta.getID()); + int oldVersion = object.cdoRevision().getVersion(); + + merger.merge(object, delta); + registerRevisionDelta(delta); + registerDirty(object, null); + + if (delta.getVersion() < oldVersion) + { + setConflict(object); + } + } } } + + return savepoints.toArray(new CDOSavepoint[savepoints.size()]); + } + finally + { + unlockView(); } } - - return savepoints.toArray(new CDOSavepoint[savepoints.size()]); } private void importNewRevisions(CDODataInput in, List<InternalCDORevision> revisions, Map<CDOID, CDOID> idMappings) @@ -2393,121 +2827,228 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return object; } - public synchronized Map<CDOID, CDOObject> getDirtyObjects() + public Map<CDOID, CDOObject> getDirtyObjects() { checkActive(); - return lastSavepoint.getAllDirtyObjects(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return lastSavepoint.getAllDirtyObjects(); + } + finally + { + unlockView(); + } + } } - public synchronized Map<CDOID, CDOObject> getNewObjects() + public Map<CDOID, CDOObject> getNewObjects() { checkActive(); - return lastSavepoint.getAllNewObjects(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return lastSavepoint.getAllNewObjects(); + } + finally + { + unlockView(); + } + } } /** * @since 2.0 */ - public synchronized Map<CDOID, CDORevision> getBaseNewObjects() + public Map<CDOID, CDORevision> getBaseNewObjects() { checkActive(); - return lastSavepoint.getAllBaseNewObjects(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return lastSavepoint.getAllBaseNewObjects(); + } + finally + { + unlockView(); + } + } } - public synchronized Map<CDOID, CDORevisionDelta> getRevisionDeltas() + public Map<CDOID, CDORevisionDelta> getRevisionDeltas() { checkActive(); - return lastSavepoint.getAllRevisionDeltas(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return lastSavepoint.getAllRevisionDeltas(); + } + finally + { + unlockView(); + } + } } /** * @since 2.0 */ - public synchronized Map<CDOID, CDOObject> getDetachedObjects() + public Map<CDOID, CDOObject> getDetachedObjects() { checkActive(); - return lastSavepoint.getAllDetachedObjects(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return lastSavepoint.getAllDetachedObjects(); + } + finally + { + unlockView(); + } + } } @Override - protected synchronized CDOID getXRefTargetID(CDOObject target) + protected CDOID getXRefTargetID(CDOObject target) { - CDORevisionKey key = cleanRevisions.get(target); - if (key != null) + synchronized (getViewMonitor()) { - return key.getID(); - } + lockView(); + + try + { + CDORevisionKey key = cleanRevisions.get(target); + if (key != null) + { + return key.getID(); + } - return super.getXRefTargetID(target); + return super.getXRefTargetID(target); + } + finally + { + unlockView(); + } + } } @Override - protected synchronized CDOID getID(InternalCDOObject object, boolean onlyPersistedID) + protected CDOID getID(InternalCDOObject object, boolean onlyPersistedID) { - CDOID id = super.getID(object, onlyPersistedID); - - // If super returned a good result, return immediately - if (id != null) + synchronized (getViewMonitor()) { - return id; - } + lockView(); - // Don't perform the trickery that follows later in this method, if we are being called - // indirectly through provideCDOID. This occurs when deltas or revisions are - // being written out to a stream; in which case null must be returned (for transients) so that - // the caller will detect a dangling reference - if (providingCDOID.get()) - { - return null; - } + try + { + CDOID id = super.getID(object, onlyPersistedID); - // The super implementation will return null for a transient (unattached) object; - // but in a tx, an transient object may previously have been attached. So we consult - // the cleanRevisions if that's the case. - CDORevisionKey revKey = cleanRevisions.get(object); - if (revKey != null && getDetachedObjects().containsValue(object)) - { - id = revKey.getID(); - } + // If super returned a good result, return immediately + if (id != null) + { + return id; + } - return id; + // Don't perform the trickery that follows later in this method, if we are being called + // indirectly through provideCDOID. This occurs when deltas or revisions are + // being written out to a stream; in which case null must be returned (for transients) so that + // the caller will detect a dangling reference + if (providingCDOID.get()) + { + return null; + } + + // The super implementation will return null for a transient (unattached) object; + // but in a tx, an transient object may previously have been attached. So we consult + // the cleanRevisions if that's the case. + CDORevisionKey revKey = cleanRevisions.get(object); + if (revKey != null && getDetachedObjects().containsValue(object)) + { + id = revKey.getID(); + } + + return id; + } + finally + { + unlockView(); + } + } } @Override - public synchronized CDOID provideCDOID(Object idOrObject) + public CDOID provideCDOID(Object idOrObject) { - try + synchronized (getViewMonitor()) { - providingCDOID.set(true); - return super.provideCDOID(idOrObject); - } - finally - { - providingCDOID.set(false); + lockView(); + + try + { + try + { + providingCDOID.set(true); + return super.provideCDOID(idOrObject); + } + finally + { + providingCDOID.set(false); + } + } + finally + { + unlockView(); + } } } @Override - public synchronized CDOQueryImpl createQuery(String language, String queryString, Object context) + public CDOQueryImpl createQuery(String language, String queryString, Object context) { return createQuery(language, queryString, context, false); } - public synchronized CDOQueryImpl createQuery(String language, String queryString, boolean considerDirtyState) + public CDOQueryImpl createQuery(String language, String queryString, boolean considerDirtyState) { return createQuery(language, queryString, null, considerDirtyState); } - public synchronized CDOQueryImpl createQuery(String language, String queryString, Object context, - boolean considerDirtyState) + public CDOQueryImpl createQuery(String language, String queryString, Object context, boolean considerDirtyState) { - CDOQueryImpl query = super.createQuery(language, queryString, context); - if (considerDirtyState && isDirty()) + synchronized (getViewMonitor()) { - query.setChangeSetData(getChangeSetData()); - } + lockView(); + + try + { + CDOQueryImpl query = super.createQuery(language, queryString, context); + if (considerDirtyState && isDirty()) + { + query.setChangeSetData(getChangeSetData()); + } - return query; + return query; + } + finally + { + unlockView(); + } + } } @Override @@ -2741,34 +3282,106 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return (EContentsEList.FeatureIterator<EObject>)ECrossReferenceEList.<EObject> emptyContentsEList().iterator(); } - public synchronized long getLastCommitTime() + public long getLastCommitTime() { - return lastCommitTime; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return lastCommitTime; + } + finally + { + unlockView(); + } + } } - public synchronized String getCommitComment() + public String getCommitComment() { - return commitComment; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return commitComment; + } + finally + { + unlockView(); + } + } } - public synchronized void setCommitComment(String comment) + public void setCommitComment(String comment) { - commitComment = comment; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + commitComment = comment; + } + finally + { + unlockView(); + } + } } - public synchronized void setCommittables(Set<? extends EObject> committables) + public void setCommittables(Set<? extends EObject> committables) { - this.committables = committables; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + this.committables = committables; + } + finally + { + unlockView(); + } + } } - public synchronized Set<? extends EObject> getCommittables() + public Set<? extends EObject> getCommittables() { - return committables; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return committables; + } + finally + { + unlockView(); + } + } } - public synchronized Map<InternalCDOObject, InternalCDORevision> getCleanRevisions() + public Map<InternalCDOObject, InternalCDORevision> getCleanRevisions() { - return cleanRevisions; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return cleanRevisions; + } + finally + { + unlockView(); + } + } } @Override @@ -3590,12 +4203,21 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } IEvent event = null; - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - if (this.undoDetector != undoDetector) + lockView(); + + try + { + if (this.undoDetector != undoDetector) + { + this.undoDetector = undoDetector; + event = new UndoDetectorEventImpl(); + } + } + finally { - this.undoDetector = undoDetector; - event = new UndoDetectorEventImpl(); + unlockView(); } } @@ -3610,29 +4232,46 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa public CDOConflictResolver[] getConflictResolvers() { - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - return conflictResolvers.toArray(new CDOConflictResolver[conflictResolvers.size()]); + lockView(); + + try + { + return conflictResolvers.toArray(new CDOConflictResolver[conflictResolvers.size()]); + } + finally + { + unlockView(); + } } } public void setConflictResolvers(CDOConflictResolver[] resolvers) { checkActive(); - - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - for (CDOConflictResolver resolver : conflictResolvers) + lockView(); + + try { - resolver.setTransaction(null); - } + for (CDOConflictResolver resolver : conflictResolvers) + { + resolver.setTransaction(null); + } - conflictResolvers.clear(); + conflictResolvers.clear(); - for (CDOConflictResolver resolver : resolvers) + for (CDOConflictResolver resolver : resolvers) + { + validateResolver(resolver); + conflictResolvers.add(resolver); + } + } + finally { - validateResolver(resolver); - conflictResolvers.add(resolver); + unlockView(); } } @@ -3644,11 +4283,20 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa checkActive(); IEvent event = null; - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - validateResolver(resolver); - conflictResolvers.add(resolver); - event = new ConflictResolversEventImpl(); + lockView(); + + try + { + validateResolver(resolver); + conflictResolvers.add(resolver); + event = new ConflictResolversEventImpl(); + } + finally + { + unlockView(); + } } fireEvent(event); @@ -3659,12 +4307,21 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa checkActive(); IEvent event = null; - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - if (conflictResolvers.remove(resolver)) + lockView(); + + try { - resolver.setTransaction(null); - event = new ConflictResolversEventImpl(); + if (conflictResolvers.remove(resolver)) + { + resolver.setTransaction(null); + event = new ConflictResolversEventImpl(); + } + } + finally + { + unlockView(); } } @@ -3686,12 +4343,21 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } IEvent event = null; - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - if (this.staleReferenceCleaner != staleReferenceCleaner) + lockView(); + + try + { + if (this.staleReferenceCleaner != staleReferenceCleaner) + { + this.staleReferenceCleaner = staleReferenceCleaner; + event = new StaleReferenceCleanerEventImpl(); + } + } + finally { - this.staleReferenceCleaner = staleReferenceCleaner; - event = new StaleReferenceCleanerEventImpl(); + unlockView(); } } @@ -3740,12 +4406,21 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa checkActive(); IEvent event = null; - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - if (autoReleaseLocksEnabled != on) + lockView(); + + try { - autoReleaseLocksEnabled = on; - event = new AutoReleaseLocksEventImpl(); + if (autoReleaseLocksEnabled != on) + { + autoReleaseLocksEnabled = on; + event = new AutoReleaseLocksEventImpl(); + } + } + finally + { + unlockView(); } } @@ -3762,12 +4437,21 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa checkActive(); IEvent event = null; - synchronized (CDOTransactionImpl.this) + synchronized (getViewMonitor()) { - if (this.commitInfoTimeout != commitInfoTimeout) + lockView(); + + try + { + if (this.commitInfoTimeout != commitInfoTimeout) + { + this.commitInfoTimeout = commitInfoTimeout; + event = new CommitInfoTimeoutImpl(); + } + } + finally { - this.commitInfoTimeout = commitInfoTimeout; - event = new CommitInfoTimeoutImpl(); + unlockView(); } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java index 625e80f22f..d5772c8206 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java @@ -85,6 +85,7 @@ import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.collection.CloseableIterator; import org.eclipse.net4j.util.collection.ConcurrentArray; import org.eclipse.net4j.util.collection.Pair; +import org.eclipse.net4j.util.concurrent.DelegableReentrantLock; import org.eclipse.net4j.util.container.IContainerDelta; import org.eclipse.net4j.util.container.IContainerEvent; import org.eclipse.net4j.util.container.SelfAttachingContainerListener.DoNotDescend; @@ -132,6 +133,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; /** * @author Eike Stepper @@ -143,10 +147,16 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb private static final String REPOSITORY_NAME_KEY = "cdo.repository.name"; + private static final ThreadLocal<Lock> NEXT_VIEW_LOCK = new ThreadLocal<Lock>(); + private final ViewAndState[] viewAndStates = ViewAndState.create(this); private final CDOURIHandler uriHandler = new CDOURIHandler(this); + protected final Lock viewLock; + + protected final Condition viewLockCondition; + private CDOBranchPoint branchPoint; private CDOBranchPoint normalizedBranchPoint; @@ -190,14 +200,27 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb @ExcludeFromDump private transient InternalCDOObject lastLookupObject; - public AbstractCDOView(CDOBranchPoint branchPoint) + public AbstractCDOView(CDOSession session, CDOBranchPoint branchPoint) { + this(session); basicSetBranchPoint(branchPoint); - initObjectsMap(ReferenceType.SOFT); } - public AbstractCDOView() + public AbstractCDOView(CDOSession session) { + Lock lock = NEXT_VIEW_LOCK.get(); + if (lock != null) + { + NEXT_VIEW_LOCK.remove(); + } + else if (session != null && session.options().isDelegableViewLockEnabled()) + { + lock = new DelegableReentrantLock(); + } + + viewLock = lock; + viewLockCondition = viewLock != null ? viewLock.newCondition() : null; + initObjectsMap(ReferenceType.SOFT); } @@ -233,24 +256,60 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return true; } - protected synchronized final Map<CDOID, InternalCDOObject> getModifiableObjects() + protected final Map<CDOID, InternalCDOObject> getModifiableObjects() { - return objects; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return objects; + } + finally + { + unlockView(); + } + } } - public synchronized Map<CDOID, InternalCDOObject> getObjects() + public Map<CDOID, InternalCDOObject> getObjects() { - if (objects == null) + synchronized (getViewMonitor()) { - return Collections.emptyMap(); - } + lockView(); - return Collections.unmodifiableMap(objects); + try + { + if (objects == null) + { + return Collections.emptyMap(); + } + + return Collections.unmodifiableMap(objects); + } + finally + { + unlockView(); + } + } } - protected synchronized final void setObjects(Map<CDOID, InternalCDOObject> objects) + protected final void setObjects(Map<CDOID, InternalCDOObject> objects) { - this.objects = objects; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + this.objects = objects; + } + finally + { + unlockView(); + } + } } protected boolean initObjectsMap(ReferenceType referenceType) @@ -358,6 +417,71 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } + public final Object getViewMonitor() + { + if (viewLock != null) + { + return new NOOPMonitor(); + } + + return this; + } + + public final Lock getViewLock() + { + return viewLock; + } + + public final void lockView() + { + if (viewLock != null) + { + viewLock.lock(); + } + } + + public final void unlockView() + { + if (viewLock != null) + { + viewLock.unlock(); + } + } + + public void syncExec(Runnable runnable) + { + synchronized (getViewMonitor()) + { + lockView(); + + try + { + runnable.run(); + } + finally + { + unlockView(); + } + } + } + + public <V> V syncExec(Callable<V> callable) throws Exception + { + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return callable.call(); + } + finally + { + unlockView(); + } + } + } + public CDOViewProvider getProvider() { return provider; @@ -382,19 +506,32 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } - public synchronized CDOResourceImpl getRootResource() + public CDOResourceImpl getRootResource() { checkActive(); - if (rootResource == null) + + synchronized (getViewMonitor()) { - getObject(rootResourceID); - CheckUtil.checkState(rootResource, "rootResource"); - } + lockView(); + + try + { + if (rootResource == null) + { + getObject(rootResourceID); + CheckUtil.checkState(rootResource, "rootResource"); + } - return rootResource; + return rootResource; + } + finally + { + unlockView(); + } + } } - private synchronized void setRootResource(CDOResourceImpl resource) + private void setRootResource(CDOResourceImpl resource) { rootResource = resource; rootResource.setRoot(true); @@ -426,41 +563,64 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return CDOURIUtil.createResourceURI(session, path); } - public synchronized boolean isEmpty() + public boolean isEmpty() { - CDOResource rootResource = getRootResource(); - if (rootResource.cdoPermission() == CDOPermission.NONE) + synchronized (getViewMonitor()) { - return true; - } + lockView(); - boolean empty = rootResource.getContents().isEmpty(); - ensureContainerAdapter(rootResource); - return empty; + try + { + CDOResource rootResource = getRootResource(); + if (rootResource.cdoPermission() == CDOPermission.NONE) + { + return true; + } + + boolean empty = rootResource.getContents().isEmpty(); + ensureContainerAdapter(rootResource); + return empty; + } + finally + { + unlockView(); + } + } } - public synchronized CDOResourceNode[] getElements() + public CDOResourceNode[] getElements() { List<CDOResourceNode> elements = new ArrayList<CDOResourceNode>(); - - if (isActive()) + synchronized (getViewMonitor()) { - CDOResource rootResource = getRootResource(); - EList<EObject> contents = rootResource.getContents(); + lockView(); - for (EObject object : contents) + try { - if (object instanceof CDOResourceNode) + if (isActive()) { - CDOResourceNode element = (CDOResourceNode)object; - elements.add(element); + CDOResource rootResource = getRootResource(); + EList<EObject> contents = rootResource.getContents(); + + for (EObject object : contents) + { + if (object instanceof CDOResourceNode) + { + CDOResourceNode element = (CDOResourceNode)object; + elements.add(element); + } + } + + ensureContainerAdapter(rootResource); } } + finally + { + unlockView(); + } - ensureContainerAdapter(rootResource); + return elements.toArray(new CDOResourceNode[elements.size()]); } - - return elements.toArray(new CDOResourceNode[elements.size()]); } private void ensureContainerAdapter(final CDOResource rootResource) @@ -500,57 +660,141 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return uriHandler; } - protected synchronized CDOBranchPoint getBranchPoint() + protected CDOBranchPoint getBranchPoint() { - return branchPoint; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return branchPoint; + } + finally + { + unlockView(); + } + } } - protected synchronized CDOBranchPoint getNormalizedBranchPoint() + protected CDOBranchPoint getNormalizedBranchPoint() { - return normalizedBranchPoint; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return normalizedBranchPoint; + } + finally + { + unlockView(); + } + } } - public synchronized boolean setBranch(CDOBranch branch) + public boolean setBranch(CDOBranch branch) { - return setBranchPoint(branch, getTimeStamp(), null); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return setBranchPoint(branch, getTimeStamp(), null); + } + finally + { + unlockView(); + } + } } - public synchronized boolean setBranch(CDOBranch branch, IProgressMonitor monitor) + public boolean setBranch(CDOBranch branch, IProgressMonitor monitor) { - return setBranchPoint(branch, getTimeStamp(), monitor); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return setBranchPoint(branch, getTimeStamp(), monitor); + } + finally + { + unlockView(); + } + } } - public synchronized boolean setTimeStamp(long timeStamp) + public boolean setTimeStamp(long timeStamp) { - return setBranchPoint(getBranch(), timeStamp, null); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return setBranchPoint(getBranch(), timeStamp, null); + } + finally + { + unlockView(); + } + } } - public synchronized boolean setTimeStamp(long timeStamp, IProgressMonitor monitor) + public boolean setTimeStamp(long timeStamp, IProgressMonitor monitor) { - return setBranchPoint(getBranch(), timeStamp, monitor); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return setBranchPoint(getBranch(), timeStamp, monitor); + } + finally + { + unlockView(); + } + } } - public synchronized boolean setBranchPoint(CDOBranch branch, long timeStamp) + public boolean setBranchPoint(CDOBranch branch, long timeStamp) { return setBranchPoint(branch, timeStamp, null); } - public synchronized boolean setBranchPoint(CDOBranch branch, long timeStamp, IProgressMonitor monitor) + public boolean setBranchPoint(CDOBranch branch, long timeStamp, IProgressMonitor monitor) { CDOBranchPoint branchPoint = branch.getPoint(timeStamp); return setBranchPoint(branchPoint, monitor); } - public synchronized boolean setBranchPoint(CDOBranchPoint branchPoint) + public boolean setBranchPoint(CDOBranchPoint branchPoint) { return setBranchPoint(branchPoint, null); } - protected synchronized CDOBranchPoint basicSetBranchPoint(CDOBranchPoint branchPoint) + protected CDOBranchPoint basicSetBranchPoint(CDOBranchPoint branchPoint) { - this.branchPoint = adjustBranchPoint(branchPoint); - normalizedBranchPoint = CDOBranchUtil.normalizeBranchPoint(this.branchPoint); - return this.branchPoint; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + this.branchPoint = adjustBranchPoint(branchPoint); + normalizedBranchPoint = CDOBranchUtil.normalizeBranchPoint(this.branchPoint); + return this.branchPoint; + } + finally + { + unlockView(); + } + } } protected final CDOBranchPoint adjustBranchPoint(CDOBranchPoint branchPoint) @@ -570,14 +814,38 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb waitForUpdate(updateTime, NO_TIMEOUT); } - public synchronized CDOBranch getBranch() + public CDOBranch getBranch() { - return branchPoint.getBranch(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return branchPoint.getBranch(); + } + finally + { + unlockView(); + } + } } - public synchronized long getTimeStamp() + public long getTimeStamp() { - return branchPoint.getTimeStamp(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return branchPoint.getTimeStamp(); + } + finally + { + unlockView(); + } + } } protected void fireViewTargetChangedEvent(CDOBranchPoint oldBranchPoint, IListener[] listeners) @@ -595,44 +863,73 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return false; } - public synchronized boolean hasResource(String path) + public boolean hasResource(String path) { - try + synchronized (getViewMonitor()) { - checkActive(); - getResourceNodeID(path); - return true; - } - catch (Exception ex) - { - return false; + lockView(); + + try + { + checkActive(); + getResourceNodeID(path); + return true; + } + catch (Exception ex) + { + return false; + } } } - public synchronized CDOQueryImpl createQuery(String language, String queryString) + public CDOQueryImpl createQuery(String language, String queryString) { return createQuery(language, queryString, null); } - public synchronized CDOQueryImpl createQuery(String language, String queryString, Object context) + public CDOQueryImpl createQuery(String language, String queryString, Object context) { checkActive(); - return new CDOQueryImpl(this, language, queryString, context); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return new CDOQueryImpl(this, language, queryString, context); + } + finally + { + unlockView(); + } + } } - public synchronized CDOResourceNode getResourceNode(String path) + public CDOResourceNode getResourceNode(String path) { - CDOID id = getResourceNodeID(path); - if (id != null) // Should always be true + synchronized (getViewMonitor()) { - InternalCDOObject object = getObject(id); - if (object instanceof CDOResourceNode) + lockView(); + + try + { + CDOID id = getResourceNodeID(path); + if (id != null) // Should always be true + { + InternalCDOObject object = getObject(id); + if (object instanceof CDOResourceNode) + { + return (CDOResourceNode)object; + } + } + + throw new CDOException("Resource node not found: " + path); + } + finally { - return (CDOResourceNode)object; + unlockView(); } } - - throw new CDOException("Resource node not found: " + path); } private CDOID getCachedResourceNodeID(String path) @@ -660,75 +957,111 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } - public synchronized void setResourcePathCache(Map<String, CDOID> resourcePathCache) + public void setResourcePathCache(Map<String, CDOID> resourcePathCache) { - this.resourcePathCache = resourcePathCache; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + this.resourcePathCache = resourcePathCache; + } + finally + { + unlockView(); + } + } } /** * If <code>delta == null</code> the cache is cleared unconditionally. * If <code>delta != null</code> the cache is cleared only if the delta can have an impact on the resource tree structure. */ - public synchronized void clearResourcePathCacheIfNecessary(CDORevisionDelta delta) + public void clearResourcePathCacheIfNecessary(CDORevisionDelta delta) { - if (resourcePathCache != null && !resourcePathCache.isEmpty()) + synchronized (getViewMonitor()) { - if (delta == null) - { - resourcePathCache.clear(); - } - else + lockView(); + + try { - if (canHaveResourcePathImpact(delta, rootResourceID)) + if (resourcePathCache != null && !resourcePathCache.isEmpty()) { - resourcePathCache.clear(); + if (delta == null) + { + resourcePathCache.clear(); + } + else + { + if (canHaveResourcePathImpact(delta, rootResourceID)) + { + resourcePathCache.clear(); + } + } } } + finally + { + unlockView(); + } } } /** * @return never <code>null</code> */ - public synchronized CDOID getResourceNodeID(String path) + public CDOID getResourceNodeID(String path) { if (StringUtil.isEmpty(path)) { throw new IllegalArgumentException(Messages.getString("CDOViewImpl.1")); //$NON-NLS-1$ } - CDOID id = getCachedResourceNodeID(path); - if (id == null) + synchronized (getViewMonitor()) { - if (CDOURIUtil.SEGMENT_SEPARATOR.equals(path)) - { - id = getResourceNodeIDChecked(null, null); - setCachedResourceNodeID(path, id); - } - else - { - List<String> names = CDOURIUtil.analyzePath(path); - path = ""; + lockView(); - for (String name : names) + try + { + CDOID id = getCachedResourceNodeID(path); + if (id == null) { - path = path.length() == 0 ? name : path + "/" + name; - - CDOID cached = getCachedResourceNodeID(path); - if (cached != null) + if (CDOURIUtil.SEGMENT_SEPARATOR.equals(path)) { - id = cached; + id = getResourceNodeIDChecked(null, null); + setCachedResourceNodeID(path, id); } else { - id = getResourceNodeIDChecked(id, name); - setCachedResourceNodeID(path, id); + List<String> names = CDOURIUtil.analyzePath(path); + path = ""; + + for (String name : names) + { + path = path.length() == 0 ? name : path + "/" + name; + + CDOID cached = getCachedResourceNodeID(path); + if (cached != null) + { + id = cached; + } + else + { + id = getResourceNodeIDChecked(id, name); + setCachedResourceNodeID(path, id); + } + } } } + + return id; + } + finally + { + unlockView(); } } - - return id; } /** @@ -748,98 +1081,131 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb /** * @return never <code>null</code> */ - protected synchronized CDOResourceNode getResourceNode(CDOID folderID, String name) + protected CDOResourceNode getResourceNode(CDOID folderID, String name) { - try - { - CDOID id = getResourceNodeID(folderID, name); - return (CDOResourceNode)getObject(id); - } - catch (CDOException ex) + synchronized (getViewMonitor()) { - throw ex; - } - catch (Exception ex) - { - throw new CDOException(ex); + lockView(); + + try + { + CDOID id = getResourceNodeID(folderID, name); + return (CDOResourceNode)getObject(id); + } + catch (CDOException ex) + { + throw ex; + } + catch (Exception ex) + { + throw new CDOException(ex); + } + finally + { + unlockView(); + } } } - protected synchronized CDOID getResourceNodeID(CDOID folderID, String name) + protected CDOID getResourceNodeID(CDOID folderID, String name) { - if (folderID == null) + synchronized (getViewMonitor()) { - return getRootOrTopLevelResourceNodeID(name); - } + lockView(); - if (name == null) - { - throw new IllegalArgumentException(Messages.getString("CDOViewImpl.3")); //$NON-NLS-1$ - } + try + { + if (folderID == null) + { + return getRootOrTopLevelResourceNodeID(name); + } - InternalCDORevision folderRevision = getLocalRevision(folderID); - EClass resourceFolderClass = EresourcePackage.eINSTANCE.getCDOResourceFolder(); - if (folderRevision.getEClass() != resourceFolderClass) - { - throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.4"), folderID)); //$NON-NLS-1$ - } + if (name == null) + { + throw new IllegalArgumentException(Messages.getString("CDOViewImpl.3")); //$NON-NLS-1$ + } - EReference nodesFeature = EresourcePackage.eINSTANCE.getCDOResourceFolder_Nodes(); - EAttribute nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name(); + InternalCDORevision folderRevision = getLocalRevision(folderID); + EClass resourceFolderClass = EresourcePackage.eINSTANCE.getCDOResourceFolder(); + if (folderRevision.getEClass() != resourceFolderClass) + { + throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.4"), folderID)); //$NON-NLS-1$ + } - CDOList list; - boolean bypassPermissionChecks = folderRevision.bypassPermissionChecks(true); + EReference nodesFeature = EresourcePackage.eINSTANCE.getCDOResourceFolder_Nodes(); + EAttribute nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name(); - try - { - list = folderRevision.getList(nodesFeature); - } - finally - { - folderRevision.bypassPermissionChecks(bypassPermissionChecks); - } + CDOList list; + boolean bypassPermissionChecks = folderRevision.bypassPermissionChecks(true); - CDOStore store = getStore(); - int size = list.size(); - for (int i = 0; i < size; i++) - { - Object value = list.get(i); - value = store.resolveProxy(folderRevision, nodesFeature, i, value); + try + { + list = folderRevision.getList(nodesFeature); + } + finally + { + folderRevision.bypassPermissionChecks(bypassPermissionChecks); + } + + CDOStore store = getStore(); + int size = list.size(); + for (int i = 0; i < size; i++) + { + Object value = list.get(i); + value = store.resolveProxy(folderRevision, nodesFeature, i, value); - CDOID childID = (CDOID)convertObjectToID(value); - InternalCDORevision childRevision = getLocalRevision(childID); - String childName = (String)childRevision.get(nameFeature, 0); - if (name.equals(childName)) + CDOID childID = (CDOID)convertObjectToID(value); + InternalCDORevision childRevision = getLocalRevision(childID); + String childName = (String)childRevision.get(nameFeature, 0); + if (name.equals(childName)) + { + return childID; + } + } + + throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.5"), name)); //$NON-NLS-1$ + } + finally { - return childID; + unlockView(); } } - - throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.5"), name)); //$NON-NLS-1$ } - protected synchronized CDOID getRootOrTopLevelResourceNodeID(String name) + protected CDOID getRootOrTopLevelResourceNodeID(String name) { - if (name == null) + synchronized (getViewMonitor()) { - return rootResourceID; - } + lockView(); - CDOQuery resourceQuery = createResourcesQuery(null, name, true); - resourceQuery.setMaxResults(1); - List<CDOID> ids = resourceQuery.getResult(CDOID.class); - if (ids.isEmpty()) - { - throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.7"), name)); //$NON-NLS-1$ - } + try + { + if (name == null) + { + return rootResourceID; + } - if (ids.size() > 1) - { - // TODO is this still needed since the is resourceQuery.setMaxResults(1) ?? - throw new ImplementationError(Messages.getString("CDOViewImpl.8")); //$NON-NLS-1$ - } + CDOQuery resourceQuery = createResourcesQuery(null, name, true); + resourceQuery.setMaxResults(1); + List<CDOID> ids = resourceQuery.getResult(CDOID.class); + if (ids.isEmpty()) + { + throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.7"), name)); //$NON-NLS-1$ + } - return ids.get(0); + if (ids.size() > 1) + { + // TODO is this still needed since the is resourceQuery.setMaxResults(1) ?? + throw new ImplementationError(Messages.getString("CDOViewImpl.8")); //$NON-NLS-1$ + } + + return ids.get(0); + } + finally + { + unlockView(); + } + } } private InternalCDORevision getLocalRevision(CDOID id) @@ -864,50 +1230,74 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return revision; } - public synchronized List<InternalCDOObject> getObjectsList() + public List<InternalCDOObject> getObjectsList() { - List<InternalCDOObject> result = new ArrayList<InternalCDOObject>(); - for (InternalCDOObject value : objects.values()) + synchronized (getViewMonitor()) { - if (value != null) + lockView(); + + try + { + List<InternalCDOObject> result = new ArrayList<InternalCDOObject>(); + for (InternalCDOObject value : objects.values()) + { + if (value != null) + { + result.add(value); + } + } + + return result; + } + finally { - result.add(value); + unlockView(); } } - - return result; } - public synchronized CDOResource getResource(String path) + public CDOResource getResource(String path) { return getResource(path, true); } - public synchronized CDOResource getResource(String path, boolean loadOnDemand) + public CDOResource getResource(String path, boolean loadOnDemand) { checkActive(); - URI uri = CDOURIUtil.createResourceURI(this, path); - ResourceSet resourceSet = getResourceSet(); - ensureURIs(resourceSet); // Bug 337523 - - try - { - return (CDOResource)resourceSet.getResource(uri, loadOnDemand); - } - catch (RuntimeException ex) + synchronized (getViewMonitor()) { - EList<Resource> resources = resourceSet.getResources(); - for (int i = resources.size() - 1; i >= 0; --i) + lockView(); + + try { - Resource resource = resources.get(i); - if (uri.equals(resource.getURI())) + URI uri = CDOURIUtil.createResourceURI(this, path); + ResourceSet resourceSet = getResourceSet(); + ensureURIs(resourceSet); // Bug 337523 + + try { - resources.remove(i); - break; + return (CDOResource)resourceSet.getResource(uri, loadOnDemand); } - } + catch (RuntimeException ex) + { + EList<Resource> resources = resourceSet.getResources(); + for (int i = resources.size() - 1; i >= 0; --i) + { + Resource resource = resources.get(i); + if (uri.equals(resource.getURI())) + { + resources.remove(i); + break; + } + } - throw ex; + throw ex; + } + } + finally + { + unlockView(); + } } } @@ -961,17 +1351,41 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } while (resources.size() > size); } - public synchronized List<CDOResourceNode> queryResources(CDOResourceFolder folder, String name, boolean exactMatch) + public List<CDOResourceNode> queryResources(CDOResourceFolder folder, String name, boolean exactMatch) { - CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch); - return resourceQuery.getResult(CDOResourceNode.class); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch); + return resourceQuery.getResult(CDOResourceNode.class); + } + finally + { + unlockView(); + } + } } - public synchronized CloseableIterator<CDOResourceNode> queryResourcesAsync(CDOResourceFolder folder, String name, + public CloseableIterator<CDOResourceNode> queryResourcesAsync(CDOResourceFolder folder, String name, boolean exactMatch) { - CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch); - return resourceQuery.getResultAsync(CDOResourceNode.class); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch); + return resourceQuery.getResultAsync(CDOResourceNode.class); + } + finally + { + unlockView(); + } + } } private CDOQuery createResourcesQuery(CDOResourceFolder folder, String name, boolean exactMatch) @@ -1002,22 +1416,46 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return query; } - public synchronized List<CDOObjectReference> queryXRefs(CDOObject targetObject, EReference... sourceReferences) + public List<CDOObjectReference> queryXRefs(CDOObject targetObject, EReference... sourceReferences) { return queryXRefs(Collections.singleton(targetObject), sourceReferences); } - public synchronized List<CDOObjectReference> queryXRefs(Set<CDOObject> targetObjects, EReference... sourceReferences) + public List<CDOObjectReference> queryXRefs(Set<CDOObject> targetObjects, EReference... sourceReferences) { - CDOQuery xrefsQuery = createXRefsQuery(targetObjects, sourceReferences); - return xrefsQuery.getResult(CDOObjectReference.class); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOQuery xrefsQuery = createXRefsQuery(targetObjects, sourceReferences); + return xrefsQuery.getResult(CDOObjectReference.class); + } + finally + { + unlockView(); + } + } } - public synchronized CloseableIterator<CDOObjectReference> queryXRefsAsync(Set<CDOObject> targetObjects, + public CloseableIterator<CDOObjectReference> queryXRefsAsync(Set<CDOObject> targetObjects, EReference... sourceReferences) { - CDOQuery xrefsQuery = createXRefsQuery(targetObjects, sourceReferences); - return xrefsQuery.getResultAsync(CDOObjectReference.class); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOQuery xrefsQuery = createXRefsQuery(targetObjects, sourceReferences); + return xrefsQuery.getResultAsync(CDOObjectReference.class); + } + finally + { + unlockView(); + } + } } private CDOQuery createXRefsQuery(Set<CDOObject> targetObjects, EReference... sourceReferences) @@ -1085,17 +1523,29 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return builder.toString(); } - protected synchronized CDOID getXRefTargetID(CDOObject target) + protected CDOID getXRefTargetID(CDOObject target) { - if (FSMUtil.isTransient(target)) + synchronized (getViewMonitor()) { - throw new IllegalArgumentException("Cross referencing for transient objects not supported " + target); - } + lockView(); + + try + { + if (FSMUtil.isTransient(target)) + { + throw new IllegalArgumentException("Cross referencing for transient objects not supported " + target); + } - return target.cdoID(); + return target.cdoID(); + } + finally + { + unlockView(); + } + } } - public synchronized CDOResourceImpl getResource(CDOID resourceID) + public CDOResourceImpl getResource(CDOID resourceID) { if (CDOIDUtil.isNull(resourceID)) { @@ -1105,23 +1555,35 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return (CDOResourceImpl)getObject(resourceID); } - public synchronized InternalCDOObject newInstance(EClass eClass) + public InternalCDOObject newInstance(EClass eClass) { - EObject eObject = EcoreUtil.create(eClass); - return FSMUtil.adapt(eObject, this); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + EObject eObject = EcoreUtil.create(eClass); + return FSMUtil.adapt(eObject, this); + } + finally + { + unlockView(); + } + } } - public synchronized InternalCDORevision getRevision(CDOID id) + public InternalCDORevision getRevision(CDOID id) { return getRevision(id, true); } - public synchronized InternalCDOObject getObject(CDOID id) + public InternalCDOObject getObject(CDOID id) { return getObject(id, true); } - public synchronized InternalCDOObject getObject(CDOID id, boolean loadOnDemand) + public InternalCDOObject getObject(CDOID id, boolean loadOnDemand) { checkActive(); if (CDOIDUtil.isNull(id)) @@ -1129,67 +1591,91 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return null; } - if (rootResource != null && rootResource.cdoID() == id) - { - return rootResource; - } - - if (id == lastLookupID) - { - return lastLookupObject; - } - - lastLookupID = null; - lastLookupObject = null; - InternalCDOObject localLookupObject = null; - - if (id.isExternal()) + synchronized (getViewMonitor()) { - URI uri = URI.createURI(((CDOIDExternal)id).getURI()); - ResourceSet resourceSet = getResourceSet(); + lockView(); - localLookupObject = (InternalCDOObject)CDOUtil.getCDOObject(resourceSet.getEObject(uri, loadOnDemand)); - if (localLookupObject == null) + try { - if (!loadOnDemand) + if (rootResource != null && rootResource.cdoID() == id) { - return null; + return rootResource; } - throw new ObjectNotFoundException(id, this); - } - } - else - { - // Needed for recursive call to getObject. (from createObject/cleanObject/getResource/getObject) - localLookupObject = objects.get(id); - if (localLookupObject == null) - { - if (!loadOnDemand) + if (id == lastLookupID) { - return null; + return lastLookupObject; } - excludeNewObject(id); - localLookupObject = createObject(id); + lastLookupID = null; + lastLookupObject = null; + InternalCDOObject localLookupObject = null; + + if (id.isExternal()) + { + URI uri = URI.createURI(((CDOIDExternal)id).getURI()); + ResourceSet resourceSet = getResourceSet(); + + localLookupObject = (InternalCDOObject)CDOUtil.getCDOObject(resourceSet.getEObject(uri, loadOnDemand)); + if (localLookupObject == null) + { + if (!loadOnDemand) + { + return null; + } - if (id == rootResourceID) + throw new ObjectNotFoundException(id, this); + } + } + else { - setRootResource((CDOResourceImpl)localLookupObject); + // Needed for recursive call to getObject. (from createObject/cleanObject/getResource/getObject) + localLookupObject = objects.get(id); + if (localLookupObject == null) + { + if (!loadOnDemand) + { + return null; + } + + excludeNewObject(id); + localLookupObject = createObject(id); + + if (id == rootResourceID) + { + setRootResource((CDOResourceImpl)localLookupObject); + } + } } + + lastLookupID = id; + lastLookupObject = localLookupObject; + return lastLookupObject; + } + finally + { + unlockView(); } } - - lastLookupID = id; - lastLookupObject = localLookupObject; - return lastLookupObject; } - protected synchronized void excludeNewObject(CDOID id) + protected void excludeNewObject(CDOID id) { - if (isObjectNew(id)) + synchronized (getViewMonitor()) { - throw new ObjectNotFoundException(id, this); + lockView(); + + try + { + if (isObjectNew(id)) + { + throw new ObjectNotFoundException(id, this); + } + } + finally + { + unlockView(); + } } } @@ -1201,43 +1687,55 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb /** * @since 2.0 */ - public synchronized <T extends EObject> T getObject(T objectFromDifferentView) + public <T extends EObject> T getObject(T objectFromDifferentView) { checkActive(); - CDOObject object = CDOUtil.getCDOObject(objectFromDifferentView); - CDOView view = object.cdoView(); - if (view == null) + synchronized (getViewMonitor()) { - return null; - } + lockView(); - if (view != this) - { - if (!view.getSession().getRepositoryInfo().getUUID().equals(getSession().getRepositoryInfo().getUUID())) + try { - throw new IllegalArgumentException( - MessageFormat.format(Messages.getString("CDOViewImpl.11"), objectFromDifferentView)); //$NON-NLS-1$ - } + CDOObject object = CDOUtil.getCDOObject(objectFromDifferentView); + CDOView view = object.cdoView(); + if (view == null) + { + return null; + } - CDOID id = object.cdoID(); - InternalCDOObject contextified = getObject(id, true); + if (view != this) + { + if (!view.getSession().getRepositoryInfo().getUUID().equals(getSession().getRepositoryInfo().getUUID())) + { + throw new IllegalArgumentException( + MessageFormat.format(Messages.getString("CDOViewImpl.11"), objectFromDifferentView)); //$NON-NLS-1$ + } - if (objectFromDifferentView instanceof CDOLegacyAdapter) + CDOID id = object.cdoID(); + InternalCDOObject contextified = getObject(id, true); + + if (objectFromDifferentView instanceof CDOLegacyAdapter) + { + @SuppressWarnings("unchecked") + T cast = (T)contextified; + return cast; + } + + @SuppressWarnings("unchecked") + T cast = (T)CDOUtil.getEObject(contextified); + return cast; + } + + return objectFromDifferentView; + } + finally { - @SuppressWarnings("unchecked") - T cast = (T)contextified; - return cast; + unlockView(); } - - @SuppressWarnings("unchecked") - T cast = (T)CDOUtil.getEObject(contextified); - return cast; } - - return objectFromDifferentView; } - public synchronized boolean isObjectRegistered(CDOID id) + public boolean isObjectRegistered(CDOID id) { checkActive(); if (CDOIDUtil.isNull(id)) @@ -1245,23 +1743,47 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return false; } - return objects.containsKey(id); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return objects.containsKey(id); + } + finally + { + unlockView(); + } + } } - public synchronized InternalCDOObject removeObject(CDOID id) + public InternalCDOObject removeObject(CDOID id) { if (id == null) { return null; } - if (id == lastLookupID) + synchronized (getViewMonitor()) { - lastLookupID = null; - lastLookupObject = null; - } + lockView(); - return objects.remove(id); + try + { + if (id == lastLookupID) + { + lastLookupID = null; + lastLookupObject = null; + } + + return objects.remove(id); + } + finally + { + unlockView(); + } + } } /** @@ -1368,67 +1890,92 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb /** * @since 2.0 */ - protected synchronized void cleanObject(InternalCDOObject object, InternalCDORevision revision) + protected void cleanObject(InternalCDOObject object, InternalCDORevision revision) { - object.cdoInternalSetView(this); - object.cdoInternalSetRevision(revision); + synchronized (getViewMonitor()) + { + lockView(); - // Before setting the state to CLEAN (that can trigger a duplicate loading and instantiation of the current object) - // we make sure that object is registered - without throwing exception if it is already the case - registerObjectIfNotRegistered(object); + try + { + object.cdoInternalSetView(this); + object.cdoInternalSetRevision(revision); - object.cdoInternalSetState(CDOState.CLEAN); - object.cdoInternalPostLoad(); - } + // Before setting the state to CLEAN (that can trigger a duplicate loading and instantiation of the current + // object) + // we make sure that object is registered - without throwing exception if it is already the case + registerObjectIfNotRegistered(object); - public synchronized CDOID provideCDOID(Object idOrObject) - { - Object shouldBeCDOID = convertObjectToID(idOrObject); - if (shouldBeCDOID instanceof CDOID) - { - CDOID id = (CDOID)shouldBeCDOID; - if (TRACER.isEnabled() && id != idOrObject) + object.cdoInternalSetState(CDOState.CLEAN); + object.cdoInternalPostLoad(); + } + finally { - TRACER.format("Converted object to CDOID: {0} --> {1}", idOrObject, id); //$NON-NLS-1$ + unlockView(); } - - return id; } + } - if (idOrObject instanceof InternalEObject) + public CDOID provideCDOID(Object idOrObject) + { + synchronized (getViewMonitor()) { - InternalEObject eObject = (InternalEObject)idOrObject; - if (eObject instanceof InternalCDOObject) + lockView(); + + try { - InternalCDOObject object = (InternalCDOObject)idOrObject; - if (object.cdoView() != null && FSMUtil.isNew(object)) + Object shouldBeCDOID = convertObjectToID(idOrObject); + if (shouldBeCDOID instanceof CDOID) { - String uri = EcoreUtil.getURI(object.cdoInternalInstance()).toString(); - if (object.cdoID().isTemporary()) + CDOID id = (CDOID)shouldBeCDOID; + if (TRACER.isEnabled() && id != idOrObject) { - return CDOIDUtil.createTempObjectExternal(uri); + TRACER.format("Converted object to CDOID: {0} --> {1}", idOrObject, id); //$NON-NLS-1$ } + + return id; } - } - Resource eResource = eObject.eResource(); - if (eResource != null) - { - // Check if eObject is contained by a deleted resource - if (!(eResource instanceof CDOResource) || ((CDOResource)eResource).cdoState() != CDOState.TRANSIENT) + if (idOrObject instanceof InternalEObject) { - String uri = EcoreUtil.getURI(CDOUtil.getEObject(eObject)).toString(); - return CDOIDUtil.createExternal(uri); + InternalEObject eObject = (InternalEObject)idOrObject; + if (eObject instanceof InternalCDOObject) + { + InternalCDOObject object = (InternalCDOObject)idOrObject; + if (object.cdoView() != null && FSMUtil.isNew(object)) + { + String uri = EcoreUtil.getURI(object.cdoInternalInstance()).toString(); + if (object.cdoID().isTemporary()) + { + return CDOIDUtil.createTempObjectExternal(uri); + } + } + } + + Resource eResource = eObject.eResource(); + if (eResource != null) + { + // Check if eObject is contained by a deleted resource + if (!(eResource instanceof CDOResource) || ((CDOResource)eResource).cdoState() != CDOState.TRANSIENT) + { + String uri = EcoreUtil.getURI(CDOUtil.getEObject(eObject)).toString(); + return CDOIDUtil.createExternal(uri); + } + } + + throw new DanglingReferenceException(eObject); } - } - throw new DanglingReferenceException(eObject); + throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOViewImpl.16"), idOrObject)); //$NON-NLS-1$ + } + finally + { + unlockView(); + } } - - throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOViewImpl.16"), idOrObject)); //$NON-NLS-1$ } - public synchronized Object convertObjectToID(Object potentialObject) + public Object convertObjectToID(Object potentialObject) { return convertObjectToID(potentialObject, false); } @@ -1436,75 +1983,100 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb /** * @since 2.0 */ - public synchronized Object convertObjectToID(Object potentialObject, boolean onlyPersistedID) + public Object convertObjectToID(Object potentialObject, boolean onlyPersistedID) { if (potentialObject instanceof CDOID) { return potentialObject; } - if (potentialObject instanceof InternalEObject) + synchronized (getViewMonitor()) { - if (potentialObject instanceof InternalCDOObject) - { - InternalCDOObject object = (InternalCDOObject)potentialObject; - CDOID id = getID(object, onlyPersistedID); - if (id != null) - { - return id; - } - } - else + lockView(); + + try { - InternalCDOObject object = (InternalCDOObject)EcoreUtil - .getAdapter(((InternalEObject)potentialObject).eAdapters(), CDOLegacyAdapter.class); - if (object != null) + if (potentialObject instanceof InternalEObject) { - CDOID id = getID(object, onlyPersistedID); - if (id != null) + if (potentialObject instanceof InternalCDOObject) { - return id; + InternalCDOObject object = (InternalCDOObject)potentialObject; + CDOID id = getID(object, onlyPersistedID); + if (id != null) + { + return id; + } + } + else + { + InternalCDOObject object = (InternalCDOObject)EcoreUtil + .getAdapter(((InternalEObject)potentialObject).eAdapters(), CDOLegacyAdapter.class); + if (object != null) + { + CDOID id = getID(object, onlyPersistedID); + if (id != null) + { + return id; + } + + potentialObject = object; + } } - - potentialObject = object; } + + return potentialObject; + } + finally + { + unlockView(); } } - - return potentialObject; } - protected synchronized CDOID getID(InternalCDOObject object, boolean onlyPersistedID) + protected CDOID getID(InternalCDOObject object, boolean onlyPersistedID) { - if (onlyPersistedID) + synchronized (getViewMonitor()) { - if (FSMUtil.isTransient(object) || FSMUtil.isNew(object)) + lockView(); + + try { - return null; - } - } + if (onlyPersistedID) + { + if (FSMUtil.isTransient(object) || FSMUtil.isNew(object)) + { + return null; + } + } - CDOView view = object.cdoView(); - if (view == this) - { - return object.cdoID(); - } + CDOView view = object.cdoView(); + if (view == this) + { + return object.cdoID(); + } - if (view != null && view.getSession() == getSession()) - { - boolean sameTarget = view.getBranch() == getBranch() && view.getTimeStamp() == getTimeStamp(); - if (sameTarget) + if (view != null && view.getSession() == getSession()) + { + boolean sameTarget = view.getBranch() == getBranch() && view.getTimeStamp() == getTimeStamp(); + if (sameTarget) + { + return object.cdoID(); + } + + throw new IllegalArgumentException( + "Object " + object + " is managed by a view with different target: " + view); + } + + return null; + } + finally { - return object.cdoID(); + unlockView(); } - - throw new IllegalArgumentException("Object " + object + " is managed by a view with different target: " + view); } - - return null; } - public synchronized Object convertIDToObject(Object potentialID) + public Object convertIDToObject(Object potentialID) { if (potentialID instanceof CDOID) { @@ -1513,19 +2085,31 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return null; } - CDOID id = (CDOID)potentialID; - if (id.isExternal()) + synchronized (getViewMonitor()) { - return getResourceSet().getEObject(URI.createURI(id.toURIFragment()), true); - } + lockView(); - InternalCDOObject result = getObject(id, true); - if (result == null) - { - throw new ImplementationError(MessageFormat.format(Messages.getString("CDOViewImpl.17"), id)); //$NON-NLS-1$ - } + try + { + CDOID id = (CDOID)potentialID; + if (id.isExternal()) + { + return getResourceSet().getEObject(URI.createURI(id.toURIFragment()), true); + } + + InternalCDOObject result = getObject(id, true); + if (result == null) + { + throw new ImplementationError(MessageFormat.format(Messages.getString("CDOViewImpl.17"), id)); //$NON-NLS-1$ + } - return result.cdoInternalInstance(); + return result.cdoInternalInstance(); + } + finally + { + unlockView(); + } + } } return potentialID; @@ -1534,60 +2118,84 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb /** * @since 2.0 */ - public synchronized void attachResource(CDOResourceImpl resource) + public void attachResource(CDOResourceImpl resource) { - if (!resource.isExisting()) + synchronized (getViewMonitor()) { - throw new ReadOnlyException(MessageFormat.format(Messages.getString("CDOViewImpl.18"), this)); //$NON-NLS-1$ - } + lockView(); - // ResourceSet.getResource(uri, true) was called!! - resource.cdoInternalSetView(this); - resource.cdoInternalSetState(CDOState.PROXY); - registerProxyResource2(resource); + try + { + if (!resource.isExisting()) + { + throw new ReadOnlyException(MessageFormat.format(Messages.getString("CDOViewImpl.18"), this)); //$NON-NLS-1$ + } + + // ResourceSet.getResource(uri, true) was called!! + resource.cdoInternalSetView(this); + resource.cdoInternalSetState(CDOState.PROXY); + registerProxyResource2(resource); + } + finally + { + unlockView(); + } + } } - private synchronized void registerProxyResource2(CDOResourceImpl resource) + private void registerProxyResource2(CDOResourceImpl resource) { - URI uri = resource.getURI(); - String path = CDOURIUtil.extractResourcePath(uri); - boolean isRoot = "/".equals(path); //$NON-NLS-1$ - - try + synchronized (getViewMonitor()) { - CDOID id; - if (isRoot) - { - id = rootResourceID; - } - else + lockView(); + + try { - id = getResourceNodeID(path); - } + URI uri = resource.getURI(); + String path = CDOURIUtil.extractResourcePath(uri); + boolean isRoot = "/".equals(path); //$NON-NLS-1$ - resource.cdoInternalSetID(id); - registerObject(resource); - if (isRoot) + try + { + CDOID id; + if (isRoot) + { + id = rootResourceID; + } + else + { + id = getResourceNodeID(path); + } + + resource.cdoInternalSetID(id); + registerObject(resource); + if (isRoot) + { + resource.setRoot(true); + rootResource = resource; + } + } + catch (LifecycleException ex) + { + throw ex; + } + catch (Exception ex) + { + throw new InvalidURIException(uri, ex); + } + } + finally { - resource.setRoot(true); - rootResource = resource; + unlockView(); } } - catch (LifecycleException ex) - { - throw ex; - } - catch (Exception ex) - { - throw new InvalidURIException(uri, ex); - } } /** * @deprecated No longer supported. */ @Deprecated - public synchronized void registerProxyResource(CDOResourceImpl resource) + public void registerProxyResource(CDOResourceImpl resource) { registerProxyResource2(resource); } @@ -1613,55 +2221,91 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb registerObject(object); } - public synchronized void registerObject(InternalCDOObject object) + public void registerObject(InternalCDOObject object) { - if (TRACER.isEnabled()) + synchronized (getViewMonitor()) { - TRACER.format("Registering {0}", object); //$NON-NLS-1$ - } + lockView(); - InternalCDOObject old = objects.put(object.cdoID(), object); - if (old != null) - { - if (old != object) + try { - throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOViewImpl.30"), object.cdoID())); //$NON-NLS-1$ - } + if (TRACER.isEnabled()) + { + TRACER.format("Registering {0}", object); //$NON-NLS-1$ + } + + InternalCDOObject old = objects.put(object.cdoID(), object); + if (old != null) + { + if (old != object) + { + throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOViewImpl.30"), object.cdoID())); //$NON-NLS-1$ + } - if (TRACER.isEnabled()) + if (TRACER.isEnabled()) + { + TRACER.format(Messages.getString("CDOViewImpl.20"), old); //$NON-NLS-1$ + } + } + } + finally { - TRACER.format(Messages.getString("CDOViewImpl.20"), old); //$NON-NLS-1$ + unlockView(); } } } - public synchronized void deregisterObject(InternalCDOObject object) + public void deregisterObject(InternalCDOObject object) { - if (TRACER.isEnabled()) + synchronized (getViewMonitor()) { - TRACER.format("Deregistering {0}", object); //$NON-NLS-1$ - } + lockView(); + + try + { + if (TRACER.isEnabled()) + { + TRACER.format("Deregistering {0}", object); //$NON-NLS-1$ + } - removeObject(object.cdoID()); + removeObject(object.cdoID()); + } + finally + { + unlockView(); + } + } } - public synchronized void remapObject(CDOID oldID) + public void remapObject(CDOID oldID) { - CDOID newID; - InternalCDOObject object = objects.remove(oldID); - newID = object.cdoID(); + synchronized (getViewMonitor()) + { + lockView(); - objects.put(newID, object); + try + { + CDOID newID; + InternalCDOObject object = objects.remove(oldID); + newID = object.cdoID(); - if (lastLookupID == oldID) - { - lastLookupID = null; - lastLookupObject = null; - } + objects.put(newID, object); - if (TRACER.isEnabled()) - { - TRACER.format("Remapping {0} --> {1}", oldID, newID); //$NON-NLS-1$ + if (lastLookupID == oldID) + { + lastLookupID = null; + lastLookupObject = null; + } + + if (TRACER.isEnabled()) + { + TRACER.format("Remapping {0} --> {1}", oldID, newID); //$NON-NLS-1$ + } + } + finally + { + unlockView(); + } } } @@ -1680,13 +2324,25 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return objectHandlers.get(); } - public synchronized void handleObjectStateChanged(InternalCDOObject object, CDOState oldState, CDOState newState) + public void handleObjectStateChanged(InternalCDOObject object, CDOState oldState, CDOState newState) { - CDOObjectHandler[] handlers = getObjectHandlers(); - for (int i = 0; i < handlers.length; i++) + synchronized (getViewMonitor()) { - CDOObjectHandler handler = handlers[i]; - handler.objectStateChanged(this, object, oldState, newState); + lockView(); + + try + { + CDOObjectHandler[] handlers = getObjectHandlers(); + for (int i = 0; i < handlers.length; i++) + { + CDOObjectHandler handler = handlers[i]; + handler.objectStateChanged(this, object, oldState, newState); + } + } + finally + { + unlockView(); + } } } @@ -1793,8 +2449,8 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb /** * Overridden by {@link CDOTransactionImpl#handleConflicts(long, Map, List)}. */ - protected synchronized void handleConflicts(long lastUpdateTime, - Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts, List<CDORevisionDelta> deltas) + protected void handleConflicts(long lastUpdateTime, Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts, + List<CDORevisionDelta> deltas) { // Do nothing } @@ -1824,32 +2480,44 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } @Deprecated - public synchronized int reload(CDOObject... objects) + public int reload(CDOObject... objects) { - Collection<InternalCDOObject> internalObjects; - if (objects != null && objects.length != 0) + synchronized (getViewMonitor()) { - internalObjects = new ArrayList<InternalCDOObject>(objects.length); - for (CDOObject object : objects) + lockView(); + + try { - if (object instanceof InternalCDOObject) + Collection<InternalCDOObject> internalObjects; + if (objects != null && objects.length != 0) { - internalObjects.add((InternalCDOObject)object); + internalObjects = new ArrayList<InternalCDOObject>(objects.length); + for (CDOObject object : objects) + { + if (object instanceof InternalCDOObject) + { + internalObjects.add((InternalCDOObject)object); + } + } + } + else + { + internalObjects = new ArrayList<InternalCDOObject>(this.objects.values()); } - } - } - else - { - internalObjects = new ArrayList<InternalCDOObject>(this.objects.values()); - } - int result = internalObjects.size(); - if (result != 0) - { - CDOStateMachine.INSTANCE.reload(internalObjects.toArray(new InternalCDOObject[result])); - } + int result = internalObjects.size(); + if (result != 0) + { + CDOStateMachine.INSTANCE.reload(internalObjects.toArray(new InternalCDOObject[result])); + } - return result; + return result; + } + finally + { + unlockView(); + } + } } public void close() @@ -1942,29 +2610,41 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return getResourceSet(); } - public synchronized void collectViewedRevisions(Map<CDOID, InternalCDORevision> revisions) + public void collectViewedRevisions(Map<CDOID, InternalCDORevision> revisions) { - for (InternalCDOObject object : objects.values()) + synchronized (getViewMonitor()) { - CDOState state = object.cdoState(); - if (state != CDOState.CLEAN && state != CDOState.DIRTY && state != CDOState.CONFLICT) - { - continue; - } + lockView(); - CDOID id = object.cdoID(); - if (revisions.containsKey(id)) + try { - continue; - } + for (InternalCDOObject object : objects.values()) + { + CDOState state = object.cdoState(); + if (state != CDOState.CLEAN && state != CDOState.DIRTY && state != CDOState.CONFLICT) + { + continue; + } + + CDOID id = object.cdoID(); + if (revisions.containsKey(id)) + { + continue; + } + + InternalCDORevision revision = getViewedRevision(object); + if (revision == null) + { + continue; + } - InternalCDORevision revision = getViewedRevision(object); - if (revision == null) + revisions.put(id, revision); + } + } + finally { - continue; + unlockView(); } - - revisions.put(id, revision); } } @@ -1973,10 +2653,22 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb return CDOStateMachine.INSTANCE.readNoLoad(object); } - public synchronized CDOChangeSetData compareRevisions(CDOBranchPoint source) + public CDOChangeSetData compareRevisions(CDOBranchPoint source) { - CDOSession session = getSession(); - return session.compareRevisions(source, this); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOSession session = getSession(); + return session.compareRevisions(source, this); + } + finally + { + unlockView(); + } + } } @Override @@ -1998,6 +2690,8 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb { super.doActivate(); + LifecycleUtil.activate(viewLock); + if (branchPoint != null) { basicSetBranchPoint(branchPoint); @@ -2012,6 +2706,8 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb viewSet.getResourceSet().getURIConverter().getURIHandlers().remove(getURIHandler()); } + LifecycleUtil.deactivate(viewLock); + viewSet = null; objects = null; store = null; @@ -2021,6 +2717,18 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb super.doDeactivate(); } + public static void setNextViewLock(Lock viewLock) + { + if (viewLock != null) + { + NEXT_VIEW_LOCK.set(viewLock); + } + else + { + NEXT_VIEW_LOCK.remove(); + } + } + public static boolean canHaveResourcePathImpact(CDORevisionDelta delta, CDOID rootResourceID) { EClass eClass = delta.getEClass(); @@ -2223,4 +2931,13 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } } + + /** + * For better debugging. + * + * @author Eike Stepper + */ + private static final class NOOPMonitor + { + } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java index 396afc43be..0f31676d58 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java @@ -69,6 +69,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.locks.Lock; /** * @author Eike Stepper @@ -198,15 +199,24 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent */ public void attach(InternalCDOObject object, InternalCDOTransaction transaction) { - synchronized (transaction) + synchronized (transaction.getViewMonitor()) { - List<InternalCDOObject> contents = new ArrayList<InternalCDOObject>(); - prepare(object, Pair.create(transaction, contents)); + transaction.lockView(); - attachOrReattach(object, transaction); - for (InternalCDOObject content : contents) + try + { + List<InternalCDOObject> contents = new ArrayList<InternalCDOObject>(); + prepare(object, Pair.create(transaction, contents)); + + attachOrReattach(object, transaction); + for (InternalCDOObject content : contents) + { + attachOrReattach(content, transaction); + } + } + finally { - attachOrReattach(content, transaction); + transaction.unlockView(); } } } @@ -267,34 +277,50 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - if (TRACER.isEnabled()) + Lock lock = getLock(object); + if (lock != null) { - trace(object, CDOEvent.DETACH); + lock.lock(); } - List<InternalCDOObject> objectsToDetach = new ArrayList<InternalCDOObject>(); - InternalCDOTransaction transaction = (InternalCDOTransaction)object.cdoView(); + try + { + if (TRACER.isEnabled()) + { + trace(object, CDOEvent.DETACH); + } - // Accumulate objects that needs to be detached - // If we have an error, we will keep the graph exactly like it was before. - process(object, CDOEvent.DETACH, objectsToDetach); + List<InternalCDOObject> objectsToDetach = new ArrayList<InternalCDOObject>(); + InternalCDOTransaction transaction = (InternalCDOTransaction)object.cdoView(); - // postDetach requires the object to be TRANSIENT - for (InternalCDOObject content : objectsToDetach) - { - CDOState oldState = content.cdoInternalSetState(CDOState.TRANSIENT); - content.cdoInternalPostDetach(false); - content.cdoInternalSetState(oldState); - } + // Accumulate objects that needs to be detached + // If we have an error, we will keep the graph exactly like it was before. + process(object, CDOEvent.DETACH, objectsToDetach); - // detachObject needs to know the state before we change the object to TRANSIENT - for (InternalCDOObject content : objectsToDetach) - { - transaction.detachObject(content); - content.cdoInternalSetState(CDOState.TRANSIENT); + // postDetach requires the object to be TRANSIENT + for (InternalCDOObject content : objectsToDetach) + { + CDOState oldState = content.cdoInternalSetState(CDOState.TRANSIENT); + content.cdoInternalPostDetach(false); + content.cdoInternalSetState(oldState); + } + + // detachObject needs to know the state before we change the object to TRANSIENT + for (InternalCDOObject content : objectsToDetach) + { + transaction.detachObject(content); + content.cdoInternalSetState(CDOState.TRANSIENT); - content.cdoInternalSetView(null); - content.cdoInternalSetID(null); + content.cdoInternalSetView(null); + content.cdoInternalSetID(null); + } + } + finally + { + if (lock != null) + { + lock.unlock(); + } } } } @@ -303,13 +329,29 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - if (TRACER.isEnabled()) + Lock lock = getLock(object); + if (lock != null) { - trace(object, CDOEvent.READ); + lock.lock(); } - process(object, CDOEvent.READ, null); - return object.cdoRevision(); + try + { + if (TRACER.isEnabled()) + { + trace(object, CDOEvent.READ); + } + + process(object, CDOEvent.READ, null); + return object.cdoRevision(); + } + finally + { + if (lock != null) + { + lock.unlock(); + } + } } } @@ -317,19 +359,35 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - switch (object.cdoState()) + Lock lock = getLock(object); + if (lock != null) { - case TRANSIENT: - case PREPARED: - case NEW: - case CONFLICT: - case INVALID_CONFLICT: - case INVALID: - case PROXY: - return null; + lock.lock(); } - return object.cdoRevision(); + try + { + switch (object.cdoState()) + { + case TRANSIENT: + case PREPARED: + case NEW: + case CONFLICT: + case INVALID_CONFLICT: + case INVALID: + case PROXY: + return null; + } + + return object.cdoRevision(); + } + finally + { + if (lock != null) + { + lock.unlock(); + } + } } } @@ -337,7 +395,23 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - return writeWithoutViewLock(object, featureDelta); + Lock lock = getLock(object); + if (lock != null) + { + lock.lock(); + } + + try + { + return writeWithoutViewLock(object, featureDelta); + } + finally + { + if (lock != null) + { + lock.unlock(); + } + } } } @@ -364,14 +438,30 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent synchronized (getMonitor(objects[0])) { - for (InternalCDOObject object : objects) + Lock lock = getLock(objects[0]); + if (lock != null) { - CDOState state = object.cdoState(); - if (state == CDOState.CLEAN || state == CDOState.PROXY) + lock.lock(); + } + + try + { + for (InternalCDOObject object : objects) { - changeState(object, CDOState.PROXY); - object.cdoInternalSetRevision(null); - read(object); + CDOState state = object.cdoState(); + if (state == CDOState.CLEAN || state == CDOState.PROXY) + { + changeState(object, CDOState.PROXY); + object.cdoInternalSetRevision(null); + read(object); + } + } + } + finally + { + if (lock != null) + { + lock.unlock(); } } } @@ -381,12 +471,28 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - if (TRACER.isEnabled()) + Lock lock = getLock(object); + if (lock != null) { - trace(object, CDOEvent.INVALIDATE); + lock.lock(); } - process(object, CDOEvent.INVALIDATE, key); + try + { + if (TRACER.isEnabled()) + { + trace(object, CDOEvent.INVALIDATE); + } + + process(object, CDOEvent.INVALIDATE, key); + } + finally + { + if (lock != null) + { + lock.unlock(); + } + } } } @@ -394,12 +500,28 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - if (TRACER.isEnabled()) + Lock lock = getLock(object); + if (lock != null) { - trace(object, CDOEvent.DETACH_REMOTE); + lock.lock(); } - process(object, CDOEvent.DETACH_REMOTE, null); + try + { + if (TRACER.isEnabled()) + { + trace(object, CDOEvent.DETACH_REMOTE); + } + + process(object, CDOEvent.DETACH_REMOTE, null); + } + finally + { + if (lock != null) + { + lock.unlock(); + } + } } } @@ -407,12 +529,28 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - if (TRACER.isEnabled()) + Lock lock = getLock(object); + if (lock != null) { - trace(object, CDOEvent.COMMIT); + lock.lock(); } - process(object, CDOEvent.COMMIT, result); + try + { + if (TRACER.isEnabled()) + { + trace(object, CDOEvent.COMMIT); + } + + process(object, CDOEvent.COMMIT, result); + } + finally + { + if (lock != null) + { + lock.unlock(); + } + } } } @@ -420,12 +558,28 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { synchronized (getMonitor(object)) { - if (TRACER.isEnabled()) + Lock lock = getLock(object); + if (lock != null) { - trace(object, CDOEvent.ROLLBACK); + lock.lock(); } - process(object, CDOEvent.ROLLBACK, transaction); + try + { + if (TRACER.isEnabled()) + { + trace(object, CDOEvent.ROLLBACK); + } + + process(object, CDOEvent.ROLLBACK, transaction); + } + finally + { + if (lock != null) + { + lock.unlock(); + } + } } } @@ -441,12 +595,24 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent object.cdoInternalSetState(state); } + private Lock getLock(InternalCDOObject object) + { + InternalCDOView view = object.cdoView(); + if (view != null) + { + return view.getViewLock(); + } + + // In TRANSIENT and PREPARED the object is not yet attached to a view + return null; + } + private Object getMonitor(InternalCDOObject object) { InternalCDOView view = object.cdoView(); if (view != null) { - return view; + return view.getViewMonitor(); } // In TRANSIENT and PREPARED the object is not yet attached to a view @@ -621,7 +787,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent * @author Eike Stepper */ private final class PrepareTransition implements - ITransition<CDOState, CDOEvent, InternalCDOObject, Pair<InternalCDOTransaction, List<InternalCDOObject>>> + ITransition<CDOState, CDOEvent, InternalCDOObject, Pair<InternalCDOTransaction, List<InternalCDOObject>>> { public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<InternalCDOTransaction, List<InternalCDOObject>> transactionAndContents) @@ -735,7 +901,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent * @author Caspar De Groot */ private final class ReattachTransition - implements ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction> + implements ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction> { public void execute(InternalCDOObject object, CDOState state, CDOEvent event, InternalCDOTransaction transaction) { @@ -835,7 +1001,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent * @author Eike Stepper */ private static final class DetachTransition - implements ITransition<CDOState, CDOEvent, InternalCDOObject, List<InternalCDOObject>> + implements ITransition<CDOState, CDOEvent, InternalCDOObject, List<InternalCDOObject>> { public void execute(InternalCDOObject object, CDOState state, CDOEvent event, List<InternalCDOObject> objectsToDetach) @@ -865,7 +1031,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent * @author Eike Stepper */ final private class CommitTransition - implements ITransition<CDOState, CDOEvent, InternalCDOObject, CommitTransactionResult> + implements ITransition<CDOState, CDOEvent, InternalCDOObject, CommitTransactionResult> { public CommitTransition(boolean useDeltas) { @@ -901,8 +1067,8 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent /** * @author Eike Stepper */ - private final class RollbackTransition implements - ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction> + private final class RollbackTransition + implements ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction> { public void execute(InternalCDOObject object, CDOState state, CDOEvent event, InternalCDOTransaction transaction) { @@ -925,7 +1091,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent * @author Eike Stepper */ private static abstract class AbstractWriteTransition - implements ITransition<CDOState, CDOEvent, InternalCDOObject, FeatureDeltaAndResult> + implements ITransition<CDOState, CDOEvent, InternalCDOObject, FeatureDeltaAndResult> { public void execute(InternalCDOObject object, CDOState state, CDOEvent event, FeatureDeltaAndResult featureDeltaAndResult) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java index d308c4e74f..c1d2076edb 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStoreImpl.java @@ -74,7 +74,7 @@ public final class CDOStoreImpl implements CDOStore { private final ContextTracer TRACER = new ContextTracer(OM.DEBUG_STORE, CDOStoreImpl.class); - private InternalCDOView view; + private final InternalCDOView view; public CDOStoreImpl(InternalCDOView view) { @@ -91,16 +91,25 @@ public final class CDOStoreImpl implements CDOStore */ public InternalEObject getContainer(InternalEObject eObject) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("getContainer({0})", cdoObject); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("getContainer({0})", cdoObject); //$NON-NLS-1$ + } - InternalCDORevision revision = readRevision(cdoObject); - return (InternalEObject)convertIDToObject(view, cdoObject, null, -1, revision.getContainerID()); + InternalCDORevision revision = readRevision(cdoObject); + return (InternalEObject)convertIDToObject(view, cdoObject, null, -1, revision.getContainerID()); + } + finally + { + view.unlockView(); + } } } @@ -109,16 +118,25 @@ public final class CDOStoreImpl implements CDOStore */ public int getContainingFeatureID(InternalEObject eObject) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("getContainingFeatureID({0})", cdoObject); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("getContainingFeatureID({0})", cdoObject); //$NON-NLS-1$ + } - InternalCDORevision revision = readRevision(cdoObject); - return revision.getContainingFeatureID(); + InternalCDORevision revision = readRevision(cdoObject); + return revision.getContainingFeatureID(); + } + finally + { + view.unlockView(); + } } } @@ -127,16 +145,25 @@ public final class CDOStoreImpl implements CDOStore */ public InternalEObject getResource(InternalEObject eObject) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("getResource({0})", cdoObject); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("getResource({0})", cdoObject); //$NON-NLS-1$ + } - InternalCDORevision revision = readRevision(cdoObject); - return (InternalEObject)convertIDToObject(view, cdoObject, null, -1, revision.getResourceID()); + InternalCDORevision revision = readRevision(cdoObject); + return (InternalEObject)convertIDToObject(view, cdoObject, null, -1, revision.getResourceID()); + } + finally + { + view.unlockView(); + } } } @@ -153,24 +180,33 @@ public final class CDOStoreImpl implements CDOStore */ public Object get(InternalEObject eObject, EStructuralFeature feature, int index) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("get({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("get({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$ + } - CDOFeatureAnalyzer featureAnalyzer = view.options().getFeatureAnalyzer(); + CDOFeatureAnalyzer featureAnalyzer = view.options().getFeatureAnalyzer(); - featureAnalyzer.preTraverseFeature(cdoObject, feature, index); - InternalCDORevision revision = readRevision(cdoObject); + featureAnalyzer.preTraverseFeature(cdoObject, feature, index); + InternalCDORevision revision = readRevision(cdoObject); - Object value = revision.get(feature, index); - value = convertToEMF(eObject, revision, feature, index, value); + Object value = revision.get(feature, index); + value = convertToEMF(eObject, revision, feature, index, value); - featureAnalyzer.postTraverseFeature(cdoObject, feature, index, value); - return value; + featureAnalyzer.postTraverseFeature(cdoObject, feature, index, value); + return value; + } + finally + { + view.unlockView(); + } } } @@ -179,35 +215,44 @@ public final class CDOStoreImpl implements CDOStore */ public boolean isSet(InternalEObject eObject, EStructuralFeature feature) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) - { - TRACER.format("isSet({0}, {1})", cdoObject, feature); //$NON-NLS-1$ - } + view.lockView(); - InternalCDORevision revision = readRevision(cdoObject); - if (feature.isMany()) + try { - CDOList list = revision.getList(feature); - return list != null && !list.isEmpty(); - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("isSet({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + } - Object value = revision.getValue(feature); - if (feature.isUnsettable()) - { - return value != null; - } + InternalCDORevision revision = readRevision(cdoObject); + if (feature.isMany()) + { + CDOList list = revision.getList(feature); + return list != null && !list.isEmpty(); + } + + Object value = revision.getValue(feature); + if (feature.isUnsettable()) + { + return value != null; + } - if (value == null) + if (value == null) + { + return false; + } + + value = convertToEMF(eObject, revision, feature, NO_INDEX, value); + Object defaultValue = feature.getDefaultValue(); + return !ObjectUtil.equals(value, defaultValue); + } + finally { - return false; + view.unlockView(); } - - value = convertToEMF(eObject, revision, feature, NO_INDEX, value); - Object defaultValue = feature.getDefaultValue(); - return !ObjectUtil.equals(value, defaultValue); } } @@ -216,16 +261,25 @@ public final class CDOStoreImpl implements CDOStore */ public int size(InternalEObject eObject, EStructuralFeature feature) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("size({0}, {1})", cdoObject, feature); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("size({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + } - InternalCDORevision revision = readRevision(cdoObject); - return revision.size(feature); + InternalCDORevision revision = readRevision(cdoObject); + return revision.size(feature); + } + finally + { + view.unlockView(); + } } } @@ -234,16 +288,25 @@ public final class CDOStoreImpl implements CDOStore */ public boolean isEmpty(InternalEObject eObject, EStructuralFeature feature) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("isEmpty({0}, {1})", cdoObject, feature); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("isEmpty({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + } - InternalCDORevision revision = readRevision(cdoObject); - return revision.isEmpty(feature); + InternalCDORevision revision = readRevision(cdoObject); + return revision.isEmpty(feature); + } + finally + { + view.unlockView(); + } } } @@ -252,26 +315,35 @@ public final class CDOStoreImpl implements CDOStore */ public boolean contains(InternalEObject eObject, EStructuralFeature feature, Object value) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("contains({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("contains({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$ + } - Object convertedValue = convertToCDO(cdoObject, feature, value); + Object convertedValue = convertToCDO(cdoObject, feature, value); - InternalCDORevision revision = readRevision(cdoObject); - boolean result = revision.contains(feature, convertedValue); + InternalCDORevision revision = readRevision(cdoObject); + boolean result = revision.contains(feature, convertedValue); - // Special handling of detached (TRANSIENT) objects, see bug 354395 - if (!result && value != convertedValue && value instanceof EObject) + // Special handling of detached (TRANSIENT) objects, see bug 354395 + if (!result && value != convertedValue && value instanceof EObject) + { + result = revision.contains(feature, value); + } + + return result; + } + finally { - result = revision.contains(feature, value); + view.unlockView(); } - - return result; } } @@ -280,18 +352,27 @@ public final class CDOStoreImpl implements CDOStore */ public int indexOf(InternalEObject eObject, EStructuralFeature feature, Object value) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("indexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("indexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$ + } - value = convertToCDO(cdoObject, feature, value); + value = convertToCDO(cdoObject, feature, value); - InternalCDORevision revision = readRevision(cdoObject); - return revision.indexOf(feature, value); + InternalCDORevision revision = readRevision(cdoObject); + return revision.indexOf(feature, value); + } + finally + { + view.unlockView(); + } } } @@ -300,18 +381,27 @@ public final class CDOStoreImpl implements CDOStore */ public int lastIndexOf(InternalEObject eObject, EStructuralFeature feature, Object value) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("lastIndexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("lastIndexOf({0}, {1}, {2})", cdoObject, feature, value); //$NON-NLS-1$ + } - value = convertToCDO(cdoObject, feature, value); + value = convertToCDO(cdoObject, feature, value); - InternalCDORevision revision = readRevision(cdoObject); - return revision.lastIndexOf(feature, value); + InternalCDORevision revision = readRevision(cdoObject); + return revision.lastIndexOf(feature, value); + } + finally + { + view.unlockView(); + } } } @@ -320,16 +410,25 @@ public final class CDOStoreImpl implements CDOStore */ public int hashCode(InternalEObject eObject, EStructuralFeature feature) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("hashCode({0}, {1})", cdoObject, feature); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("hashCode({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + } - InternalCDORevision revision = readRevision(cdoObject); - return revision.hashCode(feature); + InternalCDORevision revision = readRevision(cdoObject); + return revision.hashCode(feature); + } + finally + { + view.unlockView(); + } } } @@ -338,32 +437,41 @@ public final class CDOStoreImpl implements CDOStore */ public Object[] toArray(InternalEObject eObject, EStructuralFeature feature) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) - { - TRACER.format("toArray({0}, {1})", cdoObject, feature); //$NON-NLS-1$ - } + view.lockView(); - InternalCDORevision revision = readRevision(cdoObject); - Object[] result = revision.toArray(feature); - for (int i = 0; i < result.length; i++) + try { - result[i] = convertToEMF(eObject, revision, feature, i, result[i]); - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("toArray({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + } + + InternalCDORevision revision = readRevision(cdoObject); + Object[] result = revision.toArray(feature); + for (int i = 0; i < result.length; i++) + { + result[i] = convertToEMF(eObject, revision, feature, i, result[i]); + } - // // TODO Clarify feature maps - // if (feature instanceof EReference) - // { - // for (int i = 0; i < result.length; i++) - // { - // result[i] = resolveProxy(revision, feature, i, result[i]); - // result[i] = convertIdToObject(cdoObject.cdoView(), eObject, feature, i, result[i]); - // } - // } + // // TODO Clarify feature maps + // if (feature instanceof EReference) + // { + // for (int i = 0; i < result.length; i++) + // { + // result[i] = resolveProxy(revision, feature, i, result[i]); + // result[i] = convertIdToObject(cdoObject.cdoView(), eObject, feature, i, result[i]); + // } + // } - return result; + return result; + } + finally + { + view.unlockView(); + } } } @@ -373,23 +481,32 @@ public final class CDOStoreImpl implements CDOStore @SuppressWarnings("unchecked") public <T> T[] toArray(InternalEObject eObject, EStructuralFeature feature, T[] a) { - synchronized (view) + synchronized (view.getViewMonitor()) { - Object[] array = toArray(eObject, feature); - int size = array.length; + view.lockView(); - if (a.length < size) + try { - a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); - } + Object[] array = toArray(eObject, feature); + int size = array.length; + + if (a.length < size) + { + a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); + } - System.arraycopy(array, 0, a, 0, size); - if (a.length > size) + System.arraycopy(array, 0, a, 0, size); + if (a.length > size) + { + a[size] = null; + } + + return a; + } + finally { - a[size] = null; + view.unlockView(); } - - return a; } } @@ -399,19 +516,29 @@ public final class CDOStoreImpl implements CDOStore public void setContainer(InternalEObject eObject, CDOResource newResource, InternalEObject newEContainer, int newContainerFeatureID) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("setContainer({0}, {1}, {2}, {3})", cdoObject, newResource, newEContainer, newContainerFeatureID); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("setContainer({0}, {1}, {2}, {3})", cdoObject, newResource, newEContainer, //$NON-NLS-1$ + newContainerFeatureID); + } - Object newContainerID = newEContainer == null ? CDOID.NULL : view.convertObjectToID(newEContainer, true); - CDOID newResourceID = newResource == null ? CDOID.NULL : newResource.cdoID(); + Object newContainerID = newEContainer == null ? CDOID.NULL : view.convertObjectToID(newEContainer, true); + CDOID newResourceID = newResource == null ? CDOID.NULL : newResource.cdoID(); - CDOFeatureDelta delta = new CDOContainerFeatureDeltaImpl(newResourceID, newContainerID, newContainerFeatureID); - writeRevision(cdoObject, delta); + CDOFeatureDelta delta = new CDOContainerFeatureDeltaImpl(newResourceID, newContainerID, newContainerFeatureID); + writeRevision(cdoObject, delta); + } + finally + { + view.unlockView(); + } } } @@ -420,25 +547,34 @@ public final class CDOStoreImpl implements CDOStore */ public Object set(InternalEObject eObject, EStructuralFeature feature, int index, Object value) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("set({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("set({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$ + } - value = convertToCDO(cdoObject, feature, value); + value = convertToCDO(cdoObject, feature, value); - // TODO: Use writeRevision() result!! - InternalCDORevision oldRevision = readRevision(cdoObject); - Object oldValue = oldRevision.get(feature, index); - oldValue = convertToEMF(eObject, oldRevision, feature, index, oldValue); + // TODO: Use writeRevision() result!! + InternalCDORevision oldRevision = readRevision(cdoObject); + Object oldValue = oldRevision.get(feature, index); + oldValue = convertToEMF(eObject, oldRevision, feature, index, oldValue); - CDOFeatureDelta delta = new CDOSetFeatureDeltaImpl(feature, index, value, oldValue); - writeRevision(cdoObject, delta); + CDOFeatureDelta delta = new CDOSetFeatureDeltaImpl(feature, index, value, oldValue); + writeRevision(cdoObject, delta); - return oldValue; + return oldValue; + } + finally + { + view.unlockView(); + } } } @@ -447,27 +583,36 @@ public final class CDOStoreImpl implements CDOStore */ public void unset(InternalEObject eObject, EStructuralFeature feature) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) - { - TRACER.format("unset({0}, {1})", cdoObject, feature); //$NON-NLS-1$ - } + view.lockView(); - if (feature.isMany()) + try { - Object object = cdoObject.eGet(feature); - if (object instanceof List<?> && !CDOUtil.isLegacyObject(cdoObject)) + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) { - List<?> list = (List<?>)object; - list.clear(); + TRACER.format("unset({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + } + + if (feature.isMany()) + { + Object object = cdoObject.eGet(feature); + if (object instanceof List<?> && !CDOUtil.isLegacyObject(cdoObject)) + { + List<?> list = (List<?>)object; + list.clear(); + } + } + else + { + CDOFeatureDelta delta = new CDOUnsetFeatureDeltaImpl(feature); + writeRevision(cdoObject, delta); } } - else + finally { - CDOFeatureDelta delta = new CDOUnsetFeatureDeltaImpl(feature); - writeRevision(cdoObject, delta); + view.unlockView(); } } } @@ -477,18 +622,27 @@ public final class CDOStoreImpl implements CDOStore */ public void add(InternalEObject eObject, EStructuralFeature feature, int index, Object value) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("add({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("add({0}, {1}, {2}, {3})", cdoObject, feature, index, value); //$NON-NLS-1$ + } - value = convertToCDO(cdoObject, feature, value); + value = convertToCDO(cdoObject, feature, value); - CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value); - writeRevision(cdoObject, delta); + CDOFeatureDelta delta = new CDOAddFeatureDeltaImpl(feature, index, value); + writeRevision(cdoObject, delta); + } + finally + { + view.unlockView(); + } } } @@ -497,18 +651,27 @@ public final class CDOStoreImpl implements CDOStore */ public Object remove(InternalEObject eObject, EStructuralFeature feature, int index) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("remove({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("remove({0}, {1}, {2})", cdoObject, feature, index); //$NON-NLS-1$ + } - Object oldValue = getOldListValue(eObject, cdoObject, feature, index); + Object oldValue = getOldListValue(eObject, cdoObject, feature, index); - removeElement(cdoObject, feature, index); - return oldValue; + removeElement(cdoObject, feature, index); + return oldValue; + } + finally + { + view.unlockView(); + } } } @@ -517,20 +680,29 @@ public final class CDOStoreImpl implements CDOStore */ public Object move(InternalEObject eObject, EStructuralFeature feature, int target, int source) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("move({0}, {1}, {2}, {3})", cdoObject, feature, target, source); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("move({0}, {1}, {2}, {3})", cdoObject, feature, target, source); //$NON-NLS-1$ + } - Object oldValue = getOldListValue(eObject, cdoObject, feature, source); + Object oldValue = getOldListValue(eObject, cdoObject, feature, source); - CDOFeatureDelta delta = new CDOMoveFeatureDeltaImpl(feature, target, source); - writeRevision(cdoObject, delta); + CDOFeatureDelta delta = new CDOMoveFeatureDeltaImpl(feature, target, source); + writeRevision(cdoObject, delta); - return oldValue; + return oldValue; + } + finally + { + view.unlockView(); + } } } @@ -539,16 +711,25 @@ public final class CDOStoreImpl implements CDOStore */ public void clear(InternalEObject eObject, EStructuralFeature feature) { - synchronized (view) + synchronized (view.getViewMonitor()) { - InternalCDOObject cdoObject = getCDOObject(eObject); - if (TRACER.isEnabled()) + view.lockView(); + + try { - TRACER.format("clear({0}, {1})", cdoObject, feature); //$NON-NLS-1$ - } + InternalCDOObject cdoObject = getCDOObject(eObject); + if (TRACER.isEnabled()) + { + TRACER.format("clear({0}, {1})", cdoObject, feature); //$NON-NLS-1$ + } - CDOFeatureDelta delta = new CDOClearFeatureDeltaImpl(feature); - writeRevision(cdoObject, delta); + CDOFeatureDelta delta = new CDOClearFeatureDeltaImpl(feature); + writeRevision(cdoObject, delta); + } + finally + { + view.unlockView(); + } } } @@ -568,16 +749,25 @@ public final class CDOStoreImpl implements CDOStore */ public Object resolveProxy(InternalCDORevision revision, EStructuralFeature feature, int index, Object value) { - synchronized (view) + synchronized (view.getViewMonitor()) { - if (value instanceof CDOElementProxy) + view.lockView(); + + try { - // Resolve proxy - CDOElementProxy proxy = (CDOElementProxy)value; - value = view.getSession().resolveElementProxy(revision, feature, index, proxy.getIndex()); - } + if (value instanceof CDOElementProxy) + { + // Resolve proxy + CDOElementProxy proxy = (CDOElementProxy)value; + value = view.getSession().resolveElementProxy(revision, feature, index, proxy.getIndex()); + } - return value; + return value; + } + finally + { + view.unlockView(); + } } } @@ -586,37 +776,46 @@ public final class CDOStoreImpl implements CDOStore */ public Object convertToCDO(InternalCDOObject object, EStructuralFeature feature, Object value) { - synchronized (view) + if (value != null) { - if (value != null) + synchronized (view.getViewMonitor()) { - if (feature instanceof EReference) - { - value = view.convertObjectToID(value, true); - } - else if (FeatureMapUtil.isFeatureMap(feature)) + view.lockView(); + + try { - FeatureMap.Entry entry = (FeatureMap.Entry)value; - EStructuralFeature innerFeature = entry.getEStructuralFeature(); - Object innerValue = entry.getValue(); - Object convertedValue = view.convertObjectToID(innerValue); - if (convertedValue != innerValue) + if (feature instanceof EReference) { - value = CDORevisionUtil.createFeatureMapEntry(innerFeature, convertedValue); + value = view.convertObjectToID(value, true); } - } - else - { - CDOType type = CDOModelUtil.getType(feature.getEType()); - if (type != null) + else if (FeatureMapUtil.isFeatureMap(feature)) { - value = type.convertToCDO(feature.getEType(), value); + FeatureMap.Entry entry = (FeatureMap.Entry)value; + EStructuralFeature innerFeature = entry.getEStructuralFeature(); + Object innerValue = entry.getValue(); + Object convertedValue = view.convertObjectToID(innerValue); + if (convertedValue != innerValue) + { + value = CDORevisionUtil.createFeatureMapEntry(innerFeature, convertedValue); + } } + else + { + CDOType type = CDOModelUtil.getType(feature.getEType()); + if (type != null) + { + value = type.convertToCDO(feature.getEType(), value); + } + } + } + finally + { + view.unlockView(); } } - - return value; } + + return value; } /** @@ -625,60 +824,69 @@ public final class CDOStoreImpl implements CDOStore public Object convertToEMF(EObject eObject, InternalCDORevision revision, EStructuralFeature feature, int index, Object value) { - synchronized (view) + if (value != null) { - if (value != null) + synchronized (view.getViewMonitor()) { - if (feature.isMany()) + view.lockView(); + + try { - if (index == EStore.NO_INDEX) + if (feature.isMany()) { - return value; + if (index == EStore.NO_INDEX) + { + return value; + } + + value = resolveProxy(revision, feature, index, value); + if (value instanceof CDOID) + { + CDOID id = (CDOID)value; + CDOList list = revision.getList(feature); + CDORevisionPrefetchingPolicy policy = view.options().getRevisionPrefetchingPolicy(); + InternalCDORevisionManager revisionManager = view.getSession().getRevisionManager(); + List<CDOID> listOfIDs = policy.loadAhead(revisionManager, view, eObject, feature, list, index, id); + if (!listOfIDs.isEmpty()) + { + int initialChunkSize = view.getSession().options().getCollectionLoadingPolicy().getInitialChunkSize(); + revisionManager.getRevisions(listOfIDs, view, initialChunkSize, CDORevision.DEPTH_NONE, true); + } + } } - value = resolveProxy(revision, feature, index, value); - if (value instanceof CDOID) + if (feature instanceof EReference) + { + value = convertIDToObject(view, eObject, feature, index, value); + } + else if (FeatureMapUtil.isFeatureMap(feature)) { - CDOID id = (CDOID)value; - CDOList list = revision.getList(feature); - CDORevisionPrefetchingPolicy policy = view.options().getRevisionPrefetchingPolicy(); - InternalCDORevisionManager revisionManager = view.getSession().getRevisionManager(); - List<CDOID> listOfIDs = policy.loadAhead(revisionManager, view, eObject, feature, list, index, id); - if (!listOfIDs.isEmpty()) + FeatureMap.Entry entry = (FeatureMap.Entry)value; + EStructuralFeature innerFeature = entry.getEStructuralFeature(); + Object innerValue = entry.getValue(); + Object convertedValue = convertIDToObject(view, eObject, feature, index, innerValue); + if (convertedValue != innerValue) { - int initialChunkSize = view.getSession().options().getCollectionLoadingPolicy().getInitialChunkSize(); - revisionManager.getRevisions(listOfIDs, view, initialChunkSize, CDORevision.DEPTH_NONE, true); + value = FeatureMapUtil.createEntry(innerFeature, convertedValue); } } - } - - if (feature instanceof EReference) - { - value = convertIDToObject(view, eObject, feature, index, value); - } - else if (FeatureMapUtil.isFeatureMap(feature)) - { - FeatureMap.Entry entry = (FeatureMap.Entry)value; - EStructuralFeature innerFeature = entry.getEStructuralFeature(); - Object innerValue = entry.getValue(); - Object convertedValue = convertIDToObject(view, eObject, feature, index, innerValue); - if (convertedValue != innerValue) + else { - value = FeatureMapUtil.createEntry(innerFeature, convertedValue); + CDOType type = CDOModelUtil.getType(feature.getEType()); + if (type != null) + { + value = type.convertToEMF(feature.getEType(), value); + } } } - else + finally { - CDOType type = CDOModelUtil.getType(feature.getEType()); - if (type != null) - { - value = type.convertToEMF(feature.getEType(), value); - } + view.unlockView(); } } - - return value; } + + return value; } private Object convertIDToObject(InternalCDOView view, EObject eObject, EStructuralFeature feature, int index, diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java index c7363cf9b1..721c2bbebc 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java @@ -34,6 +34,7 @@ import org.eclipse.emf.cdo.common.revision.CDORevisionsLoadedEvent; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.common.util.CDOCommonUtil; import org.eclipse.emf.cdo.common.util.CDOException; +import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; @@ -116,6 +117,7 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; /** * @author Eike Stepper @@ -149,14 +151,15 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv /** * @since 2.0 */ - public CDOViewImpl(CDOBranch branch, long timeStamp) + public CDOViewImpl(CDOSession session, CDOBranch branch, long timeStamp) { - super(branch.getPoint(timeStamp)); + super(session, branch.getPoint(timeStamp)); options = createOptions(); } - public CDOViewImpl(String durableLockingID) + public CDOViewImpl(CDOSession session, String durableLockingID) { + super(session); this.durableLockingID = durableLockingID; options = createOptions(); } @@ -210,68 +213,81 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv return session.getSessionID(); } - public synchronized boolean setBranchPoint(CDOBranchPoint branchPoint, IProgressMonitor progressMonitor) + public boolean setBranchPoint(CDOBranchPoint branchPoint, IProgressMonitor progressMonitor) { checkActive(); - branchPoint = adjustBranchPoint(branchPoint); - - long timeStamp = branchPoint.getTimeStamp(); - long creationTimeStamp = session.getRepositoryInfo().getCreationTime(); - if (timeStamp != UNSPECIFIED_DATE && timeStamp < creationTimeStamp) + synchronized (getViewMonitor()) { - throw new IllegalArgumentException(MessageFormat.format("timeStamp ({0}) < repository creation time ({1})", //$NON-NLS-1$ - CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(creationTimeStamp))); - } + lockView(); - CDOBranchPoint oldBranchPoint = CDOBranchUtil.copyBranchPoint(getBranchPoint()); - if (branchPoint.equals(oldBranchPoint)) - { - return false; - } + try + { + branchPoint = adjustBranchPoint(branchPoint); - if (TRACER.isEnabled()) - { - TRACER.format("Changing view target to {0}", branchPoint); //$NON-NLS-1$ - } + long timeStamp = branchPoint.getTimeStamp(); + long creationTimeStamp = session.getRepositoryInfo().getCreationTime(); + if (timeStamp != UNSPECIFIED_DATE && timeStamp < creationTimeStamp) + { + throw new IllegalArgumentException(MessageFormat.format("timeStamp ({0}) < repository creation time ({1})", //$NON-NLS-1$ + CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(creationTimeStamp))); + } - Map<CDOID, InternalCDORevision> oldRevisions = CDOIDUtil.createMap(); - List<CDORevisionKey> allChangedObjects = new ArrayList<CDORevisionKey>(); - List<CDOIDAndVersion> allDetachedObjects = new ArrayList<CDOIDAndVersion>(); + CDOBranchPoint oldBranchPoint = CDOBranchUtil.copyBranchPoint(getBranchPoint()); + if (branchPoint.equals(oldBranchPoint)) + { + return false; + } - List<InternalCDOObject> invalidObjects = getInvalidObjects(branchPoint); - for (InternalCDOObject object : invalidObjects) - { - InternalCDORevision revision = object.cdoRevision(); - if (revision != null) - { - oldRevisions.put(object.cdoID(), revision); - } - } + if (TRACER.isEnabled()) + { + TRACER.format("Changing view target to {0}", branchPoint); //$NON-NLS-1$ + } - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - OMMonitor monitor = progressMonitor != null ? new EclipseMonitor(progressMonitor) : null; - sessionProtocol.switchTarget(viewID, branchPoint, invalidObjects, allChangedObjects, allDetachedObjects, monitor); + Map<CDOID, InternalCDORevision> oldRevisions = CDOIDUtil.createMap(); + List<CDORevisionKey> allChangedObjects = new ArrayList<CDORevisionKey>(); + List<CDOIDAndVersion> allDetachedObjects = new ArrayList<CDOIDAndVersion>(); - basicSetBranchPoint(branchPoint); - CDOBranch branch = branchPoint.getBranch(); + List<InternalCDOObject> invalidObjects = getInvalidObjects(branchPoint); + for (InternalCDOObject object : invalidObjects) + { + InternalCDORevision revision = object.cdoRevision(); + if (revision != null) + { + oldRevisions.put(object.cdoID(), revision); + } + } - try - { - CDOStateMachine.SWITCHING_TARGET.set(Boolean.TRUE); - doInvalidate(branch, UNSPECIFIED_DATE, allChangedObjects, allDetachedObjects, oldRevisions, true); - } - finally - { - CDOStateMachine.SWITCHING_TARGET.remove(); - } + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + OMMonitor monitor = progressMonitor != null ? new EclipseMonitor(progressMonitor) : null; + sessionProtocol.switchTarget(viewID, branchPoint, invalidObjects, allChangedObjects, allDetachedObjects, + monitor); - IListener[] listeners = getListeners(); - if (listeners != null) - { - fireViewTargetChangedEvent(oldBranchPoint, listeners); - } + basicSetBranchPoint(branchPoint); + CDOBranch branch = branchPoint.getBranch(); - return true; + try + { + CDOStateMachine.SWITCHING_TARGET.set(Boolean.TRUE); + doInvalidate(branch, UNSPECIFIED_DATE, allChangedObjects, allDetachedObjects, oldRevisions, true); + } + finally + { + CDOStateMachine.SWITCHING_TARGET.remove(); + } + + IListener[] listeners = getListeners(); + if (listeners != null) + { + fireViewTargetChangedEvent(oldBranchPoint, listeners); + } + + return true; + } + finally + { + unlockView(); + } + } } private List<InternalCDOObject> getInvalidObjects(CDOBranchPoint branchPoint) @@ -300,107 +316,118 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } /** - * @throws InterruptedException * @since 2.0 */ - public synchronized void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout) + public void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout) throws InterruptedException { lockObjects(objects, lockType, timeout, false); } - public synchronized void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout, - boolean recursive) throws InterruptedException + public void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout, boolean recursive) + throws InterruptedException { checkActive(); checkState(getTimeStamp() == UNSPECIFIED_DATE, "Locking not supported for historial views"); - Set<? extends CDOObject> uniqueObjects = getSet(objects); - int size = uniqueObjects.size(); - - List<CDORevisionKey> revisionKeys = new ArrayList<CDORevisionKey>(size); - List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(size); - - for (CDOObject object : uniqueObjects) + synchronized (getViewMonitor()) { - if (FSMUtil.isNew(object)) - { - CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, true); - locksOnNewObjects.add(lockState); - } - else + lockView(); + + try { - InternalCDORevision revision = getRevision(object); - if (revision != null) - { - revisionKeys.add(revision); - } - } - } + Set<? extends CDOObject> uniqueObjects = getSet(objects); + int size = uniqueObjects.size(); - LockObjectsResult result = null; - if (!revisionKeys.isEmpty()) - { - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - result = sessionProtocol.lockObjects2(revisionKeys, viewID, getBranch(), lockType, recursive, timeout); + List<CDORevisionKey> revisionKeys = new ArrayList<CDORevisionKey>(size); + List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(size); - if (!result.isSuccessful()) - { - if (result.isTimedOut()) + for (CDOObject object : uniqueObjects) { - throw new LockTimeoutException(); + if (FSMUtil.isNew(object)) + { + CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, true); + locksOnNewObjects.add(lockState); + } + else + { + InternalCDORevision revision = getRevision(object); + if (revision != null) + { + revisionKeys.add(revision); + } + } } - CDORevisionKey[] staleRevisions = result.getStaleRevisions(); - if (staleRevisions != null) + LockObjectsResult result = null; + if (!revisionKeys.isEmpty()) { - throw new StaleRevisionLockException(staleRevisions); - } + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + result = sessionProtocol.lockObjects2(revisionKeys, viewID, getBranch(), lockType, recursive, timeout); - throw new AssertionError("Unexpected lock result state"); - } + if (!result.isSuccessful()) + { + if (result.isTimedOut()) + { + throw new LockTimeoutException(); + } - if (result.isWaitForUpdate()) - { - if (!session.options().isPassiveUpdateEnabled()) - { - throw new AssertionError( - "Lock result requires client to wait, but client does not have passiveUpdates enabled"); - } + CDORevisionKey[] staleRevisions = result.getStaleRevisions(); + if (staleRevisions != null) + { + throw new StaleRevisionLockException(staleRevisions); + } - long requiredTimestamp = result.getRequiredTimestamp(); - if (!waitForUpdate(requiredTimestamp, 10000L)) - { - throw new AssertionError("Lock result requires client to wait for commit " + requiredTimestamp - + ", but client did not receive invalidations after " + lastUpdateTime); - } + throw new AssertionError("Unexpected lock result state"); + } - InternalCDOSession session = this.session; - InternalCDORevisionManager revisionManager = session.getRevisionManager(); + if (result.isWaitForUpdate()) + { + if (!session.options().isPassiveUpdateEnabled()) + { + throw new AssertionError( + "Lock result requires client to wait, but client does not have passiveUpdates enabled"); + } - for (CDORevisionKey requiredKey : result.getStaleRevisions()) - { - CDOID id = requiredKey.getID(); - InternalCDOObject object = getObject(id); + long requiredTimestamp = result.getRequiredTimestamp(); + if (!waitForUpdate(requiredTimestamp, 10000L)) + { + throw new AssertionError("Lock result requires client to wait for commit " + requiredTimestamp + + ", but client did not receive invalidations after " + lastUpdateTime); + } - CDORevision revision = object.cdoRevision(true); - if (!requiredKey.equals(revision)) - { - InternalCDORevision requiredRevision = revisionManager.getRevisionByVersion(id, requiredKey, - CDORevision.UNCHUNKED, true); - InternalCDORevisionDelta revisionDelta = requiredRevision.compare(revision); - CDOStateMachine.INSTANCE.invalidate(object, revisionDelta); + InternalCDOSession session = this.session; + InternalCDORevisionManager revisionManager = session.getRevisionManager(); + + for (CDORevisionKey requiredKey : result.getStaleRevisions()) + { + CDOID id = requiredKey.getID(); + InternalCDOObject object = getObject(id); + + CDORevision revision = object.cdoRevision(true); + if (!requiredKey.equals(revision)) + { + InternalCDORevision requiredRevision = revisionManager.getRevisionByVersion(id, requiredKey, + CDORevision.UNCHUNKED, true); + InternalCDORevisionDelta revisionDelta = requiredRevision.compare(revision); + CDOStateMachine.INSTANCE.invalidate(object, revisionDelta); + } + } } } - } - } - CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); - updateLockStates(locksOnNewObjectsArray); + CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); + updateLockStates(locksOnNewObjectsArray); - if (result != null) - { - updateAndNotifyLockStates(Operation.LOCK, lockType, result.getTimestamp(), result.getNewLockStates()); + if (result != null) + { + updateAndNotifyLockStates(Operation.LOCK, lockType, result.getTimestamp(), result.getNewLockStates()); + } + } + finally + { + unlockView(); + } } } @@ -554,7 +581,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv /** * @since 2.0 */ - public synchronized void unlockObjects(Collection<? extends CDOObject> objects, LockType lockType) + public void unlockObjects(Collection<? extends CDOObject> objects, LockType lockType) { unlockObjects(objects, lockType, false); } @@ -563,48 +590,59 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv * Note: This may get called with objects == null, and lockType == null, which is a request to remove all locks on all * objects in this view. */ - public synchronized void unlockObjects(Collection<? extends CDOObject> objects, LockType lockType, boolean recursive) + public void unlockObjects(Collection<? extends CDOObject> objects, LockType lockType, boolean recursive) { checkActive(); - - List<CDOID> objectIDs = null; - List<CDOLockState> locksOnNewObjects = new LinkedList<CDOLockState>(); - - if (objects != null) + synchronized (getViewMonitor()) { - objectIDs = new ArrayList<CDOID>(); + lockView(); - for (CDOObject object : getSet(objects)) + try { - if (FSMUtil.isNew(object)) + List<CDOID> objectIDs = null; + List<CDOLockState> locksOnNewObjects = new LinkedList<CDOLockState>(); + + if (objects != null) { - CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, false); - locksOnNewObjects.add(lockState); + objectIDs = new ArrayList<CDOID>(); + + for (CDOObject object : getSet(objects)) + { + if (FSMUtil.isNew(object)) + { + CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, false); + locksOnNewObjects.add(lockState); + } + else + { + objectIDs.add(object.cdoID()); + } + } } else { - objectIDs.add(object.cdoID()); + locksOnNewObjects.addAll(createUnlockedLockStatesForAllNewObjects()); } - } - } - else - { - locksOnNewObjects.addAll(createUnlockedLockStatesForAllNewObjects()); - } - UnlockObjectsResult result = null; - if (objectIDs == null || !objectIDs.isEmpty()) - { - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - result = sessionProtocol.unlockObjects2(this, objectIDs, lockType, recursive); - } + UnlockObjectsResult result = null; + if (objectIDs == null || !objectIDs.isEmpty()) + { + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + result = sessionProtocol.unlockObjects2(this, objectIDs, lockType, recursive); + } - CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); - updateLockStates(locksOnNewObjectsArray); + CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); + updateLockStates(locksOnNewObjectsArray); - if (result != null) - { - updateAndNotifyLockStates(Operation.UNLOCK, lockType, result.getTimestamp(), result.getNewLockStates()); + if (result != null) + { + updateAndNotifyLockStates(Operation.UNLOCK, lockType, result.getTimestamp(), result.getNewLockStates()); + } + } + finally + { + unlockView(); + } } } @@ -621,7 +659,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv /** * @since 2.0 */ - public synchronized void unlockObjects() + public void unlockObjects() { unlockObjects(null, null); } @@ -629,11 +667,23 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv /** * @since 2.0 */ - public synchronized boolean isObjectLocked(CDOObject object, LockType lockType, boolean byOthers) + public boolean isObjectLocked(CDOObject object, LockType lockType, boolean byOthers) { checkActive(); - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - return sessionProtocol.isObjectLocked(this, object, lockType, byOthers); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + return sessionProtocol.isObjectLocked(this, object, lockType, byOthers); + } + finally + { + unlockView(); + } + } } public boolean isDurableView() @@ -641,9 +691,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv return durableLockingID != null; } - public synchronized String getDurableLockingID() + public String getDurableLockingID() { - return durableLockingID; + synchronized (getViewMonitor()) + { + lockView(); // TODO ??? + + try + { + return durableLockingID; + } + finally + { + unlockView(); + } + } } @Deprecated @@ -664,15 +726,24 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv try { - synchronized (this) + synchronized (getViewMonitor()) { - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - if (durableLockingID == null) + lockView(); + + try { - durableLockingID = sessionProtocol.changeLockArea(this, true); - } + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + if (durableLockingID == null) + { + durableLockingID = sessionProtocol.changeLockArea(this, true); + } - return durableLockingID; + return durableLockingID; + } + finally + { + unlockView(); + } } } finally @@ -687,19 +758,28 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv try { - synchronized (this) + synchronized (getViewMonitor()) { - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - if (durableLockingID != null) - { - sessionProtocol.changeLockArea(this, false); - durableLockingID = null; + lockView(); - if (releaseLocks) + try + { + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + if (durableLockingID != null) { - unlockObjects(); + sessionProtocol.changeLockArea(this, false); + durableLockingID = null; + + if (releaseLocks) + { + unlockObjects(); + } } } + finally + { + unlockView(); + } } } finally @@ -736,18 +816,42 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv * @since 2.0 */ @Deprecated - public synchronized CDOFeatureAnalyzer getFeatureAnalyzer() + public CDOFeatureAnalyzer getFeatureAnalyzer() { - return options().getFeatureAnalyzer(); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return options().getFeatureAnalyzer(); + } + finally + { + unlockView(); + } + } } /** * @since 2.0 */ @Deprecated - public synchronized void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer) + public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer) { - options.setFeatureAnalyzer(featureAnalyzer); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + options.setFeatureAnalyzer(featureAnalyzer); + } + finally + { + unlockView(); + } + } } /** @@ -764,127 +868,188 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv throw new ReadOnlyException(MessageFormat.format(Messages.getString("CDOViewImpl.0"), this)); //$NON-NLS-1$ } - public synchronized InternalCDORevision getRevision(CDOID id, boolean loadOnDemand) + public InternalCDORevision getRevision(CDOID id, boolean loadOnDemand) { - InternalCDORevisionManager revisionManager = session.getRevisionManager(); - int initialChunkSize = session.options().getCollectionLoadingPolicy().getInitialChunkSize(); - CDOBranchPoint branchPoint = getBranchPointForID(id); - return revisionManager.getRevision(id, branchPoint, initialChunkSize, CDORevision.DEPTH_NONE, loadOnDemand); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + InternalCDORevisionManager revisionManager = session.getRevisionManager(); + int initialChunkSize = session.options().getCollectionLoadingPolicy().getInitialChunkSize(); + CDOBranchPoint branchPoint = getBranchPointForID(id); + return revisionManager.getRevision(id, branchPoint, initialChunkSize, CDORevision.DEPTH_NONE, loadOnDemand); + } + finally + { + unlockView(); + } + } } @Override - public synchronized void remapObject(CDOID oldID) + public void remapObject(CDOID oldID) { - InternalCDOObject object = getObject(oldID, false); - InternalCDOLockState oldLockState = (InternalCDOLockState)lockStates.remove(object); - if (oldLockState != null) - { - Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch - InternalCDOLockState newLockState = (InternalCDOLockState)CDOLockUtil.createLockState(lockedObject); - newLockState.updateFrom(oldLockState); - lockStates.put(object, newLockState); - } - else if (options().isLockStatePrefetchEnabled()) + synchronized (getViewMonitor()) { - Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch - CDOLockState newLockState = CDOLockUtil.createLockState(lockedObject); - lockStates.put(object, newLockState); - } + lockView(); + + try + { + InternalCDOObject object = getObject(oldID, false); + InternalCDOLockState oldLockState = (InternalCDOLockState)lockStates.remove(object); + if (oldLockState != null) + { + Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch + InternalCDOLockState newLockState = (InternalCDOLockState)CDOLockUtil.createLockState(lockedObject); + newLockState.updateFrom(oldLockState); + lockStates.put(object, newLockState); + } + else if (options().isLockStatePrefetchEnabled()) + { + Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch + CDOLockState newLockState = CDOLockUtil.createLockState(lockedObject); + lockStates.put(object, newLockState); + } - super.remapObject(oldID); + super.remapObject(oldID); + } + finally + { + unlockView(); + } + } } @Override - public synchronized InternalCDOObject removeObject(CDOID id) + public InternalCDOObject removeObject(CDOID id) { - InternalCDOObject removedObject = super.removeObject(id); - removeLockState(removedObject); - return removedObject; - } + synchronized (getViewMonitor()) + { + lockView(); - public synchronized CDOLockState[] getLockStates(Collection<CDOID> ids) - { - return getLockStates(ids, true); + try + { + InternalCDOObject removedObject = super.removeObject(id); + removeLockState(removedObject); + return removedObject; + } + finally + { + unlockView(); + } + } } - protected synchronized CDOLockState[] getLockStates(Collection<CDOID> ids, boolean loadOnDemand) + public CDOLockState[] getLockStates(Collection<CDOID> ids) { - List<CDOID> missing = new LinkedList<CDOID>(); - List<CDOLockState> lockStates = new LinkedList<CDOLockState>(); - List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(ids.size()); - - for (CDOID id : ids) + synchronized (getViewMonitor()) { - CDOLockState lockState = null; - InternalCDOObject object = getObject(id, false); - if (object != null) - { - lockState = this.lockStates.get(object); - } + lockView(); - if (lockState != null) - { - lockStates.add(lockState); - } - else if (loadOnDemand && object != null && FSMUtil.isNew(object)) + try { - Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch - CDOLockState defaultLockState = CDOLockUtil.createLockState(lockedObject); - locksOnNewObjects.add(defaultLockState); - lockStates.add(defaultLockState); + return getLockStates(ids, true); } - else + finally { - missing.add(id); + unlockView(); } } + } - if (loadOnDemand && (missing.size() > 0 || ids.isEmpty())) + protected CDOLockState[] getLockStates(Collection<CDOID> ids, boolean loadOnDemand) + { + synchronized (getViewMonitor()) { - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(viewID, missing, CDOLockState.DEPTH_NONE); - List<CDOLockState> newLockStateForCache = new ArrayList<CDOLockState>(loadedLockStates.length + missing.size()); - for (CDOLockState loadedLockState : loadedLockStates) - { - lockStates.add(loadedLockState); - newLockStateForCache.add(loadedLockState); - - CDOID cdoID = CDOIDUtil.getCDOID(loadedLockState.getLockedObject()); - if (cdoID != null) - { - missing.remove(cdoID); - } - } + lockView(); - for (CDOID missingLockStateForCDOID : missing) + try { - Object target; + List<CDOID> missing = new LinkedList<CDOID>(); + List<CDOLockState> lockStates = new LinkedList<CDOLockState>(); + List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(ids.size()); - InternalCDOObject object = getObject(missingLockStateForCDOID, false); - if (object != null) + for (CDOID id : ids) { - target = getLockTarget(object); // CDOID or CDOIDAndBranch + CDOLockState lockState = null; + InternalCDOObject object = getObject(id, false); + if (object != null) + { + lockState = this.lockStates.get(object); + } + + if (lockState != null) + { + lockStates.add(lockState); + } + else if (loadOnDemand && object != null && FSMUtil.isNew(object)) + { + Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch + CDOLockState defaultLockState = CDOLockUtil.createLockState(lockedObject); + locksOnNewObjects.add(defaultLockState); + lockStates.add(defaultLockState); + } + else + { + missing.add(id); + } } - else + + if (loadOnDemand && (missing.size() > 0 || ids.isEmpty())) { - target = missingLockStateForCDOID; + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(viewID, missing, CDOLockState.DEPTH_NONE); + List<CDOLockState> newLockStateForCache = new ArrayList<CDOLockState>( + loadedLockStates.length + missing.size()); + for (CDOLockState loadedLockState : loadedLockStates) + { + lockStates.add(loadedLockState); + newLockStateForCache.add(loadedLockState); + + CDOID cdoID = CDOIDUtil.getCDOID(loadedLockState.getLockedObject()); + if (cdoID != null) + { + missing.remove(cdoID); + } + } + + for (CDOID missingLockStateForCDOID : missing) + { + Object target; + + InternalCDOObject object = getObject(missingLockStateForCDOID, false); + if (object != null) + { + target = getLockTarget(object); // CDOID or CDOIDAndBranch + } + else + { + target = missingLockStateForCDOID; + } + + CDOLockState defaultLockState = CDOLockUtil.createLockState(target); + lockStates.add(defaultLockState); + newLockStateForCache.add(defaultLockState); + } + + if (options().isLockNotificationEnabled()) + { + updateLockStates(newLockStateForCache.toArray(new CDOLockState[newLockStateForCache.size()])); + } } - CDOLockState defaultLockState = CDOLockUtil.createLockState(target); - lockStates.add(defaultLockState); - newLockStateForCache.add(defaultLockState); - } + CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); + updateLockStates(locksOnNewObjectsArray); - if (options().isLockNotificationEnabled()) + return lockStates.toArray(new CDOLockState[lockStates.size()]); + } + finally { - updateLockStates(newLockStateForCache.toArray(new CDOLockState[newLockStateForCache.size()])); + unlockView(); } } - - CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); - updateLockStates(locksOnNewObjectsArray); - - return lockStates.toArray(new CDOLockState[lockStates.size()]); } protected CDOLockState removeLockState(CDOObject object) @@ -922,11 +1087,23 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv return this; } - public synchronized void prefetchRevisions(CDOID id, int depth) + public void prefetchRevisions(CDOID id, int depth) { checkArg(depth != CDORevision.DEPTH_NONE, "Prefetch depth must not be zero"); //$NON-NLS-1$ - int initialChunkSize = session.options().getCollectionLoadingPolicy().getInitialChunkSize(); - prefetchRevisions(id, depth, initialChunkSize); + synchronized (getViewMonitor()) + { + lockView(); + + try + { + int initialChunkSize = session.options().getCollectionLoadingPolicy().getInitialChunkSize(); + prefetchRevisions(id, depth, initialChunkSize); + } + finally + { + unlockView(); + } + } } protected void prefetchRevisions(CDOID id, int depth, int initialChunkSize) @@ -964,59 +1141,71 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } } - protected synchronized void doInvalidate(CDOBranch branch, long lastUpdateTime, - List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects, - Map<CDOID, InternalCDORevision> oldRevisions, boolean clearResourcePathCache) + protected void doInvalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, + List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, + boolean clearResourcePathCache) { - if (getTimeStamp() != UNSPECIFIED_DATE && CDOStateMachine.SWITCHING_TARGET.get() != Boolean.TRUE) + synchronized (getViewMonitor()) { - // Don't invalidate historical views unless during a branch point switch. - return; - } + lockView(); - try - { - // Also false for FailureCommitInfos (because of branch==null). Only setLastUpdateTime() is called below. - if (branch == getBranch()) + try { - if (clearResourcePathCache) + if (getTimeStamp() != UNSPECIFIED_DATE && CDOStateMachine.SWITCHING_TARGET.get() != Boolean.TRUE) { - clearResourcePathCacheIfNecessary(null); + // Don't invalidate historical views unless during a branch point switch. + return; } - List<CDORevisionDelta> deltas = new ArrayList<CDORevisionDelta>(); - Map<CDOObject, CDORevisionDelta> revisionDeltas = new HashMap<CDOObject, CDORevisionDelta>(); - Set<CDOObject> detachedObjects = new HashSet<CDOObject>(); + try + { + // Also false for FailureCommitInfos (because of branch==null). Only setLastUpdateTime() is called below. + if (branch == getBranch()) + { + if (clearResourcePathCache) + { + clearResourcePathCacheIfNecessary(null); + } + + List<CDORevisionDelta> deltas = new ArrayList<CDORevisionDelta>(); + Map<CDOObject, CDORevisionDelta> revisionDeltas = new HashMap<CDOObject, CDORevisionDelta>(); + Set<CDOObject> detachedObjects = new HashSet<CDOObject>(); + + Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = invalidate(allChangedObjects, + allDetachedObjects, deltas, revisionDeltas, detachedObjects); + handleConflicts(lastUpdateTime, conflicts, deltas); - Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = invalidate(allChangedObjects, - allDetachedObjects, deltas, revisionDeltas, detachedObjects); - handleConflicts(lastUpdateTime, conflicts, deltas); + sendInvalidationNotifications(revisionDeltas.keySet(), detachedObjects); + fireInvalidationEvent(lastUpdateTime, Collections.unmodifiableMap(revisionDeltas), + Collections.unmodifiableSet(detachedObjects)); - sendInvalidationNotifications(revisionDeltas.keySet(), detachedObjects); - fireInvalidationEvent(lastUpdateTime, Collections.unmodifiableMap(revisionDeltas), - Collections.unmodifiableSet(detachedObjects)); + // Then send the notifications. The deltas could have been modified by the conflict resolvers. + if (!deltas.isEmpty() || !detachedObjects.isEmpty()) + { + sendDeltaNotifications(deltas, detachedObjects, oldRevisions); + } - // Then send the notifications. The deltas could have been modified by the conflict resolvers. - if (!deltas.isEmpty() || !detachedObjects.isEmpty()) + fireAdaptersNotifiedEvent(lastUpdateTime); + } + } + catch (RuntimeException ex) { - sendDeltaNotifications(deltas, detachedObjects, oldRevisions); + if (isActive()) + { + fireEvent(new ThrowableEvent(this, ex)); + throw ex; + } + } + finally + { + setLastUpdateTime(lastUpdateTime); } - - fireAdaptersNotifiedEvent(lastUpdateTime); } - } - catch (RuntimeException ex) - { - if (isActive()) + finally { - fireEvent(new ThrowableEvent(this, ex)); - throw ex; + unlockView(); } } - finally - { - setLastUpdateTime(lastUpdateTime); - } } public ExecutorWorkSerializer getInvalidationRunner() @@ -1087,55 +1276,67 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv /** * @since 2.0 */ - public synchronized void sendDeltaNotifications(Collection<CDORevisionDelta> deltas, Set<CDOObject> detachedObjects, + public void sendDeltaNotifications(Collection<CDORevisionDelta> deltas, Set<CDOObject> detachedObjects, Map<CDOID, InternalCDORevision> oldRevisions) { - if (deltas != null) + synchronized (getViewMonitor()) { - CDONotificationBuilder builder = new CDONotificationBuilder(this); - Map<CDOID, InternalCDOObject> objects = getModifiableObjects(); - for (CDORevisionDelta delta : deltas) + lockView(); + + try { - CDOID id = delta.getID(); - InternalCDOObject object = objects.get(id); - if (object != null && object.eNotificationRequired()) + if (deltas != null) { - // if (!isLocked(object)) + CDONotificationBuilder builder = new CDONotificationBuilder(this); + Map<CDOID, InternalCDOObject> objects = getModifiableObjects(); + for (CDORevisionDelta delta : deltas) { - InternalCDORevision oldRevision = null; - if (oldRevisions != null) - { - oldRevision = oldRevisions.get(id); - } - - NotificationChain notification = builder.buildNotification(object, oldRevision, delta, detachedObjects); - if (notification != null) + CDOID id = delta.getID(); + InternalCDOObject object = objects.get(id); + if (object != null && object.eNotificationRequired()) { - notification.dispatch(); + // if (!isLocked(object)) + { + InternalCDORevision oldRevision = null; + if (oldRevisions != null) + { + oldRevision = oldRevisions.get(id); + } + + NotificationChain notification = builder.buildNotification(object, oldRevision, delta, detachedObjects); + if (notification != null) + { + notification.dispatch(); + } + } } } } - } - } - if (detachedObjects != null && !detachedObjects.isEmpty()) - { - if (options().isDetachmentNotificationEnabled()) - { - for (CDOObject detachedObject : detachedObjects) + if (detachedObjects != null && !detachedObjects.isEmpty()) { - InternalCDOObject object = (InternalCDOObject)detachedObject; - if (object.eNotificationRequired()) + if (options().isDetachmentNotificationEnabled()) { - // if (!isLocked(object)) + for (CDOObject detachedObject : detachedObjects) { - new CDODeltaNotificationImpl(object, CDONotification.DETACH_OBJECT, null, null, null).dispatch(); + InternalCDOObject object = (InternalCDOObject)detachedObject; + if (object.eNotificationRequired()) + { + // if (!isLocked(object)) + { + new CDODeltaNotificationImpl(object, CDONotification.DETACH_OBJECT, null, null, null).dispatch(); + } + } } } + + getChangeSubscriptionManager().handleDetachedObjects(detachedObjects); } } - - getChangeSubscriptionManager().handleDetachedObjects(detachedObjects); + finally + { + unlockView(); + } } } @@ -1169,62 +1370,122 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv /** * @since 2.0 */ - public synchronized void handleAddAdapter(InternalCDOObject eObject, Adapter adapter) + public void handleAddAdapter(InternalCDOObject eObject, Adapter adapter) { - if (!FSMUtil.isNew(eObject)) + synchronized (getViewMonitor()) { - subscribe(eObject, adapter); - } + lockView(); - adapterManager.attachAdapter(eObject, adapter); + try + { + if (!FSMUtil.isNew(eObject)) + { + subscribe(eObject, adapter); + } + + adapterManager.attachAdapter(eObject, adapter); + } + finally + { + unlockView(); + } + } } /** * @since 2.0 */ - public synchronized void handleRemoveAdapter(InternalCDOObject eObject, Adapter adapter) + public void handleRemoveAdapter(InternalCDOObject eObject, Adapter adapter) { - if (!FSMUtil.isNew(eObject)) + synchronized (getViewMonitor()) { - unsubscribe(eObject, adapter); - } + lockView(); + + try + { + if (!FSMUtil.isNew(eObject)) + { + unsubscribe(eObject, adapter); + } - adapterManager.detachAdapter(eObject, adapter); + adapterManager.detachAdapter(eObject, adapter); + } + finally + { + unlockView(); + } + } } /** * @since 2.0 */ - public synchronized void subscribe(EObject eObject, Adapter adapter) + public void subscribe(EObject eObject, Adapter adapter) { - if (changeSubscriptionManager != null) + synchronized (getViewMonitor()) { - changeSubscriptionManager.subscribe(eObject, adapter); + lockView(); + + try + { + if (changeSubscriptionManager != null) + { + changeSubscriptionManager.subscribe(eObject, adapter); + } + } + finally + { + unlockView(); + } } } /** * @since 2.0 */ - public synchronized void unsubscribe(EObject eObject, Adapter adapter) + public void unsubscribe(EObject eObject, Adapter adapter) { - if (changeSubscriptionManager != null) + synchronized (getViewMonitor()) { - changeSubscriptionManager.unsubscribe(eObject, adapter); + lockView(); + + try + { + if (changeSubscriptionManager != null) + { + changeSubscriptionManager.unsubscribe(eObject, adapter); + } + } + finally + { + unlockView(); + } } } /** * @since 2.0 */ - public synchronized boolean hasSubscription(CDOID id) + public boolean hasSubscription(CDOID id) { - if (changeSubscriptionManager != null) + synchronized (getViewMonitor()) { - return changeSubscriptionManager.getSubcribeObject(id) != null; - } + lockView(); - return false; + try + { + if (changeSubscriptionManager != null) + { + return changeSubscriptionManager.getSubcribeObject(id) != null; + } + + return false; + } + finally + { + unlockView(); + } + } } /** @@ -1384,76 +1645,133 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv super.doDeactivate(); } - public synchronized long getLastUpdateTime() - { - return lastUpdateTime; - } - - public synchronized void setLastUpdateTime(long lastUpdateTime) + public long getLastUpdateTime() { - if (this.lastUpdateTime < lastUpdateTime) + synchronized (getViewMonitor()) { - this.lastUpdateTime = lastUpdateTime; - } + lockView(); // TODO ??? - notifyAll(); + try + { + return lastUpdateTime; + } + finally + { + unlockView(); + } + } } - public boolean waitForUpdate(long updateTime, long timeoutMillis) + public void setLastUpdateTime(long lastUpdateTime) { - long end = timeoutMillis == NO_TIMEOUT ? Long.MAX_VALUE : System.currentTimeMillis() + timeoutMillis; - synchronized (this) + synchronized (getViewMonitor()) { - for (;;) + lockView(); + + try { - if (lastUpdateTime >= updateTime) + if (this.lastUpdateTime < lastUpdateTime) { - return true; + this.lastUpdateTime = lastUpdateTime; } - long now = System.currentTimeMillis(); - if (now >= end) + if (viewLockCondition != null) { - return false; + viewLockCondition.signalAll(); } - - try + else { - long waitMillis = end - now; - wait(waitMillis); + notifyAll(); } - catch (InterruptedException ex) + } + finally + { + unlockView(); + } + } + } + + public boolean waitForUpdate(long updateTime, long timeoutMillis) + { + long end = timeoutMillis == NO_TIMEOUT ? Long.MAX_VALUE : System.currentTimeMillis() + timeoutMillis; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + for (;;) { - throw WrappedException.wrap(ex); + if (lastUpdateTime >= updateTime) + { + return true; + } + + long now = System.currentTimeMillis(); + if (now >= end) + { + return false; + } + + try + { + long waitMillis = end - now; + + if (viewLockCondition != null) + { + viewLockCondition.await(waitMillis, TimeUnit.MILLISECONDS); + } + else + { + wait(waitMillis); + } + } + catch (InterruptedException ex) + { + throw WrappedException.wrap(ex); + } } } + finally + { + unlockView(); + } } } public boolean runAfterUpdate(final long updateTime, final Runnable runnable) { - synchronized (this) + synchronized (getViewMonitor()) { - long lastUpdateTime = getLastUpdateTime(); - if (lastUpdateTime < updateTime) + lockView(); + + try { - addListener(new IListener() + long lastUpdateTime = getLastUpdateTime(); + if (lastUpdateTime < updateTime) { - public void notifyEvent(IEvent event) + addListener(new IListener() { - if (event instanceof CDOViewInvalidationEvent) + public void notifyEvent(IEvent event) { - CDOViewInvalidationEvent e = (CDOViewInvalidationEvent)event; - if (e.getTimeStamp() >= updateTime) + if (event instanceof CDOViewInvalidationEvent) { - removeListener(this); - runnable.run(); + CDOViewInvalidationEvent e = (CDOViewInvalidationEvent)event; + if (e.getTimeStamp() >= updateTime) + { + removeListener(this); + runnable.run(); + } } } - } - }); + }); - return false; + return false; + } + } + finally + { + unlockView(); } } @@ -2121,9 +2439,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public boolean isLoadNotificationEnabled() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return loadNotificationEnabled; + lockView(); + + try + { + return loadNotificationEnabled; + } + finally + { + unlockView(); + } } } @@ -2132,12 +2459,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (loadNotificationEnabled != enabled) + lockView(); + + try { - loadNotificationEnabled = enabled; - event = new LoadNotificationEventImpl(); + if (loadNotificationEnabled != enabled) + { + loadNotificationEnabled = enabled; + event = new LoadNotificationEventImpl(); + } + } + finally + { + unlockView(); } } @@ -2146,9 +2482,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public boolean isDetachmentNotificationEnabled() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return detachmentNotificationEnabled; + lockView(); + + try + { + return detachmentNotificationEnabled; + } + finally + { + unlockView(); + } } } @@ -2157,12 +2502,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (detachmentNotificationEnabled != enabled) + lockView(); + + try + { + if (detachmentNotificationEnabled != enabled) + { + detachmentNotificationEnabled = enabled; + event = new DetachmentNotificationEventImpl(); + } + } + finally { - detachmentNotificationEnabled = enabled; - event = new DetachmentNotificationEventImpl(); + unlockView(); } } @@ -2171,9 +2525,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public boolean isInvalidationNotificationEnabled() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return invalidationNotificationEnabled; + lockView(); + + try + { + return invalidationNotificationEnabled; + } + finally + { + unlockView(); + } } } @@ -2182,12 +2545,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (invalidationNotificationEnabled != enabled) + lockView(); + + try + { + if (invalidationNotificationEnabled != enabled) + { + invalidationNotificationEnabled = enabled; + event = new InvalidationNotificationEventImpl(); + } + } + finally { - invalidationNotificationEnabled = enabled; - event = new InvalidationNotificationEventImpl(); + unlockView(); } } @@ -2196,9 +2568,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public CDOInvalidationPolicy getInvalidationPolicy() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return invalidationPolicy; + lockView(); + + try + { + return invalidationPolicy; + } + finally + { + unlockView(); + } } } @@ -2207,12 +2588,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (invalidationPolicy != policy) + lockView(); + + try { - invalidationPolicy = policy; - event = new InvalidationPolicyEventImpl(); + if (invalidationPolicy != policy) + { + invalidationPolicy = policy; + event = new InvalidationPolicyEventImpl(); + } + } + finally + { + unlockView(); } } @@ -2229,14 +2619,23 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (enabled != lockNotificationsEnabled) + lockView(); + + try + { + if (enabled != lockNotificationsEnabled) + { + CDOSessionProtocol protocol = session.getSessionProtocol(); + protocol.enableLockNotifications(viewID, enabled); + lockNotificationsEnabled = enabled; + event = new LockNotificationEventImpl(enabled); + } + } + finally { - CDOSessionProtocol protocol = session.getSessionProtocol(); - protocol.enableLockNotifications(viewID, enabled); - lockNotificationsEnabled = enabled; - event = new LockNotificationEventImpl(enabled); + unlockView(); } } @@ -2253,25 +2652,34 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (enabled) + lockView(); + + try { - if (lockStatePrefetcher == null) + if (enabled) { - lockStatePrefetcher = new LockStatePrefetcher(); - event = new LockStatePrefetchEventImpl(); + if (lockStatePrefetcher == null) + { + lockStatePrefetcher = new LockStatePrefetcher(); + event = new LockStatePrefetchEventImpl(); + } } - } - else - { - if (lockStatePrefetcher != null) + else { - lockStatePrefetcher.dispose(); - lockStatePrefetcher = null; - event = new LockStatePrefetchEventImpl(); + if (lockStatePrefetcher != null) + { + lockStatePrefetcher.dispose(); + lockStatePrefetcher = null; + event = new LockStatePrefetchEventImpl(); + } } } + finally + { + unlockView(); + } } fireEvent(event); @@ -2279,35 +2687,70 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public CDOLockStateLoadingPolicy getLockStateLoadingPolicy() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return lockStateLoadingPolicy; + lockView(); + + try + { + return lockStateLoadingPolicy; + } + finally + { + unlockView(); + } } } public void setLockStateLoadingPolicy(CDOLockStateLoadingPolicy lockStateLoadingPolicy) { checkActive(); - - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - this.lockStateLoadingPolicy = lockStateLoadingPolicy; + lockView(); + + try + { + this.lockStateLoadingPolicy = lockStateLoadingPolicy; + } + finally + { + unlockView(); + } } } public boolean hasChangeSubscriptionPolicies() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return !changeSubscriptionPolicies.isEmpty(); + lockView(); + + try + { + return !changeSubscriptionPolicies.isEmpty(); + } + finally + { + unlockView(); + } } } public CDOAdapterPolicy[] getChangeSubscriptionPolicies() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return changeSubscriptionPolicies.toArray(new CDOAdapterPolicy[changeSubscriptionPolicies.size()]); + lockView(); + + try + { + return changeSubscriptionPolicies.toArray(new CDOAdapterPolicy[changeSubscriptionPolicies.size()]); + } + finally + { + unlockView(); + } } } @@ -2316,12 +2759,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (changeSubscriptionPolicies.add(policy)) + lockView(); + + try { - changeSubscriptionManager.notifyChangeSubcriptionPolicy(); - event = new ChangeSubscriptionPoliciesEventImpl(); + if (changeSubscriptionPolicies.add(policy)) + { + changeSubscriptionManager.notifyChangeSubcriptionPolicy(); + event = new ChangeSubscriptionPoliciesEventImpl(); + } + } + finally + { + unlockView(); } } @@ -2333,12 +2785,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv checkActive(); IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (changeSubscriptionPolicies.remove(policy) && !changeSubscriptionPolicies.contains(policy)) + lockView(); + + try { - changeSubscriptionManager.notifyChangeSubcriptionPolicy(); - event = new ChangeSubscriptionPoliciesEventImpl(); + if (changeSubscriptionPolicies.remove(policy) && !changeSubscriptionPolicies.contains(policy)) + { + changeSubscriptionManager.notifyChangeSubcriptionPolicy(); + event = new ChangeSubscriptionPoliciesEventImpl(); + } + } + finally + { + unlockView(); } } @@ -2347,9 +2808,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public CDOAdapterPolicy getStrongReferencePolicy() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return strongReferencePolicy; + lockView(); + + try + { + return strongReferencePolicy; + } + finally + { + unlockView(); + } } } @@ -2363,13 +2833,22 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (strongReferencePolicy != adapterPolicy) + lockView(); + + try { - strongReferencePolicy = adapterPolicy; - adapterManager.reset(); - event = new ReferencePolicyEventImpl(); + if (strongReferencePolicy != adapterPolicy) + { + strongReferencePolicy = adapterPolicy; + adapterManager.reset(); + event = new ReferencePolicyEventImpl(); + } + } + finally + { + unlockView(); } } @@ -2378,9 +2857,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public CDORevisionPrefetchingPolicy getRevisionPrefetchingPolicy() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return revisionPrefetchingPolicy; + lockView(); + + try + { + return revisionPrefetchingPolicy; + } + finally + { + unlockView(); + } } } @@ -2394,12 +2882,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (revisionPrefetchingPolicy != prefetchingPolicy) + lockView(); + + try { - revisionPrefetchingPolicy = prefetchingPolicy; - event = new RevisionPrefetchingPolicyEventImpl(); + if (revisionPrefetchingPolicy != prefetchingPolicy) + { + revisionPrefetchingPolicy = prefetchingPolicy; + event = new RevisionPrefetchingPolicyEventImpl(); + } + } + finally + { + unlockView(); } } @@ -2408,9 +2905,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public CDOFeatureAnalyzer getFeatureAnalyzer() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return featureAnalyzer; + lockView(); + + try + { + return featureAnalyzer; + } + finally + { + unlockView(); + } } } @@ -2424,12 +2930,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (this.featureAnalyzer != featureAnalyzer) + lockView(); + + try + { + if (this.featureAnalyzer != featureAnalyzer) + { + this.featureAnalyzer = featureAnalyzer; + event = new FeatureAnalyzerEventImpl(); + } + } + finally { - this.featureAnalyzer = featureAnalyzer; - event = new FeatureAnalyzerEventImpl(); + unlockView(); } } @@ -2450,9 +2965,18 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public CDOStaleReferencePolicy getStaleReferencePolicy() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - return staleReferencePolicy; + lockView(); + + try + { + return staleReferencePolicy; + } + finally + { + unlockView(); + } } } @@ -2466,12 +2990,21 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } IEvent event = null; - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (staleReferencePolicy != policy) + lockView(); + + try + { + if (staleReferencePolicy != policy) + { + staleReferencePolicy = policy; + event = new StaleReferencePolicyEventImpl(); + } + } + finally { - staleReferencePolicy = policy; - event = new StaleReferencePolicyEventImpl(); + unlockView(); } } @@ -2480,25 +3013,34 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv public ReferenceType getCacheReferenceType() { - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - Map<CDOID, InternalCDOObject> objects = getModifiableObjects(); - if (objects instanceof ReferenceValueMap.Strong<?, ?>) - { - return ReferenceType.STRONG; - } + lockView(); - if (objects instanceof ReferenceValueMap.Soft<?, ?>) + try { - return ReferenceType.SOFT; - } + Map<CDOID, InternalCDOObject> objects = getModifiableObjects(); + if (objects instanceof ReferenceValueMap.Strong<?, ?>) + { + return ReferenceType.STRONG; + } + + if (objects instanceof ReferenceValueMap.Soft<?, ?>) + { + return ReferenceType.SOFT; + } + + if (objects instanceof ReferenceValueMap.Weak<?, ?>) + { + return ReferenceType.WEAK; + } - if (objects instanceof ReferenceValueMap.Weak<?, ?>) + throw new IllegalStateException(Messages.getString("CDOViewImpl.29")); //$NON-NLS-1$ + } + finally { - return ReferenceType.WEAK; + unlockView(); } - - throw new IllegalStateException(Messages.getString("CDOViewImpl.29")); //$NON-NLS-1$ } } @@ -2511,11 +3053,20 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv referenceType = ReferenceType.SOFT; } - synchronized (CDOViewImpl.this) + synchronized (getViewMonitor()) { - if (!initObjectsMap(referenceType)) + lockView(); + + try { - return false; + if (!initObjectsMap(referenceType)) + { + return false; + } + } + finally + { + unlockView(); } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java index 7ec330855c..84c5513f6a 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java @@ -199,6 +199,21 @@ public interface InternalCDOView extends CDOView, CDOIDProvider, ILifecycle public ViewAndState getViewAndState(CDOState state); /** + * @since 4.5 + */ + public Object getViewMonitor(); + + /** + * @since 4.5 + */ + public void lockView(); + + /** + * @since 4.5 + */ + public void unlockView(); + + /** * Optimizes the storage of {@link CDOObject#cdoView()} and {@link CDOObject#cdoState()}. All objects of a view * share a small number of {@link CDOState} literals, so they are moved into a final AbstractCDOView.viewAndStates array. * For the {@link CDOState#TRANSIENT TRANSIENT} state, where there is no view associated with a {@link CDOObject}, this class |