Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java')
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java512
1 files changed, 308 insertions, 204 deletions
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 46a5aae5de..e8017cc1e3 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
@@ -1828,7 +1828,198 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
}
- private Set<CDOID> rollbackCompletely(CDOUserSavepoint savepoint)
+ /**
+ * @since 2.0
+ */
+ public void detachObject(InternalCDOObject object)
+ {
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ 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)
+ {
+ 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);
+
+ // Object may have been reattached previously, in which case it must
+ // here be removed from the collection of reattached objects
+ lastSavepoint.getReattachedObjects().remove(id);
+ }
+
+ getUnitManager().removeObject(object);
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void handleRollback(InternalCDOSavepoint savepoint)
+ {
+ if (savepoint == null)
+ {
+ throw new IllegalArgumentException(Messages.getString("CDOTransactionImpl.3")); //$NON-NLS-1$
+ }
+
+ if (savepoint.getTransaction() != this)
+ {
+ throw new IllegalArgumentException(MessageFormat.format(Messages.getString("CDOTransactionImpl.4"), savepoint)); //$NON-NLS-1$
+ }
+
+ if (!savepoint.isValid())
+ {
+ throw new IllegalArgumentException(MessageFormat.format(Messages.getString("CDOTransactionImpl.6"), savepoint)); //$NON-NLS-1$
+ }
+
+ if (TRACER.isEnabled())
+ {
+ TRACER.trace("handleRollback()"); //$NON-NLS-1$
+ }
+
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ // Remember current revisions
+ Map<CDOObject, CDORevision> oldRevisions = new HashMap<CDOObject, CDORevision>();
+ collectRevisions(oldRevisions, getDirtyObjects());
+ collectRevisions(oldRevisions, getNewObjects());
+
+ // Rollback objects
+ Map<CDOObject, CDORevision> newRevisions = new HashMap<CDOObject, CDORevision>();
+ Set<CDOID> idsOfNewObjectWithDeltas = rollbackCompletely(savepoint, newRevisions);
+
+ lastSavepoint = savepoint;
+ lastSavepoint.setNextSavepoint(null);
+ lastSavepoint.clear();
+
+ // 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)
+ {
+ // Unlock all objects
+ unlockObjects(null, null);
+ }
+ }
+
+ // Send notifications.
+ for (Entry<CDOObject, CDORevision> entry : oldRevisions.entrySet())
+ {
+ InternalCDOObject object = (InternalCDOObject)entry.getKey();
+ InternalCDORevision oldRevision = (InternalCDORevision)entry.getValue();
+
+ InternalCDORevision newRevision = object.cdoRevision();
+ if (newRevision == null)
+ {
+ newRevision = (InternalCDORevision)newRevisions.get(object);
+ }
+
+ if (newRevision == null && !FSMUtil.isTransient(object))
+ {
+ // This can happen for example for conflicting objects which have been set to PROXY in rollbackCompletely().
+ CDOID id = oldRevision.getID();
+ newRevision = getRevision(id, 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();
+ }
+ }
+ }
+ }
+
+ IListener[] listeners = getListeners();
+ if (listeners != null)
+ {
+ fireEvent(new FinishedEvent(true), listeners);
+ }
+
+ CDOTransactionHandler2[] handlers = getTransactionHandlers2();
+ for (int i = 0; i < handlers.length; i++)
+ {
+ CDOTransactionHandler2 handler = handlers[i];
+
+ try
+ {
+ handler.rolledBackTransaction(this);
+ }
+ catch (RuntimeException ex)
+ {
+ OM.LOG.error(ex);
+ }
+ }
+ }
+ catch (RuntimeException ex)
+ {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ throw new TransactionException(ex);
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+ }
+
+ private Set<CDOID> rollbackCompletely(CDOUserSavepoint savepoint, Map<CDOObject, CDORevision> newRevisions)
{
Set<CDOID> idsOfNewObjectsWithDeltas = new HashSet<CDOID>();
Set<InternalCDOObject> newObjects = new HashSet<InternalCDOObject>();
@@ -1872,16 +2063,41 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
}
+ Map<CDOID, CDORevision> attachedRevisions = options().getAttachedRevisionsMap();
for (Object idOrObject : toBeDetached)
{
- if (idOrObject instanceof CDOObjectImpl)
+ InternalCDORevision revision = null;
+
+ if (idOrObject instanceof InternalCDOObject)
{
- CDOObjectImpl impl = (CDOObjectImpl)idOrObject;
- InternalCDORevision revision = impl.cdoRevision();
+ InternalCDOObject object = (InternalCDOObject)idOrObject;
+ CDOID id = object.cdoID();
+
+ if (attachedRevisions != null)
+ {
+ revision = (InternalCDORevision)attachedRevisions.get(id);
+ }
+
+ if (revision == null)
+ {
+ revision = object.cdoRevision();
+ if (revision != null)
+ {
+ // Copy the revision, so that the revision modifications below don't apply to the oldRevisions,
+ // which have been remembered in handleRollback() for the computation of delta notifications.
+ revision = revision.copy();
+ }
+ }
- Resource.Internal directResource = impl.eDirectResource();
- EObject container = impl.eContainer();
- if (!toBeDetached.contains(directResource) && !toBeDetached.contains(container))
+ if (revision != null)
+ {
+ newRevisions.put((CDOObject)idOrObject, revision);
+ }
+
+ Resource.Internal directResource = object.eDirectResource();
+ EObject container = object.eContainer();
+ boolean topLevel = !toBeDetached.contains(directResource) && !toBeDetached.contains(container);
+ if (topLevel)
{
if (revision != null)
{
@@ -1892,22 +2108,36 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
revision.setContainerID(null);
revision.setContainingFeatureID(0);
}
- else
+ }
+
+ if (idOrObject instanceof CDOObjectImpl)
+ {
+ CDOObjectImpl impl = (CDOObjectImpl)idOrObject;
+
+ if (revision != null)
+ {
+ impl.cdoInternalSetRevision(revision);
+ }
+ else if (topLevel)
{
// Unset direct resource and eContainer in the EObject.
impl.cdoInternalSetResource(null);
}
}
- }
- else if (idOrObject instanceof CDOObjectWrapper)
- {
- CDOObjectWrapper wrapper = (CDOObjectWrapper)idOrObject;
- Resource.Internal directResource = wrapper.eDirectResource();
- EObject container = wrapper.eContainer();
- if (!toBeDetached.contains(directResource) && !toBeDetached.contains(container))
+ else if (idOrObject instanceof CDOObjectWrapper)
{
- wrapper.setInstanceResource(null);
- wrapper.setInstanceContainer(null, 0);
+ CDOObjectWrapper wrapper = (CDOObjectWrapper)idOrObject;
+
+ if (revision != null)
+ {
+ wrapper.cdoInternalRollback(revision);
+ }
+
+ if (topLevel)
+ {
+ wrapper.setInstanceResource(null);
+ wrapper.setInstanceContainer(null, 0);
+ }
}
}
}
@@ -1925,7 +2155,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
}
- // Rollback all detached objects
+ // Rollback all detached objects.
Map<CDOID, CDOObject> detachedObjectsMap = itrSavepoint.getDetachedObjects();
if (!detachedObjectsMap.isEmpty())
{
@@ -1945,6 +2175,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
}
+ // Rollback dirty objects.
for (Entry<CDOID, CDOObject> entryDirtyObject : itrSavepoint.getDirtyObjects().entrySet())
{
CDOID id = entryDirtyObject.getKey();
@@ -1967,6 +2198,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
}
+ // Rollback new objects.
for (InternalCDOObject internalCDOObject : newObjects)
{
if (FSMUtil.isNew(internalCDOObject))
@@ -2060,195 +2292,14 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
dirty = savepoint.wasDirty();
}
- /**
- * @since 2.0
- */
- public void detachObject(InternalCDOObject object)
- {
- synchronized (getViewMonitor())
- {
- lockView();
-
- try
- {
- 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)
- {
- 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);
-
- // Object may have been reattached previously, in which case it must
- // here be removed from the collection of reattached objects
- lastSavepoint.getReattachedObjects().remove(id);
- }
-
- getUnitManager().removeObject(object);
- }
- finally
- {
- unlockView();
- }
- }
- }
-
- /**
- * @since 2.0
- */
- public void handleRollback(InternalCDOSavepoint savepoint)
+ private void collectRevisions(Map<CDOObject, CDORevision> revisions, Map<CDOID, CDOObject> objects)
{
- if (savepoint == null)
- {
- throw new IllegalArgumentException(Messages.getString("CDOTransactionImpl.3")); //$NON-NLS-1$
- }
-
- if (savepoint.getTransaction() != this)
- {
- throw new IllegalArgumentException(MessageFormat.format(Messages.getString("CDOTransactionImpl.4"), savepoint)); //$NON-NLS-1$
- }
-
- if (!savepoint.isValid())
- {
- throw new IllegalArgumentException(MessageFormat.format(Messages.getString("CDOTransactionImpl.6"), savepoint)); //$NON-NLS-1$
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.trace("handleRollback()"); //$NON-NLS-1$
- }
-
- synchronized (getViewMonitor())
+ for (CDOObject object : objects.values())
{
- lockView();
-
- try
- {
- // Remember current revisions
- Map<CDOObject, CDORevision> oldRevisions = new HashMap<CDOObject, CDORevision>();
- for (CDOObject object : getDirtyObjects().values())
- {
- CDORevision oldRevision = object.cdoRevision();
- if (oldRevision != null)
- {
- oldRevisions.put(object, oldRevision);
- }
- }
-
- // Rollback objects
- Set<CDOID> idsOfNewObjectWithDeltas = rollbackCompletely(savepoint);
-
- lastSavepoint = savepoint;
- lastSavepoint.setNextSavepoint(null);
- lastSavepoint.clear();
-
- // 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)
- {
- // Unlock all objects
- unlockObjects(null, null);
- }
- }
-
- // Send notifications
- for (Entry<CDOObject, CDORevision> entry : oldRevisions.entrySet())
- {
- 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();
- }
- }
- }
- }
-
- IListener[] listeners = getListeners();
- if (listeners != null)
- {
- fireEvent(new FinishedEvent(true), listeners);
- }
-
- CDOTransactionHandler2[] handlers = getTransactionHandlers2();
- for (int i = 0; i < handlers.length; i++)
- {
- CDOTransactionHandler2 handler = handlers[i];
-
- try
- {
- handler.rolledBackTransaction(this);
- }
- catch (RuntimeException ex)
- {
- OM.LOG.error(ex);
- }
- }
- }
- catch (RuntimeException ex)
- {
- throw ex;
- }
- catch (Exception ex)
+ CDORevision oldRevision = object.cdoRevision();
+ if (oldRevision != null)
{
- throw new TransactionException(ex);
- }
- finally
- {
- unlockView();
+ revisions.put(object, oldRevision);
}
}
}
@@ -2626,6 +2677,13 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
firstSavepoint.setNextSavepoint(null);
cleanRevisions.clear();
+
+ Map<CDOID, CDORevision> attachedRevisions = options().getAttachedRevisionsMap();
+ if (attachedRevisions != null)
+ {
+ attachedRevisions.clear();
+ }
+
dirty = false;
conflict = 0;
idGenerator.reset();
@@ -4910,6 +4968,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
private long commitInfoTimeout = DEFAULT_COMMIT_INFO_TIMEOUT;
+ private Map<CDOID, CDORevision> attachedRevisionsMap;
+
public OptionsImpl()
{
}
@@ -5304,6 +5364,37 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
return effectiveAutoReleaseLock;
}
+ public Map<CDOID, CDORevision> getAttachedRevisionsMap()
+ {
+ return attachedRevisionsMap;
+ }
+
+ public void setAttachedRevisionsMap(Map<CDOID, CDORevision> attachedRevisionsMap)
+ {
+ checkActive();
+
+ IEvent event = null;
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ if (this.attachedRevisionsMap != attachedRevisionsMap)
+ {
+ this.attachedRevisionsMap = attachedRevisionsMap;
+ event = new AttachedRevisionsMapImpl();
+ }
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+
+ fireEvent(event);
+ }
+
public long getCommitInfoTimeout()
{
return commitInfoTimeout;
@@ -5403,6 +5494,19 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
/**
* @author Eike Stepper
*/
+ private final class AttachedRevisionsMapImpl extends OptionsEvent implements AttachedRevisionsMap
+ {
+ private static final long serialVersionUID = 1L;
+
+ public AttachedRevisionsMapImpl()
+ {
+ super(OptionsImpl.this);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
private final class CommitInfoTimeoutImpl extends OptionsEvent implements CommitInfoTimeout
{
private static final long serialVersionUID = 1L;

Back to the top