diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java')
-rw-r--r-- | plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java | 194 |
1 files changed, 109 insertions, 85 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java index 5163a45593..b20e5a377b 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java @@ -78,6 +78,7 @@ import org.eclipse.net4j.util.CheckUtil; import org.eclipse.net4j.util.StringUtil; import org.eclipse.net4j.util.collection.IndexedList; import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; +import org.eclipse.net4j.util.concurrent.RWOLockManager; import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState; import org.eclipse.net4j.util.io.ExtendedDataInputStream; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; @@ -92,7 +93,6 @@ import org.eclipse.emf.ecore.EStructuralFeature; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -147,8 +147,6 @@ public class TransactionCommitContext implements InternalCommitContext private InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[0]; - private CDOLockState[] locksOnNewObjects = new CDOLockState[0]; - private InternalCDORevision[] newObjects = new InternalCDORevision[0]; private InternalCDORevisionDelta[] dirtyObjectDeltas = new InternalCDORevisionDelta[0]; @@ -179,7 +177,7 @@ public class TransactionCommitContext implements InternalCommitContext private List<CDOIDReference> xRefs; - private List<LockState<Object, IView>> postCommitLockStates; + private final List<LockState<Object, IView>> postCommitLockStates = new ArrayList<LockState<Object, IView>>(); private boolean hasChanges; @@ -187,10 +185,12 @@ public class TransactionCommitContext implements InternalCommitContext private boolean ensuringReferentialIntegrity; - private boolean autoReleaseLocksEnabled; - private ExtendedDataInputStream lobs; + private CDOLockState[] locksOnNewObjects = new CDOLockState[0]; + + private CDOID[] idsToUnlock = new CDOID[0]; + private Map<Object, Object> data; private CommitNotificationInfo commitNotificationInfo = new CommitNotificationInfo(); @@ -238,11 +238,6 @@ public class TransactionCommitContext implements InternalCommitContext return lastUpdateTime; } - public boolean isAutoReleaseLocksEnabled() - { - return autoReleaseLocksEnabled; - } - public byte getRollbackReason() { return rollbackReason; @@ -294,11 +289,6 @@ public class TransactionCommitContext implements InternalCommitContext return newPackageUnits; } - public CDOLockState[] getLocksOnNewObjects() - { - return locksOnNewObjects; - } - public InternalCDORevision[] getNewObjects() { return newObjects; @@ -526,11 +516,6 @@ public class TransactionCommitContext implements InternalCommitContext this.newPackageUnits = newPackageUnits; } - public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects) - { - this.locksOnNewObjects = locksOnNewObjects; - } - public void setNewObjects(InternalCDORevision[] newObjects) { this.newObjects = newObjects; @@ -561,11 +546,6 @@ public class TransactionCommitContext implements InternalCommitContext this.lastUpdateTime = lastUpdateTime; } - public void setAutoReleaseLocksEnabled(boolean on) - { - autoReleaseLocksEnabled = on; - } - public void setCommitNumber(int commitNumber) { this.commitNumber = commitNumber; @@ -586,6 +566,38 @@ public class TransactionCommitContext implements InternalCommitContext lobs = in; } + @Deprecated + public boolean isAutoReleaseLocksEnabled() + { + return false; + } + + @Deprecated + public void setAutoReleaseLocksEnabled(boolean on) + { + // Do nothing. + } + + public CDOLockState[] getLocksOnNewObjects() + { + return locksOnNewObjects; + } + + public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects) + { + this.locksOnNewObjects = locksOnNewObjects; + } + + public CDOID[] getIDsToUnlock() + { + return idsToUnlock; + } + + public void setIDsToUnlock(CDOID[] idsToUnlock) + { + this.idsToUnlock = idsToUnlock; + } + public <T> T getData(Object key) { if (data == null) @@ -1107,50 +1119,6 @@ public class TransactionCommitContext implements InternalCommitContext } } - protected synchronized void unlockObjects() - { - // Unlock objects locked during commit - if (!lockedObjects.isEmpty()) - { - lockManager.unlock2(LockType.WRITE, transaction, lockedObjects); - lockedObjects.clear(); - } - - // Release durable locks that have been acquired on detached objects - if (detachedObjects.length > 0) - { - boolean branching = repository.isSupportingBranches(); - Collection<? extends Object> unlockables; - if (branching) - { - List<CDOIDAndBranch> keys = new ArrayList<CDOIDAndBranch>(detachedObjects.length); - for (CDOID id : detachedObjects) - { - CDOIDAndBranch idAndBranch = CDOIDUtil.createIDAndBranch(id, branch); - keys.add(idAndBranch); - } - - unlockables = keys; - } - else - { - unlockables = Arrays.asList(detachedObjects); - } - - // We only need to consider detached objects that have been explicitly locked - Collection<Object> detachedObjectsToUnlock = new ArrayList<Object>(); - for (Object unlockable : unlockables) - { - if (lockManager.hasLock(LockType.WRITE, transaction, unlockable)) - { - detachedObjectsToUnlock.add(unlockable); - } - } - - lockManager.unlock2(true, LockType.WRITE, transaction, detachedObjectsToUnlock, false); - } - } - protected void computeDirtyObjects(OMMonitor monitor) { try @@ -1355,7 +1323,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - unlockObjects(); + releaseImplicitLocks(); } } @@ -1374,24 +1342,22 @@ public class TransactionCommitContext implements InternalCommitContext addRevisions(dirtyObjects, monitor.fork()); reviseDetachedObjects(monitor.fork()); - unlockObjects(); + releaseImplicitLocks(); monitor.worked(); - applyLocksOnNewObjects(); + acquireLocksOnNewObjects(); monitor.worked(); - if (autoReleaseLocksEnabled) + autoReleaseExplicitLocks(); + monitor.worked(); + + if (!postCommitLockStates.isEmpty()) { - postCommitLockStates = lockManager.unlock2(true, transaction); - if (!postCommitLockStates.isEmpty()) - { - // TODO (CD) Does doing this here make sense? - // The commit notifications get sent later, from postCommit. - sendLockNotifications(postCommitLockStates); - } + // TODO (CD) Does doing this here make sense? + // The commit notifications get sent later, from postCommit. + sendLockNotifications(postCommitLockStates); } - monitor.worked(); repository.notifyWriteAccessHandlers(transaction, this, false, monitor.fork()); } catch (Throwable t) @@ -1404,15 +1370,26 @@ public class TransactionCommitContext implements InternalCommitContext } } - protected void applyLocksOnNewObjects() throws InterruptedException + protected synchronized void releaseImplicitLocks() + { + // Unlock objects locked during commit + if (!lockedObjects.isEmpty()) + { + lockManager.unlock2(LockType.WRITE, transaction, lockedObjects); + lockedObjects.clear(); + } + } + + protected void acquireLocksOnNewObjects() throws InterruptedException { final CDOLockOwner owner = CDOLockUtil.createLockOwner(transaction); + final boolean mapIDs = transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE; for (CDOLockState lockState : locksOnNewObjects) { Object target = lockState.getLockedObject(); - if (transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE) + if (mapIDs) { CDOIDAndBranch idAndBranch = target instanceof CDOIDAndBranch ? (CDOIDAndBranch)target : null; CDOID id = idAndBranch != null ? ((CDOIDAndBranch)target).getID() : (CDOID)target; @@ -1422,13 +1399,60 @@ public class TransactionCommitContext implements InternalCommitContext target = idAndBranch != null ? CDOIDUtil.createIDAndBranch(newID, idAndBranch.getBranch()) : newID; } + LockState<Object, IView> postCommitLockState = null; for (LockType type : LockType.values()) { if (lockState.isLocked(type, owner, false)) { - lockManager.lock2(type, transaction, Collections.singleton(target), 0); + List<LockState<Object, IView>> lockStates = lockManager.lock2(type, transaction, + Collections.singleton(target), 0); + postCommitLockState = lockStates.get(0); } } + + if (postCommitLockState != null) + { + postCommitLockStates.add(postCommitLockState); + } + } + } + + protected void autoReleaseExplicitLocks() throws InterruptedException + { + List<Object> targets = new ArrayList<Object>(); + + // Release locks that have been sent from the client. + for (CDOID id : idsToUnlock) + { + Object target = lockManager.getLockKey(id, branch); + targets.add(target); + } + + // Release durable locks that have been acquired on detached objects. + for (CDOID id : detachedObjects) + { + Object target = lockManager.getLockKey(id, branch); + if (lockManager.hasLock(LockType.WRITE, transaction, target)) + { + // We only need to consider detached objects that have been explicitly locked + targets.add(target); + } + } + + try + { + RWOLockManager.setUnlockAll(true); + + List<LockState<Object, IView>> lockStates = lockManager.unlock2(true, LockType.WRITE, transaction, targets, + false); + if (lockStates != null) + { + postCommitLockStates.addAll(lockStates); + } + } + finally + { + RWOLockManager.setUnlockAll(false); } } |