diff options
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.java | 512 |
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; |