Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java')
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java409
1 files changed, 383 insertions, 26 deletions
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 71f3f4ed2b..4087ffe837 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
@@ -25,9 +25,11 @@ import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
import org.eclipse.emf.cdo.common.revision.CDORevisionsLoadedEvent;
@@ -51,6 +53,8 @@ import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer;
import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy;
import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy;
+import org.eclipse.emf.cdo.view.CDOUnit;
+import org.eclipse.emf.cdo.view.CDOUnitManager;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewDurabilityChangedEvent;
import org.eclipse.emf.cdo.view.CDOViewInvalidationEvent;
@@ -74,6 +78,7 @@ import org.eclipse.net4j.util.concurrent.IExecutorServiceProvider;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.concurrent.IWorkSerializer;
import org.eclipse.net4j.util.concurrent.RunnableWithName;
+import org.eclipse.net4j.util.container.Container;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.event.Notifier;
@@ -95,6 +100,7 @@ import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
@@ -113,9 +119,11 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
@@ -135,6 +143,8 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
private String durableLockingID;
+ private final CDOUnitManagerImpl unitManager = new CDOUnitManagerImpl();
+
private ChangeSubscriptionManager changeSubscriptionManager = new ChangeSubscriptionManager();
private AdapterManager adapterManager = new AdapterManager();
@@ -926,23 +936,15 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
}
@Override
- public InternalCDOObject removeObject(CDOID id)
+ protected void objectRegistered(InternalCDOObject object)
{
- synchronized (getViewMonitor())
- {
- lockView();
+ unitManager.addObject(object);
+ }
- try
- {
- InternalCDOObject removedObject = super.removeObject(id);
- removeLockState(removedObject);
- return removedObject;
- }
- finally
- {
- unlockView();
- }
- }
+ @Override
+ protected void objectDeregistered(InternalCDOObject object)
+ {
+ removeLockState(object);
}
public CDOLockState[] getLockStates(Collection<CDOID> ids)
@@ -1551,6 +1553,8 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
{
new SyncTester().start();
}
+
+ unitManager.activate();
}
@Override
@@ -1591,6 +1595,8 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
@Override
protected void doDeactivate() throws Exception
{
+ unitManager.deactivate();
+
CDOViewRegistryImpl.INSTANCE.deregister(this);
LifecycleUtil.deactivate(invalidationRunner, OMLogger.Level.WARN);
@@ -1805,6 +1811,346 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
return id;
}
+ public final CDOUnitManagerImpl getUnitManager()
+ {
+ return unitManager;
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public final class CDOUnitManagerImpl extends Container<CDOUnit> implements CDOUnitManager
+ {
+ private final Map<EObject, CDOUnit> unitPerRoot = new HashMap<EObject, CDOUnit>();
+
+ private final Map<EObject, CDOUnit> unitPerObject = new HashMap<EObject, CDOUnit>();
+
+ public CDOUnitManagerImpl()
+ {
+ }
+
+ public CDOView getView()
+ {
+ return CDOViewImpl.this;
+ }
+
+ public boolean isUnit(EObject root)
+ {
+ CDOUnitImpl unit = requestUnit(root, CDOProtocolConstants.UNIT_CHECK);
+ return unit != null;
+ }
+
+ public CDOUnit createUnit(EObject root) throws UnitExistsException
+ {
+ CDOUnitImpl unit = requestUnit(root, CDOProtocolConstants.UNIT_CREATE);
+ if (unit == null)
+ {
+ throw new UnitExistsException();
+ }
+
+ fireElementAddedEvent(unit);
+ return unit;
+ }
+
+ public CDOUnit openUnit(EObject root) throws UnitNotFoundException
+ {
+ CDOUnitImpl unit = requestUnit(root, CDOProtocolConstants.UNIT_OPEN);
+ if (unit == null)
+ {
+ throw new UnitNotFoundException();
+ }
+
+ fireElementAddedEvent(unit);
+ return unit;
+ }
+
+ public CDOUnit[] getElements()
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ return unitPerRoot.values().toArray(new CDOUnit[unitPerRoot.size()]);
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ public CDOUnit[] getOpenUnits()
+ {
+ return getElements();
+ }
+
+ public CDOUnit getOpenUnit(EObject object)
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ return getOpenUnitUnsynced(object);
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ public CDOUnit getOpenUnitUnsynced(EObject object)
+ {
+ return unitPerObject.get(object);
+ }
+
+ public void addObject(InternalCDOObject object)
+ {
+ if (!unitPerRoot.isEmpty())
+ {
+ CDOUnit unit = getOpenUnitUnsynced(object);
+ if (unit == null)
+ {
+ EObject parent = getParent(object);
+ EObject rootResource = getRootResource();
+
+ while (parent != null && parent != rootResource)
+ {
+ unit = getOpenUnitUnsynced(parent);
+ if (unit != null)
+ {
+ unitPerObject.put(object, unit);
+ ++((CDOUnitImpl)unit).elements;
+ break;
+ }
+
+ parent = getParent(parent);
+ }
+ }
+ }
+ }
+
+ public void removeObject(InternalCDOObject object)
+ {
+ if (!unitPerRoot.isEmpty())
+ {
+ CDOUnit unit = unitPerObject.remove(object);
+ if (unit != null)
+ {
+ if (unit.getRoot() == object)
+ {
+ unitPerRoot.remove(object);
+ }
+
+ --((CDOUnitImpl)unit).elements;
+ }
+ }
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ unitPerRoot.clear();
+ unitPerObject.clear();
+ super.doDeactivate();
+ }
+
+ private EObject getParent(EObject object)
+ {
+ EObject parent = object.eContainer();
+ if (parent == null)
+ {
+ parent = (EObject)((InternalEObject)object).eDirectResource();
+ }
+
+ return parent;
+ }
+
+ private CDOObject getCDORoot(EObject root)
+ {
+ CDOObject cdoRoot = CDOUtil.getCDOObject(root);
+ if (cdoRoot == null)
+ {
+ throw new IllegalArgumentException("Root " + root + " is not managed by CDO");
+ }
+
+ CDOView view = cdoRoot.cdoView();
+ if (view != CDOViewImpl.this)
+ {
+ throw new IllegalArgumentException("Root " + root + " is managed by " + view);
+ }
+
+ return cdoRoot;
+ }
+
+ private CDOUnitImpl requestUnit(EObject root, byte opcode)
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ if (opcode == CDOProtocolConstants.UNIT_CREATE)
+ {
+ CDOUnit containingUnit = getOpenUnit(root);
+ if (containingUnit != null)
+ {
+ throw new CDOException(
+ "Attempt to nest the new unit " + root + " in the existing unit " + containingUnit);
+ }
+
+ for (CDOUnit existingUnit : unitPerRoot.values())
+ {
+ if (EcoreUtil.isAncestor(root, existingUnit.getRoot()))
+ {
+ throw new CDOException(
+ "Attempt to nest the existing unit " + existingUnit + " in the new unit " + root);
+ }
+ }
+ }
+
+ final InternalCDORevisionManager revisionManager = session.getRevisionManager();
+ final CDOUnitImpl unit = new CDOUnitImpl(root);
+
+ int viewID = getViewID();
+ CDOID rootID = getCDORoot(root).cdoID();
+
+ CDORevisionHandler revisionHandler = opcode == CDOProtocolConstants.UNIT_CREATE
+ || opcode == CDOProtocolConstants.UNIT_OPEN ? new CDORevisionHandler()
+ {
+ public boolean handleRevision(CDORevision revision)
+ {
+ ++unit.elements;
+ revisionManager.addRevision(revision);
+
+ CDOID id = revision.getID();
+ changeSubscriptionManager.removeEntry(id);
+
+ InternalCDOObject object = getObject(id);
+ unitPerObject.put(object, unit);
+ return true;
+ }
+ } : null;
+
+ CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
+ boolean success = sessionProtocol.requestUnit(viewID, rootID, opcode, revisionHandler);
+
+ if (success)
+ {
+ if (revisionHandler != null)
+ {
+ unitPerRoot.put(root, unit);
+ unitPerObject.put(root, unit);
+ }
+
+ return unit;
+ }
+
+ return null;
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ private void closeUnit(CDOUnit unit, boolean resubscribe)
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ requestUnit(unit.getRoot(), CDOProtocolConstants.UNIT_CLOSE);
+
+ if (resubscribe && !options.hasChangeSubscriptionPolicies())
+ {
+ resubscribe = false;
+ }
+
+ for (Iterator<Entry<EObject, CDOUnit>> it = unitPerObject.entrySet().iterator(); it.hasNext();)
+ {
+ Entry<EObject, CDOUnit> entry = it.next();
+ if (entry.getValue() == unit)
+ {
+ it.remove(); // Remove the object from its unit first, so that shouldSubscribe() can return true.
+
+ if (resubscribe)
+ {
+ EObject object = entry.getKey();
+ for (Adapter adapter : object.eAdapters())
+ {
+ changeSubscriptionManager.subscribe(object, adapter);
+ }
+ }
+ }
+ }
+
+ unitPerRoot.remove(unit.getRoot());
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+
+ fireElementRemovedEvent(unit);
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public final class CDOUnitImpl implements CDOUnit
+ {
+ private final EObject root;
+
+ private int elements;
+
+ public CDOUnitImpl(EObject root)
+ {
+ this.root = root;
+ }
+
+ public CDOUnitManagerImpl getManager()
+ {
+ return CDOUnitManagerImpl.this;
+ }
+
+ public EObject getRoot()
+ {
+ return root;
+ }
+
+ public int getElements()
+ {
+ return elements;
+ }
+
+ public void close()
+ {
+ close(true);
+ }
+
+ public void close(boolean resubscribe)
+ {
+ closeUnit(this, resubscribe);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "CDOUnit[" + root + "]";
+ }
+ }
+ }
+
/**
* @author Simon McDuff
* @since 2.0
@@ -1926,7 +2272,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
/**
* Register to the server all objects from the active list
*/
- private void notifyChangeSubcriptionPolicy()
+ private void handleChangeSubcriptionPoliciesChanged()
{
boolean policiesPresent = options().hasChangeSubscriptionPolicies();
subscriptions.clear();
@@ -1964,13 +2310,13 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
{
for (CDOObject object : newObjects)
{
- InternalCDOObject cdoDetachedObject = (InternalCDOObject)object;
- if (cdoDetachedObject != null)
+ InternalCDOObject internalObject = (InternalCDOObject)object;
+ if (internalObject != null)
{
- int count = getNumberOfValidAdapters(cdoDetachedObject);
+ int count = getNumberOfValidAdapters(internalObject);
if (count > 0)
{
- subscribe(cdoDetachedObject.cdoID(), cdoDetachedObject, count);
+ subscribe(internalObject.cdoID(), internalObject, count);
}
}
}
@@ -2031,6 +2377,11 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
private boolean shouldSubscribe(EObject eObject, Adapter adapter)
{
+ if (unitManager.getOpenUnitUnsynced(eObject) != null)
+ {
+ return false;
+ }
+
for (CDOAdapterPolicy policy : options().getChangeSubscriptionPolicies())
{
if (policy.isValid(eObject, adapter))
@@ -2072,7 +2423,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
// Look if objects need to be unsubscribe
if (count <= 0)
{
- subscriptions.remove(id);
+ removeEntry(id);
// Notification need to be enable to send correct value to the server
if (policiesPresent)
@@ -2098,9 +2449,14 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
subscribe(id, null, Integer.MIN_VALUE);
}
- private void addEntry(CDOID key, InternalCDOObject object, int count)
+ private void addEntry(CDOID id, InternalCDOObject object, int count)
+ {
+ subscriptions.put(id, new SubscribeEntry(object, count));
+ }
+
+ private void removeEntry(CDOID id)
{
- subscriptions.put(key, new SubscribeEntry(object, count));
+ subscriptions.remove(id);
}
}
@@ -2136,7 +2492,8 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
}
/**
- * A {@link IListener} to prefetch {@link CDOLockState lockstates} when {@link CDORevision revisions} are loaded, according to {@link Options#setLockStatePrefetchEnabled(boolean)} option.
+ * A {@link IListener} to prefetch {@link CDOLockState lock states} when {@link CDORevision revisions} are loaded,
+ * according to {@link Options#setLockStatePrefetchEnabled(boolean)} option.
*
* @author Esteban Dugueperoux
*/
@@ -2814,7 +3171,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
{
if (changeSubscriptionPolicies.add(policy))
{
- changeSubscriptionManager.notifyChangeSubcriptionPolicy();
+ changeSubscriptionManager.handleChangeSubcriptionPoliciesChanged();
event = new ChangeSubscriptionPoliciesEventImpl();
}
}
@@ -2840,7 +3197,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv
{
if (changeSubscriptionPolicies.remove(policy) && !changeSubscriptionPolicies.contains(policy))
{
- changeSubscriptionManager.notifyChangeSubcriptionPolicy();
+ changeSubscriptionManager.handleChangeSubcriptionPoliciesChanged();
event = new ChangeSubscriptionPoliciesEventImpl();
}
}

Back to the top