[577300] Optimize CDOLockState caching
https://bugs.eclipse.org/bugs/show_bug.cgi?id=577300
diff --git a/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters
index 2894e75..89de9d5 100644
--- a/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters
+++ b/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters
@@ -457,13 +457,15 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockState.java" type="org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockState">
+ <resource path="src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockChangeInfo.java" type="org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockChangeInfo">
<filter id="576725006">
<message_arguments>
- <message_argument value="CDOLockState"/>
- <message_argument value="AbstractCDOLockState"/>
+ <message_argument value="CDOLockChangeInfo"/>
+ <message_argument value="AbstractCDOLockChangeInfo"/>
</message_arguments>
</filter>
+ </resource>
+ <resource path="src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockState.java" type="org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockState">
<filter id="576725006">
<message_arguments>
<message_argument value="InternalCDOLockState"/>
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java
index f91a3fb..e0efd87 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java
@@ -12,10 +12,11 @@
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import java.util.List;
+import java.util.Set;
/**
* Represents a change in the lock state of a set of objects. Instances are meant to be sent from the server to the
@@ -29,12 +30,6 @@
public interface CDOLockChangeInfo extends CDOBranchPoint
{
/**
- * @return <code>true</code> if this instance signals that all {@link CDOLockState lock states} must be invalidated,
- * <code>false</code> otherwise
- */
- public boolean isInvalidateAll();
-
- /**
* @return The branch at which the lock changes took place, same as <code>getView().getBranch()</code>.
*/
@Override
@@ -48,31 +43,54 @@
public long getTimeStamp();
/**
- * @return the type of lock operation that caused the lock changes
- */
- public Operation getOperation();
-
- /**
- * @return the type of locks that were affected by the lock operation
- */
- public LockType getLockType();
-
- /**
* @return The view, represented as a {@link CDOLockOwner}, that authored the lock changes.
*/
public CDOLockOwner getLockOwner();
/**
- * @return The new lock states of the objects that were affected by the change
- * @deprecated As of 4.15 use the faster {@link #getNewLockStates()} method.
+ * @since 4.15
*/
- @Deprecated
+ public CDOLockDelta[] getLockDeltas();
+
+ /**
+ * @return The new lock states of the objects that were affected by the change
+ */
public CDOLockState[] getLockStates();
/**
* @since 4.15
*/
- public List<CDOLockState> getNewLockStates();
+ public Set<Operation> getOperations();
+
+ /**
+ * @since 4.15
+ */
+ public Set<LockType> getLockTypes();
+
+ /**
+ * @since 4.15
+ */
+ public Set<CDOID> getAffectedIDs();
+
+ /**
+ * @return <code>true</code> if this instance signals that all {@link CDOLockState lock states} must be invalidated,
+ * <code>false</code> otherwise
+ */
+ public boolean isInvalidateAll();
+
+ /**
+ * @return the type of lock operation that caused the lock changes
+ * @deprecated As of 4.15 use {@link #getOperations()}.
+ */
+ @Deprecated
+ public Operation getOperation();
+
+ /**
+ * @return the type of locks that were affected by the lock operation
+ * @deprecated As of 4.15 use {@link #getLockTypes()}.
+ */
+ @Deprecated
+ public LockType getLockType();
/**
* Enumerates the possible locking operations.
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockDelta.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockDelta.java
new file mode 100644
index 0000000..4d79d02
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockDelta.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.common.lock;
+
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+
+/**
+ * @author Eike Stepper
+ * @since 4.15
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface CDOLockDelta extends CDOIDAndBranch
+{
+ public Object getTarget();
+
+ public LockType getType();
+
+ public CDOLockOwner getOldOwner();
+
+ public CDOLockOwner getNewOwner();
+
+ public Kind getKind();
+
+ /**
+ * @author Eike Stepper
+ */
+ public enum Kind
+ {
+ ADDED, REMOVED, REMAPPED;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockState.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockState.java
index e33bf8e..af4734b 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockState.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockState.java
@@ -57,7 +57,7 @@
* If the 'others' argument is <code>true</code>, this method returns <code>true</code> if this lock is currently held
* by <i>another</i> view (i.e. any view different from the requesting one), <code>false</code> otherwise.
*/
- public boolean isLocked(LockType lockType, CDOLockOwner lockOwner, boolean others);
+ public boolean isLocked(LockType type, CDOLockOwner by, boolean others);
public Set<CDOLockOwner> getReadLockOwners();
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java
index d680925..af241f0 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java
@@ -20,17 +20,20 @@
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.internal.common.lock.CDOLockAreaImpl;
import org.eclipse.emf.cdo.internal.common.lock.CDOLockChangeInfoImpl;
+import org.eclipse.emf.cdo.internal.common.lock.CDOLockDeltaImpl;
import org.eclipse.emf.cdo.internal.common.lock.CDOLockStateImpl;
import org.eclipse.emf.cdo.internal.common.lock.DurableCDOLockOwner;
import org.eclipse.emf.cdo.internal.common.lock.NormalCDOLockOwner;
import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
import org.eclipse.net4j.util.HexUtil;
+import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -52,6 +55,16 @@
*/
public static final int DURABLE_VIEW_ID = 0;
+ /**
+ * @since 4.15
+ */
+ public static final CDOLockState[] NO_LOCK_STATES = {};
+
+ /**
+ * @since 4.15
+ */
+ public static final CDOLockDelta[] NO_LOCK_DELTAS = {};
+
private CDOLockUtil()
{
}
@@ -103,19 +116,6 @@
return -1;
}
- public static CDOLockState copyLockState(CDOLockState lockState)
- {
- return ((CDOLockStateImpl)lockState).copy();
- }
-
- /**
- * @since 4.12
- */
- public static CDOLockState copyLockState(CDOLockState lockState, Object lockedObject)
- {
- return ((CDOLockStateImpl)lockState).copy(lockedObject);
- }
-
/**
* @since 4.15
*/
@@ -123,21 +123,21 @@
{
InternalCDOLockState cdoLockState = new CDOLockStateImpl(lockState.getLockedObject());
- for (CDOCommonView view : lockState.getReadLockOwners())
+ for (CDOCommonView readLockOwner : lockState.getReadLockOwners())
{
- cdoLockState.addReadLockOwner(createLockOwner(view));
+ cdoLockState.addOwner(createLockOwner(readLockOwner), LockType.READ);
}
CDOCommonView writeLockOwner = lockState.getWriteLockOwner();
if (writeLockOwner != null)
{
- cdoLockState.setWriteLockOwner(createLockOwner(writeLockOwner));
+ cdoLockState.addOwner(createLockOwner(writeLockOwner), LockType.WRITE);
}
CDOCommonView writeOptionOwner = lockState.getWriteOptionOwner();
if (writeOptionOwner != null)
{
- cdoLockState.setWriteOptionOwner(createLockOwner(writeOptionOwner));
+ cdoLockState.addOwner(createLockOwner(writeOptionOwner), LockType.OPTION);
}
return cdoLockState;
@@ -148,15 +148,6 @@
return new CDOLockStateImpl(target);
}
- /**
- * @deprecated As of 4.15 use {@link #convertLockState(LockState)}.
- */
- @Deprecated
- public static CDOLockState createLockState(LockState<Object, ? extends CDOCommonView> lockState)
- {
- return convertLockState(lockState);
- }
-
public static CDOLockOwner createLockOwner(CDOCommonView view)
{
int sessionID = view.getSessionID();
@@ -179,22 +170,28 @@
}
/**
- * @deprecated As of 4.15 use the faster {@link #createLockChangeInfo(CDOBranchPoint, CDOLockOwner, Operation, LockType, Collection)} method.
+ * @since 4.15
*/
- @Deprecated
- public static CDOLockChangeInfo createLockChangeInfo(long timestamp, CDOLockOwner lockOwner, CDOBranch branch, Operation op, LockType lockType,
- CDOLockState[] newLockStates)
+ public static CDOLockDelta createLockDelta(Object target, LockType type, CDOLockOwner oldOwner, CDOLockOwner newOwner)
{
- return createLockChangeInfo(branch.getPoint(timestamp), lockOwner, op, lockType, Arrays.asList(newLockStates));
+ return CDOLockDeltaImpl.create(target, type, oldOwner, newOwner);
}
/**
* @since 4.15
*/
- public static CDOLockChangeInfo createLockChangeInfo(CDOBranchPoint branchPoint, CDOLockOwner lockOwner, Operation op, LockType lockType,
- Collection<? extends CDOLockState> newLockStates)
+ public static CDOLockDelta createLockDelta(Object target)
{
- return new CDOLockChangeInfoImpl(branchPoint, lockOwner, op, lockType, newLockStates);
+ return CDOLockDeltaImpl.createNull(target);
+ }
+
+ /**
+ * @since 4.15
+ */
+ public static CDOLockChangeInfo createLockChangeInfo(CDOBranchPoint branchPoint, CDOLockOwner lockOwner, Collection<CDOLockDelta> lockDeltas,
+ Collection<CDOLockState> lockStates)
+ {
+ return new CDOLockChangeInfoImpl(branchPoint, lockOwner, lockDeltas, lockStates);
}
public static CDOLockChangeInfo createLockChangeInfo()
@@ -202,13 +199,6 @@
return new CDOLockChangeInfoImpl();
}
- public static CDOLockChangeInfo createLockChangeInfo(long timestamp, CDOCommonView view, CDOBranch viewedBranch, Operation op, LockType lockType,
- CDOLockState[] newLockStates)
- {
- CDOLockOwner lockOwner = createLockOwner(view);
- return createLockChangeInfo(timestamp, lockOwner, viewedBranch, op, lockType, newLockStates);
- }
-
public static LockArea createLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks)
{
return new CDOLockAreaImpl(durableLockingID, userID, branchPoint, readOnly, locks);
@@ -233,4 +223,91 @@
return HexUtil.bytesToHex(buffer);
}
+
+ /**
+ * @since 4.15
+ */
+ public static List<CDOLockDelta> appendLockDelta(List<CDOLockDelta> deltas, Object target, LockType type, CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ return appendLockDelta(deltas, createLockDelta(target, type, oldOwner, newOwner));
+ }
+
+ /**
+ * @since 4.15
+ */
+ public static List<CDOLockDelta> appendLockDelta(List<CDOLockDelta> deltas, CDOLockDelta delta)
+ {
+ if (delta != null)
+ {
+ if (deltas == null)
+ {
+ deltas = new ArrayList<>(1);
+ }
+
+ deltas.add(delta);
+ }
+
+ return deltas;
+ }
+
+ /**
+ * @since 4.15
+ */
+ public static CDOLockDelta[] toArray(List<CDOLockDelta> deltas)
+ {
+ if (ObjectUtil.isEmpty(deltas))
+ {
+ return NO_LOCK_DELTAS;
+ }
+
+ return deltas.toArray(new CDOLockDelta[deltas.size()]);
+ }
+
+ /**
+ * @deprecated As of 4.15 no longer supported.
+ */
+ @Deprecated
+ public static CDOLockState copyLockState(CDOLockState lockState)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 4.12
+ * @deprecated As of 4.15 no longer supported.
+ */
+ @Deprecated
+ public static CDOLockState copyLockState(CDOLockState lockState, Object lockedObject)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated As of 4.15 use {@link #convertLockState(LockState)}.
+ */
+ @Deprecated
+ public static CDOLockState createLockState(LockState<Object, ? extends CDOCommonView> lockState)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated As of 4.15 use {@link #createLockChangeInfo(CDOBranchPoint, CDOLockOwner, Collection, Collection)}.
+ */
+ @Deprecated
+ public static CDOLockChangeInfo createLockChangeInfo(long timestamp, CDOLockOwner lockOwner, CDOBranch branch, Operation op, LockType lockType,
+ CDOLockState[] newLockStates)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated As of 4.15 use {@link #createLockChangeInfo(CDOBranchPoint, CDOLockOwner, Collection, Collection)}.
+ */
+ @Deprecated
+ public static CDOLockChangeInfo createLockChangeInfo(long timestamp, CDOCommonView view, CDOBranch viewedBranch, Operation op, LockType lockType,
+ CDOLockState[] newLockStates)
+ {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java
index 5352967..9156d48 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/IDurableLockingManager.java
@@ -17,6 +17,7 @@
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import java.util.Map;
+import java.util.function.Consumer;
/**
* Manages all persistent aspects of durable CDO views such as {@link CDOBranchPoint branch point} and acquired locks.
@@ -198,8 +199,38 @@
return (value & 4) != 0;
}
+ /**
+ * @since 4.15
+ */
+ public void forEachLockType(Consumer<LockType> consumer)
+ {
+ if (consumer != null)
+ {
+ if (isRead())
+ {
+ consumer.accept(LockType.READ);
+ }
+
+ if (isWrite())
+ {
+ consumer.accept(LockType.WRITE);
+ }
+
+ if (isOption())
+ {
+ consumer.accept(LockType.OPTION);
+ }
+ }
+ }
+
public LockGrade getUpdated(LockType type, boolean on)
{
+ if (type == null && !on)
+ {
+ // Unlock all types.
+ return NONE;
+ }
+
int mask = getMask(type);
if (on)
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java
index d1752f3..24d037b 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataInput.java
@@ -20,6 +20,7 @@
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDReference;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
@@ -46,6 +47,8 @@
import org.eclipse.emf.ecore.resource.ResourceSet;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* Provides I/O methods for reading various CDO data types and concepts from streams.
@@ -172,6 +175,51 @@
public CDOLockState readCDOLockState() throws IOException;
/**
+ * @since 4.15
+ */
+ default List<CDOLockState> readCDOLockStates() throws IOException
+ {
+ List<CDOLockState> lockDeltas = new ArrayList<>();
+ for (;;)
+ {
+ CDOLockState lockState = readCDOLockState();
+ if (lockState == null)
+ {
+ break;
+ }
+
+ lockDeltas.add(lockState);
+ }
+
+ return lockDeltas;
+ }
+
+ /**
+ * @since 4.15
+ */
+ public CDOLockDelta readCDOLockDelta() throws IOException;
+
+ /**
+ * @since 4.15
+ */
+ default List<CDOLockDelta> readCDOLockDeltas() throws IOException
+ {
+ List<CDOLockDelta> lockDeltas = new ArrayList<>();
+ for (;;)
+ {
+ CDOLockDelta lockDelta = readCDOLockDelta();
+ if (lockDelta == null)
+ {
+ break;
+ }
+
+ lockDeltas.add(lockDelta);
+ }
+
+ return lockDeltas;
+ }
+
+ /**
* @since 4.1
*/
public LockArea readCDOLockArea() throws IOException;
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java
index 7c4b8c8..a18b36f 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDODataOutput.java
@@ -21,6 +21,7 @@
import org.eclipse.emf.cdo.common.id.CDOIDProvider;
import org.eclipse.emf.cdo.common.id.CDOIDReference;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
@@ -48,7 +49,9 @@
import org.eclipse.emf.ecore.EStructuralFeature;
import java.io.IOException;
+import java.util.List;
import java.util.Set;
+import java.util.function.Predicate;
/**
* Provides I/O methods for writing various CDO data types and concepts to streams.
@@ -189,6 +192,63 @@
public void writeCDOLockState(CDOLockState lockState) throws IOException;
/**
+ * @since 4.15
+ */
+ default void writeCDOLockStates(List<CDOLockState> lockStates, Predicate<CDOLockState> filter) throws IOException
+ {
+ if (filter != null)
+ {
+ for (CDOLockState lockState : lockStates)
+ {
+ if (filter.test(lockState))
+ {
+ writeCDOLockState(lockState);
+ }
+ }
+ }
+ else
+ {
+ for (CDOLockState state : lockStates)
+ {
+ writeCDOLockState(state);
+ }
+ }
+
+ writeCDOLockState(null);
+ }
+
+ /**
+ * @since 4.15
+ */
+ public void writeCDOLockDelta(CDOLockDelta lockDelta) throws IOException;
+
+ /**
+ * @since 4.15
+ */
+ default void writeCDOLockDeltas(List<CDOLockDelta> lockDeltas, Predicate<CDOLockDelta> filter) throws IOException
+ {
+ if (filter != null)
+ {
+ for (CDOLockDelta lockDelta : lockDeltas)
+ {
+ if (filter.test(lockDelta))
+ {
+ writeCDOLockDelta(lockDelta);
+ }
+ }
+ }
+ else
+ {
+ for (CDOLockDelta lockDelta : lockDeltas)
+ {
+ writeCDOLockDelta(lockDelta);
+ }
+ }
+
+ writeCDOLockDelta(null);
+ }
+
+ /**
* @since 4.1
*/
public void writeCDOLockOwner(CDOLockOwner lockOwner) throws IOException;
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
index 0de822d..22b7caf 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
@@ -415,6 +415,11 @@
public static final int RELEASE_ALL_LOCKS = -1;
+ /**
+ * @since 4.15
+ */
+ public static final long DEFAULT_OPTIMISTIC_LOCKING_TIMEOUT = -2;
+
// //////////////////////////////////////////////////////////////////////
// Remote Sessions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java
index 3a63be6..546a5e5 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java
@@ -13,51 +13,52 @@
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.spi.common.branch.CDOBranchAdjustable;
+import org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockChangeInfo;
-import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.event.INotifier;
+import org.eclipse.net4j.util.event.Notifier;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
/**
* @author Caspar De Groot
*/
-public final class CDOLockChangeInfoImpl implements CDOLockChangeInfo, CDOBranchAdjustable
+public final class CDOLockChangeInfoImpl extends AbstractCDOLockChangeInfo implements CDOBranchAdjustable
{
+ private static final INotifier SOURCE = new Notifier();
+
+ private static final long serialVersionUID = 1L;
+
private CDOBranchPoint branchPoint;
private final CDOLockOwner lockOwner;
- private final Operation operation;
+ private final CDOLockDelta[] lockDeltas;
- private final LockType lockType;
-
- private final List<CDOLockState> lockStates;
+ private final CDOLockState[] lockStates;
private final boolean isInvalidateAll;
- public CDOLockChangeInfoImpl(CDOBranchPoint branchPoint, CDOLockOwner lockOwner, Operation operation, LockType lockType,
- Collection<? extends CDOLockState> lockStates)
+ public CDOLockChangeInfoImpl(CDOBranchPoint branchPoint, CDOLockOwner lockOwner, Collection<CDOLockDelta> lockDeltas, Collection<CDOLockState> lockStates)
{
+ super(SOURCE);
this.branchPoint = branchPoint;
this.lockOwner = lockOwner;
- this.operation = operation;
- this.lockType = lockType;
- this.lockStates = Collections.unmodifiableList(lockStates instanceof List ? (List<? extends CDOLockState>)lockStates : new ArrayList<>(lockStates));
+ this.lockDeltas = lockDeltas.toArray(new CDOLockDelta[lockDeltas.size()]);
+ this.lockStates = lockStates.toArray(new CDOLockState[lockStates.size()]);
isInvalidateAll = false;
}
public CDOLockChangeInfoImpl()
{
+ super(null);
lockOwner = null;
- operation = null;
- lockType = null;
+ lockDeltas = null;
lockStates = null;
isInvalidateAll = true;
}
@@ -89,32 +90,19 @@
}
@Override
- public Operation getOperation()
- {
- return operation;
- }
-
- @Override
- public LockType getLockType()
- {
- return lockType;
- }
-
- @Override
public CDOLockOwner getLockOwner()
{
return lockOwner;
}
- @Deprecated
@Override
- public CDOLockState[] getLockStates()
+ public CDOLockDelta[] getLockDeltas()
{
- return lockStates.toArray(new CDOLockState[lockStates.size()]);
+ return lockDeltas;
}
@Override
- public List<CDOLockState> getNewLockStates()
+ public CDOLockState[] getLockStates()
{
return lockStates;
}
@@ -131,16 +119,17 @@
StringBuilder builder = new StringBuilder();
builder.append("CDOLockChangeInfo[branchPoint=");
builder.append(branchPoint);
- builder.append(", operation=");
- builder.append(operation);
- builder.append(", lockType=");
- builder.append(lockType == null ? "ALL" : lockType);
- builder.append(", lockOwner=");
- builder.append(lockOwner);
- builder.append(", lockStates=");
- builder.append(lockStates);
- builder.append(", invalidateAll=");
- builder.append(isInvalidateAll);
+
+ if (isInvalidateAll)
+ {
+ builder.append(", invalidateAll");
+ }
+ else
+ {
+ builder.append(", deltas=");
+ builder.append(Arrays.asList(lockDeltas));
+ }
+
builder.append("]");
return builder.toString();
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockDeltaImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockDeltaImpl.java
new file mode 100644
index 0000000..4a0356e
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockDeltaImpl.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2021 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.common.lock;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockState;
+
+import org.eclipse.net4j.util.CheckUtil;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class CDOLockDeltaImpl implements CDOLockDelta
+{
+ protected final Object target;
+
+ protected final CDOLockOwner oldOwner;
+
+ protected final CDOLockOwner newOwner;
+
+ private CDOLockDeltaImpl(Object target, CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ CheckUtil.checkArg(target, "target");
+ CheckUtil.checkArg(oldOwner != null || newOwner != null, "oldOwner != null || newOwner != null");
+
+ this.target = target;
+ this.oldOwner = oldOwner;
+ this.newOwner = newOwner;
+ }
+
+ @Override
+ public final Object getTarget()
+ {
+ return target;
+ }
+
+ @Override
+ public final CDOID getID()
+ {
+ return CDOLockUtil.getLockedObjectID(target);
+ }
+
+ @Override
+ public final CDOBranch getBranch()
+ {
+ return CDOLockUtil.getLockedObjectBranch(target);
+ }
+
+ @Override
+ public final CDOLockOwner getOldOwner()
+ {
+ return oldOwner;
+ }
+
+ @Override
+ public final CDOLockOwner getNewOwner()
+ {
+ return newOwner;
+ }
+
+ @Override
+ public final Kind getKind()
+ {
+ if (oldOwner == null)
+ {
+ return Kind.ADDED;
+ }
+
+ if (newOwner == null)
+ {
+ return Kind.REMOVED;
+ }
+
+ return Kind.REMAPPED;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append(getKind());
+ builder.append('_');
+ builder.append(getType());
+ builder.append('[');
+ builder.append(target);
+
+ if (oldOwner != null)
+ {
+ builder.append(" - ");
+ AbstractCDOLockState.appendLockOwner(builder, oldOwner);
+ }
+
+ if (newOwner != null)
+ {
+ builder.append(" + ");
+ AbstractCDOLockState.appendLockOwner(builder, newOwner);
+ }
+
+ builder.append(']');
+ return builder.toString();
+ }
+
+ public static CDOLockDelta create(Object target, LockType type, CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ switch (type)
+ {
+ case READ:
+ return new Read(target, oldOwner, newOwner);
+
+ case WRITE:
+ return new Write(target, oldOwner, newOwner);
+
+ case OPTION:
+ return new Option(target, oldOwner, newOwner);
+
+ default:
+ throw new IllegalArgumentException("Illegal type: " + type);
+ }
+ }
+
+ public static CDOLockDelta createNull(Object target)
+ {
+ return new Null(target);
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class Null implements CDOLockDelta
+ {
+ private final Object target;
+
+ public Null(Object target)
+ {
+ CheckUtil.checkArg(target, "target");
+ this.target = target;
+ }
+
+ @Override
+ public Object getTarget()
+ {
+ return target;
+ }
+
+ @Override
+ public final CDOID getID()
+ {
+ return CDOLockUtil.getLockedObjectID(target);
+ }
+
+ @Override
+ public final CDOBranch getBranch()
+ {
+ return CDOLockUtil.getLockedObjectBranch(target);
+ }
+
+ @Override
+ public LockType getType()
+ {
+ return null;
+ }
+
+ @Override
+ public CDOLockOwner getOldOwner()
+ {
+ return null;
+ }
+
+ @Override
+ public CDOLockOwner getNewOwner()
+ {
+ return null;
+ }
+
+ @Override
+ public Kind getKind()
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class Read extends CDOLockDeltaImpl
+ {
+ public Read(Object target, CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ super(target, oldOwner, newOwner);
+ }
+
+ @Override
+ public LockType getType()
+ {
+ return LockType.READ;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class Write extends CDOLockDeltaImpl
+ {
+ public Write(Object target, CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ super(target, oldOwner, newOwner);
+ }
+
+ @Override
+ public LockType getType()
+ {
+ return LockType.WRITE;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class Option extends CDOLockDeltaImpl
+ {
+ public Option(Object target, CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ super(target, oldOwner, newOwner);
+ }
+
+ @Override
+ public LockType getType()
+ {
+ return LockType.OPTION;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java
index 7d5aca6..c1628fd 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java
@@ -10,33 +10,27 @@
*/
package org.eclipse.emf.cdo.internal.common.lock;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
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.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockState;
-import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
* @author Caspar De Groot
*/
-public final class CDOLockStateImpl extends AbstractCDOLockState implements InternalCDOLockState
+public final class CDOLockStateImpl extends AbstractCDOLockState
{
private static final Set<CDOLockOwner> NO_LOCK_OWNERS = Collections.emptySet();
private static final Class<CDOLockOwner[]> ARRAY_CLASS = CDOLockOwner[].class;
- private final Object lockedObject;
-
private Object readLockOwners;
private CDOLockOwner writeLockOwner;
@@ -45,15 +39,7 @@
public CDOLockStateImpl(Object lockedObject)
{
- assert lockedObject instanceof CDOID || lockedObject instanceof CDOIDAndBranch : "lockedObject is of wrong type";
- assert !CDOIDUtil.isNull(CDOLockUtil.getLockedObjectID(lockedObject)) : "lockedObject is null";
- this.lockedObject = lockedObject;
- }
-
- @Override
- public Object getLockedObject()
- {
- return lockedObject;
+ super(lockedObject);
}
@Override
@@ -92,23 +78,23 @@
}
@Override
- public boolean isLocked(LockType lockType, CDOLockOwner lockOwner, boolean others)
+ public boolean isLocked(LockType type, CDOLockOwner by, boolean others)
{
- if (lockType == null)
+ if (type == null)
{
- return isReadLocked(lockOwner, others) || isWriteLocked(lockOwner, others) || isOptionLocked(lockOwner, others);
+ return isReadLocked(by, others) || isWriteLocked(by, others) || isOptionLocked(by, others);
}
- switch (lockType)
+ switch (type)
{
case READ:
- return isReadLocked(lockOwner, others);
+ return isReadLocked(by, others);
case WRITE:
- return isWriteLocked(lockOwner, others);
+ return isWriteLocked(by, others);
case OPTION:
- return isOptionLocked(lockOwner, others);
+ return isOptionLocked(by, others);
}
return false;
@@ -171,46 +157,75 @@
}
@Override
- public void addReadLockOwner(CDOLockOwner lockOwner)
+ protected CDOLockDelta addReadOwner(CDOLockOwner owner)
{
if (readLockOwners == null)
{
- readLockOwners = lockOwner;
- return;
+ readLockOwners = owner;
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.READ, null, owner);
}
if (readLockOwners.getClass() == ARRAY_CLASS)
{
CDOLockOwner[] owners = (CDOLockOwner[])readLockOwners;
- if (CDOLockUtil.indexOf(owners, lockOwner) == -1)
+ if (CDOLockUtil.indexOf(owners, owner) == -1)
{
int oldLength = owners.length;
readLockOwners = new CDOLockOwner[oldLength + 1];
System.arraycopy(owners, 0, readLockOwners, 0, oldLength);
- ((CDOLockOwner[])readLockOwners)[oldLength] = lockOwner;
+ ((CDOLockOwner[])readLockOwners)[oldLength] = owner;
+
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.READ, null, owner);
}
- return;
+ return null;
}
- if (readLockOwners != lockOwner)
+ if (readLockOwners != owner)
{
- readLockOwners = new CDOLockOwner[] { (CDOLockOwner)readLockOwners, lockOwner };
+ readLockOwners = new CDOLockOwner[] { (CDOLockOwner)readLockOwners, owner };
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.READ, null, owner);
}
+
+ return null;
}
@Override
- public boolean removeReadLockOwner(CDOLockOwner lockOwner)
+ protected CDOLockDelta addWriteOwner(CDOLockOwner owner)
+ {
+ if (writeLockOwner == null)
+ {
+ writeLockOwner = owner;
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.WRITE, null, owner);
+ }
+
+ return null;
+ }
+
+ @Override
+ protected CDOLockDelta addOptionOwner(CDOLockOwner owner)
+ {
+ if (writeOptionOwner == null)
+ {
+ writeOptionOwner = owner;
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.OPTION, null, owner);
+ }
+
+ return null;
+ }
+
+ @Override
+ protected CDOLockDelta removeReadOwner(CDOLockOwner owner)
{
if (readLockOwners == null)
{
- return false;
+ return null;
}
if (readLockOwners.getClass() == ARRAY_CLASS)
{
CDOLockOwner[] owners = (CDOLockOwner[])readLockOwners;
- int index = CDOLockUtil.indexOf(owners, lockOwner);
+ int index = CDOLockUtil.indexOf(owners, owner);
if (index != -1)
{
int oldLength = owners.length;
@@ -227,140 +242,81 @@
System.arraycopy(owners, index + 1, readLockOwners, index, rest);
}
- return true;
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.READ, owner, null);
}
- return false;
+ return null;
}
- if (readLockOwners == lockOwner)
+ if (readLockOwners == owner)
{
readLockOwners = null;
- return true;
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.READ, owner, null);
}
- return false;
+ return null;
}
@Override
- public void setWriteLockOwner(CDOLockOwner lockOwner)
+ protected CDOLockDelta removeWriteOwner(CDOLockOwner owner)
{
- writeLockOwner = lockOwner;
- }
-
- @Override
- public void setWriteOptionOwner(CDOLockOwner lockOwner)
- {
- writeOptionOwner = lockOwner;
- }
-
- @Override
- public boolean removeOwner(CDOLockOwner lockOwner)
- {
- boolean changed = removeReadLockOwner(lockOwner);
-
- if (writeLockOwner == lockOwner)
+ if (writeLockOwner == owner)
{
writeLockOwner = null;
- changed = true;
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.WRITE, owner, null);
}
- if (writeOptionOwner == lockOwner)
- {
- writeOptionOwner = null;
- changed = true;
- }
-
- return changed;
+ return null;
}
@Override
- public boolean remapOwner(CDOLockOwner oldLockOwner, CDOLockOwner newLockOwner)
+ protected CDOLockDelta removeOptionOwner(CDOLockOwner owner)
{
- boolean changed = false;
+ if (writeOptionOwner == owner)
+ {
+ writeOptionOwner = null;
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.OPTION, owner, null);
+ }
+
+ return null;
+ }
+
+ @Override
+ public CDOLockDelta[] remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ List<CDOLockDelta> deltas = null;
if (readLockOwners != null)
{
- if (readLockOwners == oldLockOwner)
+ if (readLockOwners == oldOwner)
{
- readLockOwners = newLockOwner;
- changed = true;
+ readLockOwners = newOwner;
+ deltas = CDOLockUtil.appendLockDelta(deltas, lockedObject, LockType.READ, oldOwner, newOwner);
}
-
- if (readLockOwners.getClass() == ARRAY_CLASS)
+ else if (readLockOwners.getClass() == ARRAY_CLASS)
{
CDOLockOwner[] owners = (CDOLockOwner[])readLockOwners;
- int index = CDOLockUtil.indexOf(owners, oldLockOwner);
+ int index = CDOLockUtil.indexOf(owners, oldOwner);
if (index != -1)
{
- ((CDOLockOwner[])readLockOwners)[index] = newLockOwner;
- changed = true;
+ ((CDOLockOwner[])readLockOwners)[index] = newOwner;
+ deltas = CDOLockUtil.appendLockDelta(deltas, lockedObject, LockType.READ, oldOwner, newOwner);
}
}
}
- if (writeLockOwner == oldLockOwner)
+ if (writeLockOwner == oldOwner)
{
- writeLockOwner = newLockOwner;
- changed = true;
+ writeLockOwner = newOwner;
+ deltas = CDOLockUtil.appendLockDelta(deltas, lockedObject, LockType.WRITE, oldOwner, newOwner);
}
- if (writeOptionOwner == oldLockOwner)
+ if (writeOptionOwner == oldOwner)
{
- writeOptionOwner = newLockOwner;
- changed = true;
+ writeOptionOwner = newOwner;
+ deltas = CDOLockUtil.appendLockDelta(deltas, lockedObject, LockType.OPTION, oldOwner, newOwner);
}
- return changed;
- }
-
- public CDOLockStateImpl copy()
- {
- return copy(lockedObject);
- }
-
- public CDOLockStateImpl copy(Object lockedObject)
- {
- CDOLockStateImpl newLockState = new CDOLockStateImpl(lockedObject);
- copyReadLockOwners(newLockState);
- newLockState.writeLockOwner = writeLockOwner;
- newLockState.writeOptionOwner = writeOptionOwner;
- return newLockState;
- }
-
- private void copyReadLockOwners(CDOLockStateImpl target)
- {
- if (readLockOwners != null && readLockOwners.getClass() == ARRAY_CLASS)
- {
- CDOLockOwner[] owners = (CDOLockOwner[])readLockOwners;
- target.readLockOwners = Arrays.copyOf(owners, owners.length);
- return;
- }
-
- target.readLockOwners = readLockOwners;
- }
-
- @Override
- @Deprecated
- public void updateFrom(Object object, CDOLockState source)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void updateFrom(CDOLockState source)
- {
- CDOLockStateImpl lockState = (CDOLockStateImpl)source;
- lockState.copyReadLockOwners(this);
-
- writeLockOwner = lockState.writeLockOwner;
- writeOptionOwner = lockState.writeOptionOwner;
- }
-
- @Deprecated
- @Override
- public void dispose()
- {
- throw new UnsupportedOperationException();
+ return CDOLockUtil.toArray(deltas);
}
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java
index 83903e1..721065d 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java
@@ -508,10 +508,8 @@
try
{
- @SuppressWarnings("deprecation")
- List<RevisionInfo> additionalRevisionInfos = revisionLoader instanceof RevisionLoader3
- ? ((RevisionLoader3)revisionLoader).loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates)
- : revisionLoader.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth);
+ List<RevisionInfo> additionalRevisionInfos = ((RevisionLoader3)revisionLoader).loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth,
+ prefetchLockStates);
if (additionalRevisionInfos != null)
{
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockChangeInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockChangeInfo.java
new file mode 100644
index 0000000..8d88b55
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockChangeInfo.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.common.lock;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.event.Event;
+import org.eclipse.net4j.util.event.INotifier;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @since 4.15
+ */
+public abstract class AbstractCDOLockChangeInfo extends Event implements CDOLockChangeInfo
+{
+ private static final long serialVersionUID = 1L;
+
+ public AbstractCDOLockChangeInfo(INotifier notifier)
+ {
+ super(notifier);
+ }
+
+ @Override
+ public final Set<Operation> getOperations()
+ {
+ Set<Operation> result = new HashSet<>();
+
+ for (CDOLockDelta delta : getLockDeltas())
+ {
+ CDOLockDelta.Kind kind = delta.getKind();
+
+ switch (kind)
+ {
+ case ADDED:
+ result.add(Operation.LOCK);
+ break;
+
+ case REMOVED:
+ result.add(Operation.UNLOCK);
+ break;
+
+ case REMAPPED:
+ // Do nothing.
+ break;
+
+ default:
+ throw new AssertionError("Invalid kind: " + kind);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public final Set<LockType> getLockTypes()
+ {
+ Set<LockType> result = new HashSet<>();
+
+ for (CDOLockDelta delta : getLockDeltas())
+ {
+ LockType type = delta.getType();
+ result.add(type);
+ }
+
+ return result;
+ }
+
+ @Override
+ public final Set<CDOID> getAffectedIDs()
+ {
+ Set<CDOID> ids = new HashSet<>();
+
+ for (CDOLockDelta delta : getLockDeltas())
+ {
+ CDOID id = delta.getID();
+ ids.add(id);
+ }
+
+ return ids;
+ }
+
+ @Override
+ @Deprecated
+ public final Operation getOperation()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final LockType getLockType()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockState.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockState.java
index 13c48fc..a16e854 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockState.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/AbstractCDOLockState.java
@@ -12,12 +12,17 @@
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
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.revision.CDOIDAndBranch;
import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -26,32 +31,56 @@
* @since 4.15
* @noextend This class is not intended to be extended by clients.
*/
-public abstract class AbstractCDOLockState implements CDOLockState
+public abstract class AbstractCDOLockState implements InternalCDOLockState
{
- public AbstractCDOLockState()
+ protected Object lockedObject;
+
+ public AbstractCDOLockState(Object lockedObject)
{
+ assert lockedObject instanceof CDOID || lockedObject instanceof CDOIDAndBranch : "lockedObject is of wrong type";
+ assert !CDOIDUtil.isNull(CDOLockUtil.getLockedObjectID(lockedObject)) : "lockedObject is null";
+ this.lockedObject = lockedObject;
}
@Override
- public CDOBranch getBranch()
+ public final Object getLockedObject()
{
- return CDOLockUtil.getLockedObjectBranch(getLockedObject());
+ return lockedObject;
}
@Override
- public CDOID getID()
+ public final CDOID getID()
{
- return CDOLockUtil.getLockedObjectID(getLockedObject());
+ return CDOLockUtil.getLockedObjectID(lockedObject);
}
@Override
- public int hashCode()
+ public void remapID(CDOID newID)
{
- return Objects.hashCode(getLockedObject());
+ if (lockedObject instanceof CDOID)
+ {
+ lockedObject = newID;
+ }
+ else
+ {
+ lockedObject = CDOIDUtil.createIDAndBranch(newID, ((CDOIDAndBranch)lockedObject).getBranch());
+ }
}
@Override
- public boolean equals(Object obj)
+ public final CDOBranch getBranch()
+ {
+ return CDOLockUtil.getLockedObjectBranch(lockedObject);
+ }
+
+ @Override
+ public final int hashCode()
+ {
+ return Objects.hashCode(lockedObject);
+ }
+
+ @Override
+ public final boolean equals(Object obj)
{
if (this == obj)
{
@@ -69,7 +98,7 @@
}
CDOLockState other = (CDOLockState)obj;
- if (!getLockedObject().equals(other.getLockedObject()))
+ if (!lockedObject.equals(other.getLockedObject()))
{
return false;
}
@@ -93,10 +122,10 @@
}
@Override
- public String toString()
+ public final String toString()
{
StringBuilder builder = new StringBuilder("CDOLockState[lockedObject=");
- builder.append(getLockedObject());
+ builder.append(lockedObject);
Set<CDOLockOwner> readLockOwners = getReadLockOwners();
builder.append(", readLockOwners=");
@@ -106,7 +135,7 @@
boolean first = true;
for (CDOLockOwner lockOwner : readLockOwners)
{
- appendLockOwner(builder, lockOwner, first);
+ AbstractCDOLockState.appendLockOwner(builder, lockOwner, first);
first = false;
}
}
@@ -127,16 +156,137 @@
return builder.toString();
}
- private static void appendLockOwner(StringBuilder builder, CDOLockOwner lockOwner, boolean first)
+ @Override
+ public final CDOLockDelta addOwner(CDOLockOwner owner, LockType type)
+ {
+ switch (type)
+ {
+ case READ:
+ return addReadOwner(owner);
+
+ case WRITE:
+ return addWriteOwner(owner);
+
+ case OPTION:
+ return addOptionOwner(owner);
+
+ default:
+ throw new IllegalArgumentException("Illegal type: " + type);
+ }
+ }
+
+ @Override
+ public final CDOLockDelta removeOwner(CDOLockOwner owner, LockType type)
+ {
+ switch (type)
+ {
+ case READ:
+ return removeReadOwner(owner);
+
+ case WRITE:
+ return removeWriteOwner(owner);
+
+ case OPTION:
+ return removeOptionOwner(owner);
+
+ default:
+ throw new IllegalArgumentException("Illegal type: " + type);
+ }
+ }
+
+ @Override
+ public final CDOLockDelta[] clearOwner(CDOLockOwner owner)
+ {
+ List<CDOLockDelta> deltas = null;
+ deltas = CDOLockUtil.appendLockDelta(deltas, removeReadOwner(owner));
+ deltas = CDOLockUtil.appendLockDelta(deltas, removeWriteOwner(owner));
+ deltas = CDOLockUtil.appendLockDelta(deltas, removeOptionOwner(owner));
+ return CDOLockUtil.toArray(deltas);
+ }
+
+ protected abstract CDOLockDelta addReadOwner(CDOLockOwner owner);
+
+ protected abstract CDOLockDelta addWriteOwner(CDOLockOwner owner);
+
+ protected abstract CDOLockDelta addOptionOwner(CDOLockOwner owner);
+
+ protected abstract CDOLockDelta removeReadOwner(CDOLockOwner owner);
+
+ protected abstract CDOLockDelta removeWriteOwner(CDOLockOwner owner);
+
+ protected abstract CDOLockDelta removeOptionOwner(CDOLockOwner owner);
+
+ @Override
+ @Deprecated
+ public final void addReadLockOwner(CDOLockOwner owner)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final boolean removeReadLockOwner(CDOLockOwner owner)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final void setWriteLockOwner(CDOLockOwner owner)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final void setWriteOptionOwner(CDOLockOwner owner)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final boolean removeOwner(CDOLockOwner owner)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final void updateFrom(CDOLockState source)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final void updateFrom(Object object, CDOLockState source)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public final void dispose()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public static void appendLockOwner(StringBuilder builder, CDOLockOwner lockOwner, boolean first)
{
if (!first)
{
builder.append("+");
}
- String durableLockingID = lockOwner.getDurableLockingID();
builder.append('[');
+ appendLockOwner(builder, lockOwner);
+ builder.append(']');
+ }
+ public static void appendLockOwner(StringBuilder builder, CDOLockOwner lockOwner)
+ {
+ String durableLockingID = lockOwner.getDurableLockingID();
if (durableLockingID != null)
{
builder.append(durableLockingID);
@@ -147,7 +297,5 @@
builder.append(':');
builder.append(lockOwner.getViewID());
}
-
- builder.append(']');
}
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java
index 6ffdbb4..3f45531 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java
@@ -10,9 +10,13 @@
*/
package org.eclipse.emf.cdo.spi.common.lock;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
@@ -30,43 +34,83 @@
@Deprecated
public static final CDOLockState UNLOCKED = null;
- public void addReadLockOwner(CDOLockOwner lockOwner);
-
- public boolean removeReadLockOwner(CDOLockOwner lockOwner);
-
- public void setWriteLockOwner(CDOLockOwner lockOwner);
-
- public void setWriteOptionOwner(CDOLockOwner lockOwner);
-
/**
- * @since 4.4
+ * @since 4.15
*/
- public boolean removeOwner(CDOLockOwner lockOwner);
+ public CDOLockDelta addOwner(CDOLockOwner owner, LockType type);
/**
* @since 4.15
*/
- public boolean remapOwner(CDOLockOwner oldLockOwner, CDOLockOwner newLockOwner);
+ public CDOLockDelta removeOwner(CDOLockOwner owner, LockType type);
+
+ /**
+ * @since 4.15
+ */
+ public CDOLockDelta[] clearOwner(CDOLockOwner owner);
+
+ /**
+ * @since 4.15
+ */
+ public CDOLockDelta[] remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner);
+
+ /**
+ * @since 4.15
+ */
+ public void remapID(CDOID newID);
+
+ /**
+ * @deprecated As of 4.15 use {@link #addOwner(CDOLockOwner, LockType) addOwner(owner, LockType.READ)}.
+ */
+ @Deprecated
+ public void addReadLockOwner(CDOLockOwner owner);
+
+ /**
+ * @deprecated As of 4.15 use {@link #removeOwner(CDOLockOwner, LockType) removeOwner(owner, LockType.READ)}.
+ */
+ @Deprecated
+ public boolean removeReadLockOwner(CDOLockOwner owner);
+
+ /**
+ * @deprecated As of 4.15 use {@link #addOwner(CDOLockOwner, LockType) addOwner(owner, LockType.WRITE)}
+ * or {@link #removeOwner(CDOLockOwner, LockType) removeOwner(owner, LockType.WRITE)}.
+ */
+ @Deprecated
+ public void setWriteLockOwner(CDOLockOwner owner);
+
+ /**
+ * @deprecated As of 4.15 use {@link #addOwner(CDOLockOwner, LockType) addOwner(owner, LockType.OPTION)}.
+ * or {@link #removeOwner(CDOLockOwner, LockType) removeOwner(owner, LockType.OPTION)}.
+ */
+ @Deprecated
+ public void setWriteOptionOwner(CDOLockOwner owner);
+
+ /**
+ * @since 4.4
+ * @deprecated As of 4.16 use {@link #clearOwner(CDOLockOwner)}.
+ */
+ @Deprecated
+ public boolean removeOwner(CDOLockOwner owner);
/**
* Update the {@link CDOLockOwner lockOwners} of this lock state from the one passed in.
*
* @since 4.5
+ * @deprecated As of 4.15 not supported anymore.
*/
+ @Deprecated
public void updateFrom(CDOLockState source);
/**
* @since 4.2
- * @deprecated As of 4.5 use {@link InternalCDOLockState#updateFrom(CDOLockState)} instead.
- * The lockedObject field cannot be changed because it is used to compute the hash code.
- * Instantiate a new {@link CDOLockState} object if you want to update the lockedObject field.
+ * @deprecated As of 4.5 not supported anymore.
*/
@Deprecated
public void updateFrom(Object object, CDOLockState source);
/**
* @since 4.2
- * @deprecated As of 4.15 no longer used.
+ * @deprecated As of 4.15 not supported anymore.
*/
@Deprecated
public void dispose();
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java
index 4dd4d6c..c675aea 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java
@@ -26,7 +26,7 @@
import org.eclipse.emf.cdo.common.lob.CDOLobStore;
import org.eclipse.emf.cdo.common.lob.CDOLobUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
@@ -338,18 +338,10 @@
CDOBranchPoint branchPoint = readCDOBranchPoint();
CDOLockOwner lockOwner = readCDOLockOwner();
- Operation operation = readEnum(Operation.class);
- LockType lockType = readCDOLockType();
+ List<CDOLockDelta> lockDeltas = readCDOLockDeltas();
+ List<CDOLockState> lockStates = readCDOLockStates();
- int n = readXInt();
- List<CDOLockState> lockStates = new ArrayList<>(n);
-
- for (int i = 0; i < n; i++)
- {
- lockStates.add(readCDOLockState());
- }
-
- return CDOLockUtil.createLockChangeInfo(branchPoint, lockOwner, operation, lockType, lockStates);
+ return CDOLockUtil.createLockChangeInfo(branchPoint, lockOwner, lockDeltas, lockStates);
}
@Override
@@ -377,6 +369,11 @@
public CDOLockOwner readCDOLockOwner() throws IOException
{
int session = readXInt();
+ if (session == CDOLockUtil.DURABLE_SESSION_ID - 1)
+ {
+ return null;
+ }
+
int view = readXInt();
String lockAreaID = readString();
return CDOLockUtil.createLockOwner(session, view, lockAreaID);
@@ -411,27 +408,57 @@
for (int i = 0; i < nReadLockOwners; i++)
{
CDOLockOwner lockOwner = readCDOLockOwner();
- lockState.addReadLockOwner(lockOwner);
+ lockState.addOwner(lockOwner, LockType.READ);
}
boolean hasWriteLock = readBoolean();
if (hasWriteLock)
{
CDOLockOwner lockOwner = readCDOLockOwner();
- lockState.setWriteLockOwner(lockOwner);
+ lockState.addOwner(lockOwner, LockType.WRITE);
}
boolean hasWriteOption = readBoolean();
if (hasWriteOption)
{
CDOLockOwner lockOwner = readCDOLockOwner();
- lockState.setWriteOptionOwner(lockOwner);
+ lockState.addOwner(lockOwner, LockType.OPTION);
}
return lockState;
}
@Override
+ public CDOLockDelta readCDOLockDelta() throws IOException
+ {
+ byte opcode = readByte();
+ if (opcode == -1)
+ {
+ return null;
+ }
+
+ Object target;
+ CDOID id = readCDOID();
+
+ if (opcode >= 10)
+ {
+ opcode -= 10;
+ CDOBranch branch = readCDOBranch();
+ target = CDOIDUtil.createIDAndBranch(id, branch);
+ }
+ else
+ {
+ target = id;
+ }
+
+ LockType type = LockType.values()[opcode];
+ CDOLockOwner oldOwner = readCDOLockOwner();
+ CDOLockOwner newOwner = readCDOLockOwner();
+
+ return CDOLockUtil.createLockDelta(target, type, oldOwner, newOwner);
+ }
+
+ @Override
public LockType readCDOLockType() throws IOException
{
return readEnum(LockType.class);
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java
index eaa5ee9..ef42f27 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java
@@ -21,6 +21,7 @@
import org.eclipse.emf.cdo.common.id.CDOIDReference;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
@@ -67,9 +68,8 @@
import java.io.IOException;
import java.text.MessageFormat;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -298,45 +298,14 @@
if (lockChangeInfo.isInvalidateAll())
{
writeBoolean(true);
+ return;
}
- else
- {
- writeBoolean(false);
- writeCDOBranchPoint(lockChangeInfo);
- writeCDOLockOwner(lockChangeInfo.getLockOwner());
- writeEnum(lockChangeInfo.getOperation());
- writeCDOLockType(lockChangeInfo.getLockType());
- Collection<CDOLockState> lockStates = lockChangeInfo.getNewLockStates();
-
- if (filter != null)
- {
- List<CDOLockState> filtered = new ArrayList<>(lockStates.size());
- for (CDOLockState lockState : lockStates)
- {
- Object lockedObject = lockState.getLockedObject();
- CDOID id = CDOLockUtil.getLockedObjectID(lockedObject);
- if (filter.contains(id))
- {
- filtered.add(lockState);
- }
- }
-
- writeXInt(filtered.size());
- for (CDOLockState lockState : filtered)
- {
- writeCDOLockState(lockState);
- }
- }
- else
- {
- writeXInt(lockStates.size());
- for (CDOLockState lockState : lockStates)
- {
- writeCDOLockState(lockState);
- }
- }
- }
+ writeBoolean(false);
+ writeCDOBranchPoint(lockChangeInfo);
+ writeCDOLockOwner(lockChangeInfo.getLockOwner());
+ writeCDOLockDeltas(Arrays.asList(lockChangeInfo.getLockDeltas()), filter == null ? null : delta -> filter.contains(delta.getID()));
+ writeCDOLockStates(Arrays.asList(lockChangeInfo.getLockStates()), filter == null ? null : state -> filter.contains(state.getID()));
}
@Override
@@ -361,9 +330,62 @@
@Override
public void writeCDOLockOwner(CDOLockOwner lockOwner) throws IOException
{
- writeXInt(lockOwner.getSessionID());
- writeXInt(lockOwner.getViewID());
- writeString(lockOwner.getDurableLockingID());
+ if (lockOwner == null)
+ {
+ writeXInt(CDOLockUtil.DURABLE_SESSION_ID - 1);
+ }
+ else
+ {
+ writeXInt(lockOwner.getSessionID());
+ writeXInt(lockOwner.getViewID());
+ writeString(lockOwner.getDurableLockingID());
+ }
+ }
+
+ @Override
+ public void writeCDOLockDelta(CDOLockDelta lockDelta) throws IOException
+ {
+ if (lockDelta == null)
+ {
+ writeByte(-1);
+ return;
+ }
+
+ byte opcode = 0;
+ CDOID id;
+ CDOBranch branch;
+
+ Object target = lockDelta.getTarget();
+ if (target instanceof CDOIDAndBranch)
+ {
+ CDOIDAndBranch idAndBranch = (CDOIDAndBranch)target;
+ id = idAndBranch.getID();
+ branch = idAndBranch.getBranch();
+ opcode += 10;
+ }
+ else if (target instanceof CDOID)
+ {
+ id = (CDOID)target;
+ branch = null;
+ }
+ else
+ {
+ throw new AssertionError("Unexpected type: " + target.getClass().getSimpleName());
+ }
+
+ LockType type = lockDelta.getType();
+ opcode += type.ordinal();
+
+ writeByte(opcode);
+ writeCDOID(id);
+
+ if (opcode >= 10)
+ {
+ writeCDOBranch(branch);
+ }
+
+ writeCDOLockOwner(lockDelta.getOldOwner());
+ writeCDOLockOwner(lockDelta.getNewOwner());
}
@Override
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java
index 5646f16..d12845c 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java
@@ -125,18 +125,18 @@
*/
public interface RevisionLoader
{
- /**
- * @deprecated As of 4.15 use {@link RevisionLoader3#loadRevisions(List, CDOBranchPoint, int, int, boolean)}.
- */
- @Deprecated
- public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth);
-
public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk);
/**
* @since 4.3
*/
public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime, CDORevisionHandler handler);
+
+ /**
+ * @deprecated As of 4.15 use {@link RevisionLoader3#loadRevisions(List, CDOBranchPoint, int, int, boolean)}.
+ */
+ @Deprecated
+ public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth);
}
/**
diff --git a/plugins/org.eclipse.emf.cdo.dawn/src/org/eclipse/emf/cdo/dawn/notifications/BasicDawnLockingHandler.java b/plugins/org.eclipse.emf.cdo.dawn/src/org/eclipse/emf/cdo/dawn/notifications/BasicDawnLockingHandler.java
index 24ef218..daff4cf 100644
--- a/plugins/org.eclipse.emf.cdo.dawn/src/org/eclipse/emf/cdo/dawn/notifications/BasicDawnLockingHandler.java
+++ b/plugins/org.eclipse.emf.cdo.dawn/src/org/eclipse/emf/cdo/dawn/notifications/BasicDawnLockingHandler.java
@@ -12,15 +12,13 @@
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.dawn.editors.IDawnEditor;
import org.eclipse.emf.cdo.dawn.editors.IDawnEditorSupport;
import org.eclipse.emf.cdo.dawn.spi.DawnState;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewLocksChangedEvent;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -38,31 +36,12 @@
@Override
public void handleLocksChangedEvent(CDOViewLocksChangedEvent event)
{
- CDOViewLocksChangedEvent lockEvent = event;
-
- Collection<CDOLockState> lockStates = lockEvent.getNewLockStates();
-
Map<Object, DawnState> changedObjects = new HashMap<>();
+ CDOView view = editor.getDawnEditorSupport().getView();
- for (CDOLockState state : lockStates)
+ for (CDOLockDelta lockDelta : event.getLockDeltas())
{
- Object lockedObject = state.getLockedObject();
-
- CDOView view = editor.getDawnEditorSupport().getView();
- CDOID id;
- if (lockedObject instanceof CDOID)
- {
- id = (CDOID)lockedObject;
- }
- else if (lockedObject instanceof CDOIDAndBranch)
- {
- id = ((CDOIDAndBranch)lockedObject).getID();
- }
- else
- {
- throw new RuntimeException("Unexpected object type: " + lockedObject);
- }
-
+ CDOID id = lockDelta.getID();
if (id != null)
{
CDOObject object = view.getObject(id);
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/RecoveringCDOSessionImpl.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/RecoveringCDOSessionImpl.java
index 7ec5861..2949938 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/RecoveringCDOSessionImpl.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/RecoveringCDOSessionImpl.java
@@ -23,6 +23,7 @@
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.internal.cdo.view.CDOViewImpl;
+import org.eclipse.emf.internal.cdo.view.CDOViewImpl.DurableLockProcessor;
import org.eclipse.net4j.Net4jUtil;
import org.eclipse.net4j.connector.IConnector;
@@ -320,6 +321,8 @@
private final String durableLockingID;
+ private final DurableLockProcessor durableLockProcessor;
+
private final CDOBranchPoint branchPoint;
private final CDOViewImpl.OptionsImpl options;
@@ -333,10 +336,12 @@
if (durableLockingID == null)
{
branchPoint = CDOBranchUtil.copyBranchPoint(view);
+ durableLockProcessor = null;
}
else
{
branchPoint = null;
+ durableLockProcessor = ((CDOViewImpl)view).createDurableLockProcessor();
}
options = (CDOViewImpl.OptionsImpl)view.options();
@@ -347,7 +352,8 @@
{
if (durableLockingID != null)
{
- sessionProtocol.openView(viewID, !transaction, durableLockingID);
+ sessionProtocol.openView(viewID, !transaction, durableLockingID, durableLockProcessor);
+ durableLockProcessor.run();
}
else
{
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java
index 1d993af..c91f576 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java
@@ -28,6 +28,7 @@
import org.eclipse.emf.cdo.common.lob.CDOLob;
import org.eclipse.emf.cdo.common.lob.CDOLobInfo;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevision;
@@ -86,6 +87,7 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
@@ -197,20 +199,6 @@
}
@Override
- @Deprecated
- public void deleteBranch(int branchID)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void renameBranch(int branchID, String newName)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void renameBranch(int branchID, String oldName, String newName)
{
send(new RenameBranchRequest(this, branchID, oldName, newName));
@@ -246,13 +234,6 @@
return send(new LoadChunkRequest(this, revision, feature, accessIndex, fetchIndex, fromIndex, toIndex));
}
- @Deprecated
- @Override
- public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth)
- {
- throw new UnsupportedOperationException();
- }
-
@Override
public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth,
boolean prefetchLockStates)
@@ -286,9 +267,9 @@
}
@Override
- public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID)
+ public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID, BiConsumer<CDOID, LockGrade> consumer)
{
- return send(new OpenViewRequest(this, viewID, readOnly, durableLockingID));
+ return send(new OpenViewRequest(this, viewID, readOnly, durableLockingID, consumer));
}
@Override
@@ -330,14 +311,6 @@
}
@Override
- @Deprecated
- public LockObjectsResult lockObjects(List<InternalCDORevision> revisions, int viewID, CDOBranch viewedBranch, LockType lockType, long timeout)
- throws InterruptedException
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public LockObjectsResult lockObjects2(List<CDORevisionKey> revisionKeys, int viewID, CDOBranch viewedBranch, LockType lockType, boolean recursive,
long timeout) throws InterruptedException
{
@@ -480,28 +453,12 @@
}
@Override
- @Deprecated
- public CommitTransactionResult commitTransaction(int transactionID, String comment, boolean releaseLocks, CDOIDProvider idProvider, CDOCommitData commitData,
- Collection<CDOLob<?>> lobs, OMMonitor monitor)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public CommitTransactionResult commitTransaction(InternalCDOCommitContext context, OMMonitor monitor)
{
return send(new CommitTransactionRequest(this, context), monitor);
}
@Override
- @Deprecated
- public CommitTransactionResult commitDelegation(CDOBranch branch, String userID, String comment, CDOCommitData commitData,
- Map<CDOID, EClass> detachedObjectTypes, Collection<CDOLob<?>> lobs, OMMonitor monitor)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public CommitTransactionResult commitDelegation(InternalCDOCommitContext context, OMMonitor monitor)
{
return send(new CommitDelegationRequest(this, context), monitor);
@@ -574,14 +531,6 @@
}
@Override
- @Deprecated
- public Set<CDOID> loadMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
- CDORevisionAvailabilityInfo sourceBaseInfo)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public MergeDataResult loadMergeData2(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo)
{
@@ -589,14 +538,7 @@
}
@Override
- @Deprecated
- public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids, int depth)
+ public List<CDOLockState> getLockStates2(int branchID, Collection<CDOID> ids, int depth)
{
return send(new LockStateRequest(this, branchID, ids, depth));
}
@@ -626,13 +568,6 @@
}
@Override
- @Deprecated
- public void requestChangeCredentials()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void requestChangeServerPassword(AtomicReference<char[]> receiver)
{
send(new ChangeCredentialsRequest(this, receiver), new Monitor());
@@ -764,4 +699,85 @@
REVISION_LOADING.stop(request);
}
}
+
+ @Override
+ @Deprecated
+ public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void deleteBranch(int branchID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void renameBranch(int branchID, String newName)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public LockObjectsResult lockObjects(List<InternalCDORevision> revisions, int viewID, CDOBranch viewedBranch, LockType lockType, long timeout)
+ throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CommitTransactionResult commitTransaction(int transactionID, String comment, boolean releaseLocks, CDOIDProvider idProvider, CDOCommitData commitData,
+ Collection<CDOLob<?>> lobs, OMMonitor monitor)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CommitTransactionResult commitDelegation(CDOBranch branch, String userID, String comment, CDOCommitData commitData,
+ Map<CDOID, EClass> detachedObjectTypes, Collection<CDOLob<?>> lobs, OMMonitor monitor)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public Set<CDOID> loadMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
+ CDORevisionAvailabilityInfo sourceBaseInfo)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids, int depth)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void requestChangeCredentials()
+ {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java
index fde0664..f838249 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java
@@ -27,6 +27,7 @@
import org.eclipse.emf.cdo.common.lob.CDOBlob;
import org.eclipse.emf.cdo.common.lob.CDOClob;
import org.eclipse.emf.cdo.common.lob.CDOLob;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
@@ -160,6 +161,7 @@
out.writeXInt(commitNumber);
out.writeString(commitComment);
CDOBranchUtil.writeBranchPointOrNull(out, commitMergeSource);
+ out.writeXLong(transaction.options().getOptimisticLockingTimeout());
out.writeXInt(locksOnNewObjects.size());
out.writeXInt(idsToUnlock.size());
@@ -310,7 +312,7 @@
result = confirmingResult(in);
confirmingMappingNewObjects(in, result);
- confirmingNewLockStates(in, result);
+ confirmingLocks(in, result);
confirmingNewPermissions(in, result);
confirmingNewCommitData(in, result);
return result;
@@ -382,17 +384,13 @@
}
}
- protected void confirmingNewLockStates(CDODataInput in, CommitTransactionResult result) throws IOException
+ protected void confirmingLocks(CDODataInput in, CommitTransactionResult result) throws IOException
{
- int n = in.readXInt();
- CDOLockState[] newLockStates = new CDOLockState[n];
+ List<CDOLockDelta> lockDeltas = in.readCDOLockDeltas();
+ result.setLockDeltas(lockDeltas);
- for (int i = 0; i < n; i++)
- {
- newLockStates[i] = in.readCDOLockState();
- }
-
- result.setNewLockStates(newLockStates);
+ List<CDOLockState> lockStates = in.readCDOLockStates();
+ result.setLockStates(lockStates);
}
protected void confirmingNewPermissions(CDODataInput in, CommitTransactionResult result) throws IOException
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionsRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionsRequest.java
index 4a32922..66fffac 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionsRequest.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionsRequest.java
@@ -212,18 +212,7 @@
if (in.readBoolean())
{
- List<CDOLockState> lockStates = new ArrayList<>();
-
- for (;;)
- {
- CDOLockState lockState = in.readCDOLockState();
- if (lockState == null)
- {
- break;
- }
-
- lockStates.add(lockState);
- }
+ List<CDOLockState> lockStates = in.readCDOLockStates();
int noLockStateKeys = in.readXInt();
if (noLockStateKeys != 0)
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockAreaRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockAreaRequest.java
index 7295e87..dd9bba7 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockAreaRequest.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockAreaRequest.java
@@ -22,9 +22,9 @@
*/
public class LockAreaRequest extends CDOClientRequest<String>
{
- private CDOView view;
+ private final CDOView view;
- private boolean create;
+ private final boolean create;
public LockAreaRequest(CDOClientProtocol protocol, CDOView view, boolean create)
{
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockObjectsRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockObjectsRequest.java
index 1c96f19..1e63eef 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockObjectsRequest.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockObjectsRequest.java
@@ -11,6 +11,7 @@
*/
package org.eclipse.emf.cdo.internal.net4j.protocol;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
@@ -78,6 +79,7 @@
boolean succesful = in.readBoolean();
boolean timeout = in.readBoolean();
boolean waitForUpdate = in.readBoolean();
+ long timestamp = in.readXLong();
long requiredTimestamp = in.readXLong();
int nStaleRevisions = in.readXInt();
@@ -87,16 +89,10 @@
staleRevisions[i] = in.readCDORevisionKey();
}
- long timestamp = in.readXLong();
+ List<CDOLockDelta> lockDeltas = in.readCDOLockDeltas();
+ List<CDOLockState> lockStates = in.readCDOLockStates();
- int n = in.readXInt();
- CDOLockState[] newLockStates = new CDOLockState[n];
- for (int i = 0; i < n; i++)
- {
- newLockStates[i] = in.readCDOLockState();
- }
-
- return new LockObjectsResult(succesful, timeout, waitForUpdate, requiredTimestamp, staleRevisions, newLockStates, timestamp);
+ return new LockObjectsResult(succesful, timeout, waitForUpdate, requiredTimestamp, staleRevisions, lockDeltas, lockStates, timestamp);
}
@Override
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockStateRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockStateRequest.java
index 4485e65..68d7c2f 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockStateRequest.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LockStateRequest.java
@@ -19,11 +19,12 @@
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Collection;
+import java.util.List;
/**
* @author Caspar De Groot
*/
-public class LockStateRequest extends CDOClientRequest<CDOLockState[]>
+public class LockStateRequest extends CDOClientRequest<List<CDOLockState>>
{
private int branchID;
@@ -61,16 +62,9 @@
}
@Override
- protected CDOLockState[] confirming(CDODataInput in) throws IOException
+ protected List<CDOLockState> confirming(CDODataInput in) throws IOException
{
- int n = in.readXInt();
- CDOLockState[] lockStates = new CDOLockState[n];
- for (int i = 0; i < n; i++)
- {
- lockStates[i] = in.readCDOLockState();
- }
-
- return lockStates;
+ return in.readCDOLockStates();
}
@Override
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/OpenViewRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/OpenViewRequest.java
index fc6d940..5b4263b 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/OpenViewRequest.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/OpenViewRequest.java
@@ -11,25 +11,31 @@
package org.eclipse.emf.cdo.internal.net4j.protocol;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import java.io.IOException;
+import java.util.function.BiConsumer;
/**
* @author Eike Stepper
*/
public class OpenViewRequest extends CDOClientRequest<CDOBranchPoint>
{
- private int viewID;
+ private final int viewID;
- private boolean readOnly;
+ private final boolean readOnly;
- private CDOBranchPoint branchPoint;
+ private final CDOBranchPoint branchPoint;
- private String durableLockingID;
+ private final String durableLockingID;
+
+ private final BiConsumer<CDOID, LockGrade> consumer;
public OpenViewRequest(CDOClientProtocol protocol, int viewID, boolean readOnly, CDOBranchPoint branchPoint)
{
@@ -37,14 +43,18 @@
this.viewID = viewID;
this.readOnly = readOnly;
this.branchPoint = branchPoint;
+ durableLockingID = null;
+ consumer = null;
}
- public OpenViewRequest(CDOClientProtocol protocol, int viewID, boolean readOnly, String durableLockingID)
+ public OpenViewRequest(CDOClientProtocol protocol, int viewID, boolean readOnly, String durableLockingID, BiConsumer<CDOID, LockGrade> consumer)
{
super(protocol, CDOProtocolConstants.SIGNAL_OPEN_VIEW);
this.viewID = viewID;
this.readOnly = readOnly;
this.durableLockingID = durableLockingID;
+ this.consumer = consumer;
+ branchPoint = null;
}
@Override
@@ -62,6 +72,7 @@
{
out.writeBoolean(false);
out.writeString(durableLockingID);
+ out.writeBoolean(consumer != null);
}
}
@@ -70,7 +81,24 @@
{
if (in.readBoolean())
{
- return in.readCDOBranchPoint();
+ CDOBranchPoint branchPoint = in.readCDOBranchPoint();
+
+ if (consumer != null)
+ {
+ for (;;)
+ {
+ CDOID id = in.readCDOID();
+ if (CDOIDUtil.isNull(id))
+ {
+ break;
+ }
+
+ LockGrade lockGrade = in.readEnum(LockGrade.class);
+ consumer.accept(id, lockGrade);
+ }
+ }
+
+ return branchPoint;
}
if (durableLockingID != null)
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java
index 470ff72..ab65b23 100644
--- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java
+++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java
@@ -11,6 +11,7 @@
package org.eclipse.emf.cdo.internal.net4j.protocol;
import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
@@ -22,6 +23,7 @@
import java.io.IOException;
import java.util.Collection;
+import java.util.List;
/**
* @author Simon McDuff
@@ -76,15 +78,10 @@
protected UnlockObjectsResult confirming(CDODataInput in) throws IOException
{
long timestamp = in.readXLong();
- int n = in.readXInt();
- CDOLockState[] newLockStates = new CDOLockState[n];
+ List<CDOLockDelta> lockDeltas = in.readCDOLockDeltas();
+ List<CDOLockState> lockStates = in.readCDOLockStates();
- for (int i = 0; i < n; i++)
- {
- newLockStates[i] = in.readCDOLockState();
- }
-
- return new UnlockObjectsResult(newLockStates, timestamp);
+ return new UnlockObjectsResult(timestamp, lockDeltas, lockStates);
}
@Override
diff --git a/plugins/org.eclipse.emf.cdo.server.admin/src/org/eclipse/emf/cdo/server/internal/admin/CDOAdminServerRepository.java b/plugins/org.eclipse.emf.cdo.server.admin/src/org/eclipse/emf/cdo/server/internal/admin/CDOAdminServerRepository.java
index a8ac5a7..b920790 100644
--- a/plugins/org.eclipse.emf.cdo.server.admin/src/org/eclipse/emf/cdo/server/internal/admin/CDOAdminServerRepository.java
+++ b/plugins/org.eclipse.emf.cdo.server.admin/src/org/eclipse/emf/cdo/server/internal/admin/CDOAdminServerRepository.java
@@ -190,13 +190,6 @@
}
@Override
- @Deprecated
- public boolean isSupportingEcore()
- {
- return delegate.isSupportingEcore();
- }
-
- @Override
public boolean isSerializingCommits()
{
return delegate.isSerializingCommits();
@@ -245,12 +238,6 @@
return AdapterUtil.adapt(this, adapter, false);
}
- @Override
- public String toString()
- {
- return delegate.toString();
- }
-
public void write(ExtendedDataOutputStream out) throws IOException
{
out.writeString(getName());
@@ -297,4 +284,17 @@
synchronizer.removeListener(delegateSynchronizerListener);
}
}
+
+ @Override
+ public String toString()
+ {
+ return delegate.toString();
+ }
+
+ @Override
+ @Deprecated
+ public boolean isSupportingEcore()
+ {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
index 2ce3641..3a81f22 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
@@ -107,7 +107,6 @@
import java.io.Reader;
import java.io.Writer;
import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@@ -167,35 +166,6 @@
}
@Override
- @Deprecated
- public org.eclipse.emf.cdo.server.db.IPreparedStatementCache getStatementCache()
- {
- return new org.eclipse.emf.cdo.server.db.IPreparedStatementCache()
- {
- @Override
- public void setConnection(Connection connection)
- {
- // Do nothing
- }
-
- @Override
- public IDBPreparedStatement getPreparedStatement(String sql, ReuseProbability reuseProbability)
- {
- org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability converted = //
- org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability.values()[reuseProbability.ordinal()];
-
- return connection.prepareStatement(sql, converted);
- }
-
- @Override
- public void releasePreparedStatement(PreparedStatement ps)
- {
- DBUtil.close(ps);
- }
- };
- }
-
- @Override
public DBStoreChunkReader createChunkReader(InternalCDORevision revision, EStructuralFeature feature)
{
return new DBStoreChunkReader(this, revision, feature);
@@ -211,24 +181,6 @@
return dbAdapter.openSchemaTransaction(database, connection);
}
- /**
- * Returns an iterator that iterates over all objects in the store and makes their CDOIDs available for processing.
- * This method is supposed to be called very infrequently, for example during the recovery from a crash.
- *
- * @since 2.0
- * @deprecated Not used by the framework anymore.
- */
- @Deprecated
- public CloseableIterator<CDOID> readObjectIDs()
- {
- if (TRACER.isEnabled())
- {
- TRACER.trace("Selecting object IDs"); //$NON-NLS-1$
- }
-
- return getStore().getMappingStrategy().readObjectIDs(this);
- }
-
public CDOClassifierRef readObjectType(CDOID id)
{
if (TRACER.isEnabled())
@@ -546,13 +498,6 @@
}
}
- @Deprecated
- @Override
- protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor)
- {
- writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, null, monitor);
- }
-
@Override
protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, CDOBranchPoint mergeSource,
OMMonitor monitor)
@@ -1215,20 +1160,6 @@
}
@Override
- @Deprecated
- public void deleteBranch(int branchID)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void renameBranch(int branchID, String newName)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void renameBranch(int branchID, String oldName, String newName)
{
checkBranchingSupport();
@@ -1709,13 +1640,6 @@
}
@Override
- public void unlock(String durableLockingID)
- {
- DurableLockingManager manager = getStore().getDurableLockingManager();
- manager.unlock(this, durableLockingID);
- }
-
- @Override
public List<CDOID> readUnitRoots()
{
UnitMappingTable unitMappingTable = getStore().getUnitMappingTable();
@@ -1828,4 +1752,45 @@
return super.cancel();
}
}
+
+ @Override
+ @Deprecated
+ public org.eclipse.emf.cdo.server.db.IPreparedStatementCache getStatementCache()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ public CloseableIterator<CDOID> readObjectIDs()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ @Override
+ protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void deleteBranch(int branchID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void renameBranch(int branchID, String newName)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(String durableLockingID)
+ {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
index 22ebaf5..c7fc602 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
@@ -31,6 +31,7 @@
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBConnection;
import org.eclipse.net4j.db.IDBDatabase;
import org.eclipse.net4j.db.IDBDatabase.RunnableWithSchema;
import org.eclipse.net4j.db.IDBPreparedStatement;
@@ -134,7 +135,8 @@
}
}
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlInsertLockArea, ReuseProbability.LOW);
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(sqlInsertLockArea, ReuseProbability.LOW);
try
{
@@ -167,7 +169,8 @@
private void insertLocks(DBStoreAccessor accessor, String durableLockingID, Map<CDOID, LockGrade> locks)
{
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlInsertLock, ReuseProbability.MEDIUM);
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(sqlInsertLock, ReuseProbability.MEDIUM);
try
{
@@ -196,7 +199,8 @@
public LockArea getLockArea(DBStoreAccessor accessor, String durableLockingID) throws LockAreaNotFoundException
{
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlSelectLockArea, ReuseProbability.MEDIUM);
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(sqlSelectLockArea, ReuseProbability.MEDIUM);
ResultSet resultSet = null;
try
@@ -229,6 +233,7 @@
public void getLockAreas(DBStoreAccessor accessor, String userIDPrefix, Handler handler)
{
+ IDBConnection connection = accessor.getDBConnection();
IDBPreparedStatement stmt = null;
ResultSet resultSet = null;
@@ -236,11 +241,11 @@
{
if (userIDPrefix.length() == 0)
{
- stmt = accessor.getDBConnection().prepareStatement(sqlSelectAllLockAreas, ReuseProbability.MEDIUM);
+ stmt = connection.prepareStatement(sqlSelectAllLockAreas, ReuseProbability.MEDIUM);
}
else
{
- stmt = accessor.getDBConnection().prepareStatement(sqlSelectLockAreas, ReuseProbability.MEDIUM);
+ stmt = connection.prepareStatement(sqlSelectLockAreas, ReuseProbability.MEDIUM);
stmt.setString(1, userIDPrefix + "%");
}
@@ -275,7 +280,8 @@
{
unlockWithoutCommit(accessor, durableLockingID);
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlDeleteLockArea, ReuseProbability.LOW);
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(sqlDeleteLockArea, ReuseProbability.LOW);
try
{
@@ -309,18 +315,21 @@
public void unlock(DBStoreAccessor accessor, String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock)
{
- changeLocks(accessor, durableLockingID, type, objectsToUnlock, false);
- }
-
- public void unlock(DBStoreAccessor accessor, String durableLockingID)
- {
- unlockWithoutCommit(accessor, durableLockingID);
- commit(accessor);
+ if (objectsToUnlock == null)
+ {
+ unlockWithoutCommit(accessor, durableLockingID);
+ commit(accessor);
+ }
+ else
+ {
+ changeLocks(accessor, durableLockingID, type, objectsToUnlock, false);
+ }
}
private void unlockWithoutCommit(DBStoreAccessor accessor, String durableLockingID)
{
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlDeleteLocks, ReuseProbability.MEDIUM);
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(sqlDeleteLocks, ReuseProbability.MEDIUM);
try
{
@@ -432,7 +441,8 @@
private Map<CDOID, LockGrade> getLockMap(DBStoreAccessor accessor, String durableLockingID)
{
- IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlSelectLocks, ReuseProbability.MEDIUM);
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmt = connection.prepareStatement(sqlSelectLocks, ReuseProbability.MEDIUM);
ResultSet resultSet = null;
try
@@ -469,20 +479,22 @@
return;
}
- String sql = on ? sqlInsertLock : sqlDeleteLock;
+ String sqlInsertOrDelete = on ? sqlInsertLock : sqlDeleteLock;
- IDBPreparedStatement stmtSelect = accessor.getDBConnection().prepareStatement(sqlSelectLock, ReuseProbability.MEDIUM);
- IDBPreparedStatement stmtInsertOrDelete = accessor.getDBConnection().prepareStatement(sql, ReuseProbability.MEDIUM);
- IDBPreparedStatement stmtUpdate = accessor.getDBConnection().prepareStatement(sqlUpdateLock, ReuseProbability.MEDIUM);
+ IDBConnection connection = accessor.getDBConnection();
+ IDBPreparedStatement stmtSelect = connection.prepareStatement(sqlSelectLock, ReuseProbability.MEDIUM);
+ IDBPreparedStatement stmtInsertOrDelete = connection.prepareStatement(sqlInsertOrDelete, ReuseProbability.MEDIUM);
+ IDBPreparedStatement stmtUpdate = connection.prepareStatement(sqlUpdateLock, ReuseProbability.MEDIUM);
ResultSet resultSet = null;
+ InternalLockManager lockManager = accessor.getStore().getRepository().getLockingManager();
+
try
{
stmtSelect.setString(1, durableLockingID);
stmtInsertOrDelete.setString(1, durableLockingID);
stmtUpdate.setString(2, durableLockingID);
- InternalLockManager lockManager = accessor.getStore().getRepository().getLockingManager();
for (Object key : keys)
{
CDOID id = lockManager.getLockKeyID(key);
@@ -515,7 +527,7 @@
}
}
- accessor.getDBConnection().commit();
+ connection.commit();
}
catch (SQLException e)
{
@@ -574,7 +586,8 @@
{
try
{
- accessor.getDBConnection().commit();
+ IDBConnection connection = accessor.getDBConnection();
+ connection.commit();
}
catch (SQLException ex)
{
diff --git a/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeFileHandle.java b/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeFileHandle.java
index e5f56fd..b19e062 100644
--- a/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeFileHandle.java
+++ b/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeFileHandle.java
@@ -23,6 +23,7 @@
import org.eclipse.emf.cdo.common.id.CDOIDReference;
import org.eclipse.emf.cdo.common.lob.CDOLobStore;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
@@ -499,6 +500,12 @@
}
@Override
+ public CDOLockDelta readCDOLockDelta() throws IOException
+ {
+ return in().readCDOLockDelta();
+ }
+
+ @Override
public CDOLockState readCDOLockState() throws IOException
{
return in().readCDOLockState();
@@ -822,6 +829,12 @@
}
@Override
+ public void writeCDOLockDelta(CDOLockDelta lockDelta) throws IOException
+ {
+ out().writeCDOLockDelta(lockDelta);
+ }
+
+ @Override
public void writeCDOLockOwner(CDOLockOwner lockOwner) throws IOException
{
out().writeCDOLockOwner(lockOwner);
diff --git a/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeStoreReader.java b/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeStoreReader.java
index f1e68ca..f3e9451 100644
--- a/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeStoreReader.java
+++ b/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/LissomeStoreReader.java
@@ -486,9 +486,9 @@
}
@Override
+ @Deprecated
public void unlock(String durableLockingID)
{
- // Implemented in LissomeStoreWriter
throw new UnsupportedOperationException();
}
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java
index 210055a..56d4056 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java
@@ -19,8 +19,8 @@
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDReference;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
-import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
import org.eclipse.emf.cdo.common.model.EMFUtil;
import org.eclipse.emf.cdo.common.model.EMFUtil.ExtResourceSet;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
@@ -31,7 +31,6 @@
import org.eclipse.emf.cdo.common.security.CDOPermission;
import org.eclipse.emf.cdo.etypes.EtypesPackage;
import org.eclipse.emf.cdo.server.IPermissionManager;
-import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
@@ -43,7 +42,6 @@
import org.eclipse.emf.cdo.spi.server.InternalView;
import org.eclipse.net4j.util.WrappedException;
-import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.emf.ecore.EClass;
@@ -121,6 +119,7 @@
int commitNumber = in.readXInt();
String commitComment = in.readString();
CDOBranchPoint commitMergeSource = CDOBranchUtil.readBranchPointOrNull(in);
+ long optimisticLockingTimeout = in.readXLong();
CDOLockState[] locksOnNewObjects = new CDOLockState[in.readXInt()];
CDOID[] idsToUnlock = new CDOID[in.readXInt()];
@@ -256,6 +255,7 @@
commitContext.setCommitNumber(commitNumber);
commitContext.setLastUpdateTime(lastUpdateTime);
+ commitContext.setOptimisticLockingTimeout(optimisticLockingTimeout);
commitContext.setClearResourcePathCache(clearResourcePathCache);
commitContext.setUsingEcore(usingEcore);
commitContext.setUsingEtypes(usingEtypes);
@@ -309,7 +309,7 @@
{
respondingResult(out);
respondingMappingNewObjects(out);
- respondingNewLockStates(out);
+ respondingLocks(out);
respondingNewPermissions(out);
respondingNewCommitData(out);
}
@@ -369,22 +369,13 @@
out.writeCDOID(CDOID.NULL);
}
- protected void respondingNewLockStates(CDODataOutput out) throws Exception
+ protected void respondingLocks(CDODataOutput out) throws Exception
{
- List<LockState<Object, IView>> newLockStates = commitContext.getPostCommmitLockStates();
- if (newLockStates != null)
- {
- out.writeXInt(newLockStates.size());
- for (LockState<Object, IView> lockState : newLockStates)
- {
- CDOLockState cdoLockState = CDOLockUtil.convertLockState(lockState);
- out.writeCDOLockState(cdoLockState);
- }
- }
- else
- {
- out.writeXInt(0);
- }
+ List<CDOLockDelta> lockDeltas = commitContext.getLockDeltas();
+ out.writeCDOLockDeltas(lockDeltas, null);
+
+ List<CDOLockState> lockStates = commitContext.getLockStates();
+ out.writeCDOLockStates(lockStates, null);
}
protected void respondingNewPermissions(CDODataOutput out) throws Exception
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockObjectsIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockObjectsIndication.java
index b86169b..75a3bcb 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockObjectsIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockObjectsIndication.java
@@ -12,7 +12,6 @@
*/
package org.eclipse.emf.cdo.server.internal.net4j.protocol;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
@@ -72,6 +71,7 @@
out.writeBoolean(result.isSuccessful());
out.writeBoolean(result.isTimedOut());
out.writeBoolean(result.isWaitForUpdate());
+ out.writeXLong(result.getTimestamp());
out.writeXLong(result.getRequiredTimestamp());
CDORevisionKey[] staleRevisions = result.getStaleRevisions();
@@ -81,13 +81,7 @@
out.writeCDORevisionKey(revKey);
}
- out.writeXLong(result.getTimestamp());
-
- CDOLockState[] newLockStates = result.getNewLockStates();
- out.writeXInt(newLockStates.length);
- for (CDOLockState lockState : newLockStates)
- {
- out.writeCDOLockState(lockState);
- }
+ out.writeCDOLockDeltas(result.getLockDeltas(), null);
+ out.writeCDOLockStates(result.getLockStates(), null);
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockStateIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockStateIndication.java
index 35c71e8..92ec733 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockStateIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LockStateIndication.java
@@ -22,6 +22,7 @@
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
import org.eclipse.emf.cdo.common.revision.CDORevisionProvider;
+import org.eclipse.emf.cdo.internal.server.LockingManager.LockStateCollector;
import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.ManagedRevisionProvider;
@@ -34,7 +35,6 @@
import org.eclipse.emf.ecore.EStructuralFeature;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collection;
/**
@@ -42,10 +42,16 @@
*/
public class LockStateIndication extends CDOServerReadIndication
{
- private Collection<CDOLockState> existingLockStates;
+ private final LockStateCollector existingLockStates = new LockStateCollector();
+
+ private InternalLockManager lockManager;
+
+ private CDOBranch branch;
private int prefetchDepth = CDOLockState.DEPTH_NONE;
+ private CDORevisionProvider revisionProvider;
+
public LockStateIndication(CDOServerProtocol protocol)
{
super(protocol, CDOProtocolConstants.SIGNAL_LOCK_STATE);
@@ -56,13 +62,10 @@
{
InternalRepository repository = getRepository();
CDOBranchManager branchManager = repository.getBranchManager();
- InternalLockManager lockManager = repository.getLockingManager();
+ lockManager = repository.getLockingManager();
int branchID = in.readXInt();
- CDOBranch branch = branchManager.getBranch(branchID);
-
- existingLockStates = new ArrayList<>();
- CDORevisionProvider revisionProvider;
+ branch = branchManager.getBranch(branchID);
int idsLength = in.readXInt();
if (idsLength < 0)
@@ -73,32 +76,26 @@
CDORevisionManager revisionManager = repository.getRevisionManager();
revisionProvider = new ManagedRevisionProvider(revisionManager, branch.getHead());
}
- else
- {
- revisionProvider = null;
- }
if (idsLength == 0)
{
- Collection<LockState<Object, IView>> lockStates = lockManager.getLockStates();
- for (LockState<Object, IView> lockState : lockStates)
- {
- existingLockStates.add(CDOLockUtil.convertLockState(lockState));
- }
+ lockManager.getLockStates(existingLockStates);
}
else
{
+ int depth = prefetchDepth >= CDOLockState.DEPTH_NONE ? prefetchDepth : Integer.MAX_VALUE;
+
for (int i = 0; i < idsLength; i++)
{
CDOID id = in.readCDOID();
- prefetchLockStates(lockManager, prefetchDepth >= CDOLockState.DEPTH_NONE ? prefetchDepth : Integer.MAX_VALUE, id, branch, revisionProvider);
+ prefetchLockStates(depth, id);
}
}
}
- private void prefetchLockStates(InternalLockManager lockManager, int depth, CDOID id, CDOBranch branch, CDORevisionProvider revisionProvider)
+ private void prefetchLockStates(int depth, CDOID id)
{
- addLockState(lockManager, id, branch);
+ addLockState(id);
if (depth > CDOLockState.DEPTH_NONE)
{
@@ -121,7 +118,7 @@
Object value = revision.getValue(reference);
if (value instanceof CDOID)
{
- prefetchLockStates(lockManager, depth, (CDOID)value, branch, revisionProvider);
+ prefetchLockStates(depth, (CDOID)value);
}
else if (value instanceof Collection<?>)
{
@@ -133,7 +130,7 @@
// instanceof CDOID. (See bug 339313.)
if (e instanceof CDOID)
{
- prefetchLockStates(lockManager, depth, (CDOID)e, branch, revisionProvider);
+ prefetchLockStates(depth, (CDOID)e);
}
}
}
@@ -143,7 +140,7 @@
}
}
- private void addLockState(InternalLockManager lockManager, CDOID id, CDOBranch branch)
+ private void addLockState(CDOID id)
{
Object key = lockManager.getLockKey(id, branch);
@@ -157,10 +154,6 @@
@Override
protected void responding(CDODataOutput out) throws IOException
{
- out.writeXInt(existingLockStates.size());
- for (CDOLockState lockState : existingLockStates)
- {
- out.writeCDOLockState(lockState);
- }
+ out.writeCDOLockStates(existingLockStates, null);
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/OpenViewIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/OpenViewIndication.java
index e2d8cb8..71e225a 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/OpenViewIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/OpenViewIndication.java
@@ -11,24 +11,35 @@
package org.eclipse.emf.cdo.server.internal.net4j.protocol;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.emf.cdo.spi.server.InternalSession;
-import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.io.IORuntimeException;
import java.io.IOException;
+import java.util.function.BiConsumer;
/**
* @author Eike Stepper
*/
public class OpenViewIndication extends CDOServerReadIndication
{
- private InternalView newView;
+ private int viewID;
- private String message;
+ private boolean readOnly;
+
+ private CDOBranchPoint branchPoint;
+
+ private String durableLockingID;
+
+ private boolean respondLockGrades;
public OpenViewIndication(CDOServerProtocol protocol)
{
@@ -38,14 +49,29 @@
@Override
protected void indicating(CDODataInput in) throws IOException
{
- InternalSession session = getSession();
-
- int viewID = in.readXInt();
- boolean readOnly = in.readBoolean();
+ viewID = in.readXInt();
+ readOnly = in.readBoolean();
if (in.readBoolean())
{
- CDOBranchPoint branchPoint = in.readCDOBranchPoint();
+ branchPoint = in.readCDOBranchPoint();
+ }
+ else
+ {
+ durableLockingID = in.readString();
+ respondLockGrades = in.readBoolean();
+ }
+ }
+
+ @Override
+ protected void responding(CDODataOutput out) throws IOException
+ {
+ InternalSession session = getSession();
+
+ if (branchPoint != null)
+ {
+ IView newView;
+
if (readOnly)
{
newView = session.openView(viewID, branchPoint);
@@ -54,15 +80,58 @@
{
newView = session.openTransaction(viewID, branchPoint);
}
+
+ respondNewView(out, newView, null);
}
else
{
InternalLockManager lockManager = getRepository().getLockingManager();
+ String message = null;
+
+ BiConsumer<CDOID, LockGrade> lockConsumer = respondLockGrades ? (id, lockGrade) -> {
+ try
+ {
+ out.writeCDOID(id);
+ out.writeEnum(lockGrade);
+ }
+ catch (IOException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ } : null;
try
{
- String durableLockingID = in.readString();
- newView = (InternalView)lockManager.openView(session, viewID, readOnly, durableLockingID);
+ try
+ {
+ lockManager.openView(session, viewID, readOnly, durableLockingID, newView -> {
+ try
+ {
+ respondNewView(out, newView, null);
+ }
+ catch (IOException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ }, lockConsumer);
+ }
+ catch (IORuntimeException ex)
+ {
+ Throwable cause = ex.getCause();
+ if (cause instanceof IOException)
+ {
+ throw (IOException)cause;
+ }
+
+ throw ex;
+ }
+
+ if (respondLockGrades)
+ {
+ out.writeCDOID(null);
+ }
+
+ return;
}
catch (LockAreaNotFoundException ex)
{
@@ -72,11 +141,12 @@
{
message = ex.getMessage();
}
+
+ respondNewView(out, null, message);
}
}
- @Override
- protected void responding(CDODataOutput out) throws IOException
+ private static void respondNewView(CDODataOutput out, IView newView, String message) throws IOException
{
if (newView != null)
{
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockDelegationIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockDelegationIndication.java
index 2e008cd..4a138d7 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockDelegationIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockDelegationIndication.java
@@ -13,10 +13,13 @@
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.emf.cdo.spi.server.InternalSession;
import org.eclipse.emf.cdo.spi.server.InternalView;
+import org.eclipse.net4j.util.concurrent.Holder;
+
import java.io.IOException;
/**
@@ -56,9 +59,11 @@
@Override
protected InternalView getView(int viewID)
{
+ Holder<IView> viewHolder = new Holder<>();
+
InternalLockManager lockManager = getRepository().getLockingManager();
InternalSession session = getSession();
- view = (InternalView)lockManager.openView(session, InternalSession.TEMP_VIEW_ID, true, lockAreaID);
- return view;
+ lockManager.openView(session, InternalSession.TEMP_VIEW_ID, true, lockAreaID, viewHolder, null);
+ return view = (InternalView)viewHolder.get();
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockObjectsIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockObjectsIndication.java
index 70e26a8..7852a38 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockObjectsIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/UnlockObjectsIndication.java
@@ -12,7 +12,6 @@
package org.eclipse.emf.cdo.server.internal.net4j.protocol;
import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
@@ -76,11 +75,7 @@
protected void responding(CDODataOutput out) throws IOException
{
out.writeXLong(result.getTimestamp());
- CDOLockState[] newLockStates = result.getNewLockStates();
- out.writeXInt(newLockStates.length);
- for (CDOLockState state : newLockStates)
- {
- out.writeCDOLockState(state);
- }
+ out.writeCDOLockDeltas(result.getLockDeltas(), null);
+ out.writeCDOLockStates(result.getLockStates(), null);
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters
index 2d7a2c5..a7a965d 100644
--- a/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters
+++ b/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters
@@ -87,19 +87,6 @@
</filter>
</resource>
<resource path="src/org/eclipse/emf/cdo/internal/server/Repository.java" type="org.eclipse.emf.cdo.internal.server.Repository">
- <filter id="574619656">
- <message_arguments>
- <message_argument value="CDOReplicationInfo"/>
- <message_argument value="Repository"/>
- </message_arguments>
- </filter>
- <filter id="574660632">
- <message_arguments>
- <message_argument value="InternalRepository"/>
- <message_argument value="CDOCommonRepository"/>
- <message_argument value="Repository"/>
- </message_arguments>
- </filter>
<filter id="574664731">
<message_arguments>
<message_argument value="org.eclipse.emf.cdo.internal.server.Repository.replicateRaw(CDODataOutput, int, long)"/>
@@ -457,6 +444,72 @@
<message_argument value="InternalLockManager"/>
</message_arguments>
</filter>
+ <filter id="574619656">
+ <message_arguments>
+ <message_argument value="IRWOLockManager<OBJECT, CONTEXT>"/>
+ <message_argument value="InternalLockManager"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="lock(IRWLockManager.LockType, IView, Collection<? extends Object>, long)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="lock(IRWLockManager.LockType, IView, Object, long)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="lock(IView, Collection<? extends Object>, IRWLockManager.LockType, int, long, IRWOLockManager.LockDeltaHandler<Object,IView>, Consumer<RWOLockManager.LockState<Object,IView>>)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="lock2(IRWLockManager.LockType, IView, Collection<? extends Object>, long)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="lock3(IView, Collection<? extends Object>, IRWLockManager.LockType, int, long, IRWOLockManager.LockDeltaHandler<Object,IView>, Consumer<RWOLockManager.LockState<Object,IView>>)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="unlock(IRWLockManager.LockType, IView, Collection<? extends Object>)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="unlock(IView)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="unlock(IView, Collection<? extends Object>, IRWLockManager.LockType, int, IRWOLockManager.LockDeltaHandler<Object,IView>, Consumer<RWOLockManager.LockState<Object,IView>>)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="unlock2(IRWLockManager.LockType, IView, Collection<? extends Object>)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="unlock2(IView)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="unlock2(IView, Collection<? extends Object>)"/>
+ </message_arguments>
+ </filter>
+ <filter id="1211105284">
+ <message_arguments>
+ <message_argument value="unlock3(IView, Collection<? extends Object>, IRWLockManager.LockType, int, IRWOLockManager.LockDeltaHandler<Object,IView>, Consumer<RWOLockManager.LockState<Object,IView>>)"/>
+ </message_arguments>
+ </filter>
</resource>
<resource path="src/org/eclipse/emf/cdo/spi/server/InternalRepository.java" type="org.eclipse.emf.cdo.spi.server.InternalRepository">
<filter id="571473929">
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java
index d9e9f37..013d318 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java
@@ -15,7 +15,9 @@
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocol.CommitData;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.server.IStoreAccessor;
import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
@@ -33,6 +35,7 @@
import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
/**
* @author Eike Stepper
@@ -150,13 +153,6 @@
}
@Override
- @Deprecated
- public boolean isAutoReleaseLocksEnabled()
- {
- return getDelegate().isAutoReleaseLocksEnabled();
- }
-
- @Override
public CDOLockState[] getLocksOnNewObjects()
{
return getDelegate().getLocksOnNewObjects();
@@ -169,6 +165,18 @@
}
@Override
+ public List<CDOLockDelta> getLockDeltas()
+ {
+ return getDelegate().getLockDeltas();
+ }
+
+ @Override
+ public List<CDOLockState> getLockStates()
+ {
+ return getDelegate().getLockStates();
+ }
+
+ @Override
public CDOBranchVersion[] getDetachedObjectVersions()
{
return getDelegate().getDetachedObjectVersions();
@@ -187,12 +195,6 @@
}
@Override
- public List<LockState<Object, IView>> getPostCommmitLockStates()
- {
- return getDelegate().getPostCommmitLockStates();
- }
-
- @Override
public byte getRollbackReason()
{
return getDelegate().getRollbackReason();
@@ -209,4 +211,79 @@
{
return getDelegate().getXRefs();
}
+
+ @Override
+ public CDOBranchPoint getCommitMergeSource()
+ {
+ return getDelegate().getCommitMergeSource();
+ }
+
+ @Override
+ public byte getSecurityImpact()
+ {
+ return getDelegate().getSecurityImpact();
+ }
+
+ @Override
+ public Map<CDOID, InternalCDORevision> getOldRevisions()
+ {
+ return getDelegate().getOldRevisions();
+ }
+
+ @Override
+ public Map<CDOID, InternalCDORevision> getNewRevisions()
+ {
+ return getDelegate().getNewRevisions();
+ }
+
+ @Override
+ public CommitData getOriginalCommmitData()
+ {
+ return getDelegate().getOriginalCommmitData();
+ }
+
+ @Override
+ public <T> T getData(Object key)
+ {
+ return getDelegate().getData(key);
+ }
+
+ @Override
+ public <T> T setData(Object key, T data)
+ {
+ return getDelegate().setData(key, data);
+ }
+
+ @Override
+ public void modify(Consumer<ModificationContext> modifier)
+ {
+ getDelegate().modify(modifier);
+ }
+
+ @Override
+ @Deprecated
+ public boolean isAutoReleaseLocksEnabled()
+ {
+ return getDelegate().isAutoReleaseLocksEnabled();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> getPostCommmitLockStates()
+ {
+ return getDelegate().getPostCommmitLockStates();
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ @SuppressWarnings("unused")
+ private static final class InternalCompletenessChecker extends DelegatingCommitContext
+ {
+ @Override
+ protected CommitContext getDelegate()
+ {
+ return null;
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java
index 256987f..531f26c 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java
@@ -17,7 +17,10 @@
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
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.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.common.revision.CDORevision;
@@ -33,6 +36,7 @@
import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.server.StoreThreadLocal;
import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
import org.eclipse.emf.cdo.spi.common.revision.ManagedRevisionProvider;
import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
@@ -41,11 +45,12 @@
import org.eclipse.emf.cdo.spi.server.InternalView;
import org.eclipse.net4j.util.CheckUtil;
-import org.eclipse.net4j.util.ImplementationError;
import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.collection.ConcurrentArray;
+import org.eclipse.net4j.util.concurrent.Access;
import org.eclipse.net4j.util.concurrent.RWOLockManager;
+import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import org.eclipse.net4j.util.container.ContainerEventAdapter;
import org.eclipse.net4j.util.container.IContainer;
import org.eclipse.net4j.util.event.EventUtil;
@@ -63,10 +68,13 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
/**
* @author Simon McDuff
@@ -100,7 +108,7 @@
String durableLockingID = view.getDurableLockingID();
if (durableLockingID == null)
{
- repository.unlock((InternalView)view, null, null, false);
+ repository.unlock((InternalView)view);
}
else
{
@@ -128,6 +136,12 @@
}
};
+ private BiFunction<CDOID, CDOBranch, Object> lockKeyCreator;
+
+ private Function<Object, CDOID> lockIDExtractor;
+
+ private Function<Object, CDOBranch> lockBranchExtractor;
+
public LockingManager()
{
}
@@ -145,131 +159,68 @@
}
@Override
- public synchronized Object getLockEntryObject(Object key)
- {
- LockState<Object, IView> lockState = getObjectToLocksMap().get(key);
- return lockState == null ? null : lockState.getLockedObject();
- }
-
- @Override
public Object getLockKey(CDOID id, CDOBranch branch)
{
- if (repository.isSupportingBranches())
- {
- return CDOIDUtil.createIDAndBranch(id, branch);
- }
-
- return id;
+ return lockKeyCreator.apply(id, branch);
}
@Override
- public synchronized Map<CDOID, LockGrade> getLocks(final IView view)
+ public CDOID getLockKeyID(Object key)
+ {
+ return lockIDExtractor.apply(key);
+ }
+
+ @Override
+ public CDOBranch getLockKeyBranch(Object key)
+ {
+ return lockBranchExtractor.apply(key);
+ }
+
+ /**
+ * @category Read Access
+ */
+ @Override
+ public Map<CDOID, LockGrade> getLocks(final IView view)
{
final Map<CDOID, LockGrade> result = CDOIDUtil.createMap();
- for (LockState<Object, IView> lockState : getObjectToLocksMap().values())
+ try (Access access = read.access())
{
- LockGrade grade = LockGrade.NONE;
- if (lockState.hasLock(LockType.READ, view, false))
+ for (LockState<Object, IView> lockState : getObjectToLocksMap().values())
{
- grade = grade.getUpdated(LockType.READ, true);
- }
+ LockGrade grade = LockGrade.NONE;
+ if (lockState.hasLock(LockType.READ, view, false))
+ {
+ grade = grade.getUpdated(LockType.READ, true);
+ }
- if (lockState.hasLock(LockType.WRITE, view, false))
- {
- grade = grade.getUpdated(LockType.WRITE, true);
- }
+ if (lockState.hasLock(LockType.WRITE, view, false))
+ {
+ grade = grade.getUpdated(LockType.WRITE, true);
+ }
- if (lockState.hasLock(LockType.OPTION, view, false))
- {
- grade = grade.getUpdated(LockType.OPTION, true);
- }
+ if (lockState.hasLock(LockType.OPTION, view, false))
+ {
+ grade = grade.getUpdated(LockType.OPTION, true);
+ }
- if (grade != LockGrade.NONE)
- {
- CDOID id = getLockKeyID(lockState.getLockedObject());
- result.put(id, grade);
+ if (grade != LockGrade.NONE)
+ {
+ CDOID id = getLockKeyID(lockState.getLockedObject());
+ result.put(id, grade);
+ }
}
}
return result;
}
- @Override
- @Deprecated
- public void lock(boolean explicit, LockType type, IView view, Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException
- {
- lock2(explicit, type, view, objectsToLock, false, timeout);
- }
-
- @Override
- public List<LockState<Object, IView>> lock2(boolean explicit, LockType type, IView view, Collection<? extends Object> objectsToLock, boolean recursive,
- long timeout) throws InterruptedException
- {
- String durableLockingID = null;
- DurableLocking accessor = null;
-
- if (explicit)
- {
- durableLockingID = view.getDurableLockingID();
- if (durableLockingID != null)
- {
- accessor = getDurableLocking();
- }
- }
-
- long startTime = timeout == WAIT ? 0L : currentTimeMillis();
-
- List<LockState<Object, IView>> newLockStates;
- synchronized (this)
- {
- if (recursive)
- {
- objectsToLock = createContentSet(objectsToLock, view);
- }
-
- // Adjust timeout for delay we may have incurred on entering this synchronized block
- if (timeout != WAIT)
- {
- timeout -= currentTimeMillis() - startTime;
- }
-
- newLockStates = super.lock2(type, view, objectsToLock, timeout);
- }
-
- if (accessor != null)
- {
- accessor.lock(durableLockingID, type, objectsToLock);
- }
-
- return newLockStates;
- }
-
- @Override
- public void lock(LockType type, IView context, Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException
- {
- lock2(false, type, context, objectsToLock, false, timeout);
- }
-
- @Override
- public void lock(LockType type, IView context, Object objectToLock, long timeout) throws InterruptedException
- {
- Collection<Object> objectsToLock = new LinkedHashSet<>();
- objectsToLock.add(objectToLock);
- lock2(false, type, context, objectsToLock, false, timeout);
- }
-
- @Override
- public List<LockState<Object, IView>> lock2(LockType type, IView context, Collection<? extends Object> objectsToLock, long timeout)
- throws InterruptedException
- {
- return lock2(false, type, context, objectsToLock, false, timeout);
- }
-
+ /**
+ * Synchronized by the caller.
+ */
private Set<? extends Object> createContentSet(Collection<? extends Object> objectsToLock, IView view)
{
CDOBranch branch = view.getBranch();
- boolean branching = repository.isSupportingBranches();
CDORevisionManager revisionManager = view.getSession().getRepository().getRevisionManager();
CDORevisionProvider revisionProvider = new ManagedRevisionProvider(revisionManager, branch.getHead());
@@ -280,111 +231,109 @@
{
contents.add(objectToLock);
- CDOID id = branching ? ((CDOIDAndBranch)objectToLock).getID() : (CDOID)objectToLock;
+ CDOID id = getLockKeyID(objectToLock);
CDORevision revision = revisionProvider.getRevision(id);
- createContentSet(branch, branching, revisionProvider, revision, contents);
+ createContentSet(branch, revisionProvider, revision, contents);
}
return contents;
}
- private void createContentSet(CDOBranch branch, boolean branching, CDORevisionProvider revisionProvider, CDORevision revision, Set<Object> contents)
+ /**
+ * Synchronized by the caller.
+ */
+ private void createContentSet(CDOBranch branch, CDORevisionProvider revisionProvider, CDORevision revision, Set<Object> contents)
{
for (CDORevision child : CDORevisionUtil.getChildRevisions(revision, revisionProvider))
{
CDOID childID = child.getID();
- contents.add(branching ? CDOIDUtil.createIDAndBranch(childID, branch) : childID);
- createContentSet(branch, branching, revisionProvider, child, contents);
+ Object key = getLockKey(childID, branch);
+ contents.add(key);
+ createContentSet(branch, revisionProvider, child, contents);
}
}
+ /**
+ * @category Write Access
+ */
@Override
- @Deprecated
- public synchronized void unlock(boolean explicit, LockType type, IView view, Collection<? extends Object> objectsToUnlock)
+ public long lock(IView view, Collection<? extends Object> objects, LockType lockType, int count, long timeout, //
+ boolean recursive, boolean explicit, //
+ LockDeltaHandler<Object, IView> deltaHandler, Consumer<LockState<Object, IView>> stateHandler) //
+ throws InterruptedException, TimeoutRuntimeException
{
- unlock2(explicit, type, view, objectsToUnlock, false);
- }
-
- @Override
- public synchronized List<LockState<Object, IView>> unlock2(boolean explicit, LockType type, IView view, Collection<? extends Object> objects,
- boolean recursive)
- {
- List<LockState<Object, IView>> newLockStates;
- synchronized (this)
+ long modCount;
+ try (Access access = write.access())
{
if (recursive)
{
objects = createContentSet(objects, view);
}
- newLockStates = super.unlock2(type, view, objects);
+ modCount = super.lock(view, objects, lockType, count, timeout, deltaHandler, stateHandler);
}
if (explicit)
{
- String durableLockingID = view.getDurableLockingID();
- if (durableLockingID != null)
+ try
{
- DurableLocking accessor = getDurableLocking();
- accessor.unlock(durableLockingID, type, objects);
+ lockDurably(view, objects, lockType);
+ }
+ catch (Exception | Error ex)
+ {
+ super.unlock(view, objects, lockType, count, null, null);
+ throw ex;
}
}
- return newLockStates;
+ return modCount;
}
- @Override
- @Deprecated
- public synchronized void unlock(boolean explicit, IView view)
+ private void lockDurably(IView view, Collection<? extends Object> objects, LockType lockType)
{
- unlock2(explicit, view);
+ String durableLockingID = view.getDurableLockingID();
+ if (durableLockingID != null)
+ {
+ DurableLocking accessor = getDurableLocking();
+ accessor.lock(durableLockingID, lockType, objects);
+ }
}
+ /**
+ * @category Write Access
+ */
@Override
- public synchronized List<LockState<Object, IView>> unlock2(boolean explicit, IView view)
+ public long unlock(IView view, Collection<? extends Object> objects, LockType lockType, int count, //
+ boolean recursive, boolean explicit, //
+ LockDeltaHandler<Object, IView> deltaHandler, Consumer<LockState<Object, IView>> stateHandler)
{
+ long modCount;
+ try (Access access = write.access())
+ {
+ if (recursive)
+ {
+ objects = createContentSet(objects, view);
+ }
+
+ modCount = super.unlock(view, objects, lockType, count, deltaHandler, stateHandler);
+ }
+
if (explicit)
{
- String durableLockingID = view.getDurableLockingID();
- if (durableLockingID != null)
- {
- DurableLocking accessor = getDurableLocking();
- accessor.unlock(durableLockingID);
- }
+ unlockDurably(view, objects, lockType);
}
- return super.unlock2(view);
+ return modCount;
}
- @Override
- public synchronized List<RWOLockManager.LockState<Object, IView>> unlock2(IView context)
+ private void unlockDurably(IView view, Collection<? extends Object> objects, LockType lockType)
{
- return unlock2(false, context);
- }
-
- @Override
- public synchronized List<RWOLockManager.LockState<Object, IView>> unlock2(IView context, Collection<? extends Object> objectsToUnlock)
- {
- // If no locktype is specified, use the LockType.WRITE
- return unlock2(false, LockType.WRITE, context, objectsToUnlock, false);
- }
-
- @Override
- public synchronized List<RWOLockManager.LockState<Object, IView>> unlock2(LockType type, IView context, Collection<? extends Object> objectsToUnlock)
- {
- return unlock2(false, type, context, objectsToUnlock, false);
- }
-
- @Override
- public synchronized void unlock(IView context)
- {
- unlock2(context);
- }
-
- @Override
- public synchronized void unlock(LockType type, IView context, Collection<? extends Object> objectsToUnlock)
- {
- unlock2(type, context, objectsToUnlock);
+ String durableLockingID = view.getDurableLockingID();
+ if (durableLockingID != null)
+ {
+ DurableLocking accessor = getDurableLocking();
+ accessor.unlock(durableLockingID, lockType, objects);
+ }
}
@Override
@@ -456,7 +405,8 @@
}
@Override
- public IView openView(ISession session, int viewID, boolean readOnly, final String durableLockingID)
+ public void openView(ISession session, int viewID, boolean readOnly, String durableLockingID, Consumer<IView> viewConsumer,
+ BiConsumer<CDOID, LockGrade> lockConsumer)
{
synchronized (openDurableViews)
{
@@ -509,7 +459,17 @@
});
openDurableViews.put(durableLockingID, view);
- return view;
+ viewConsumer.accept(view);
+
+ if (lockConsumer != null)
+ {
+ for (Map.Entry<CDOID, LockGrade> entry : area.getLocks().entrySet())
+ {
+ CDOID id = entry.getKey();
+ LockGrade lockGrade = entry.getValue();
+ lockConsumer.accept(id, lockGrade);
+ }
+ }
}
}
@@ -517,9 +477,25 @@
protected void doActivate() throws Exception
{
super.doActivate();
+
+ if (repository.isSupportingBranches())
+ {
+ lockKeyCreator = (id, branch) -> CDOIDUtil.createIDAndBranch(id, branch);
+ lockIDExtractor = key -> ((CDOIDAndBranch)key).getID();
+ lockBranchExtractor = key -> ((CDOIDAndBranch)key).getBranch();
+ }
+ else
+ {
+ InternalCDOBranch mainBranch = repository.getBranchManager().getMainBranch();
+
+ lockKeyCreator = (id, branch) -> id;
+ lockIDExtractor = key -> (CDOID)key;
+ lockBranchExtractor = key -> mainBranch;
+ }
+
loadLocks();
- InternalSessionManager sessionManager = getRepository().getSessionManager();
+ InternalSessionManager sessionManager = repository.getSessionManager();
sessionManager.addListener(sessionManagerListener);
for (ISession session : sessionManager.getSessions())
@@ -531,7 +507,7 @@
@Override
protected void doDeactivate() throws Exception
{
- ISessionManager sessionManager = getRepository().getSessionManager();
+ ISessionManager sessionManager = repository.getSessionManager();
sessionManager.removeListener(sessionManagerListener);
for (ISession session : sessionManager.getSessions())
@@ -604,18 +580,6 @@
}
@Override
- public CDOID getLockKeyID(Object key)
- {
- CDOID id = CDOLockUtil.getLockedObjectID(key);
- if (id == null)
- {
- throw new ImplementationError("Unexpected lock object: " + key);
- }
-
- return id;
- }
-
- @Override
public void addDurableViewHandler(DurableViewHandler handler)
{
durableViewHandlers.add(handler);
@@ -634,6 +598,66 @@
}
/**
+ * @category Read Access
+ */
+ @Override
+ public LockGrade getLockGrade(Object key)
+ {
+ try (Access access = read.access())
+ {
+ LockState<Object, IView> lockState = getObjectToLocksMap().get(key);
+ LockGrade grade = LockGrade.NONE;
+ if (lockState != null)
+ {
+ for (LockType type : ALL_LOCK_TYPES)
+ {
+ if (lockState.hasLock(type))
+ {
+ grade = grade.getUpdated(type, true);
+ }
+ }
+ }
+
+ return grade;
+ }
+ }
+
+ private LockArea getLockAreaNoEx(String durableLockingID)
+ {
+ try
+ {
+ return getLockArea(durableLockingID);
+ }
+ catch (LockAreaNotFoundException e)
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public void updateLockArea(LockArea lockArea)
+ {
+ String durableLockingID = lockArea.getDurableLockingID();
+ DurableLocking2 accessor = getDurableLocking2();
+
+ if (lockArea.isMissing())
+ {
+ LockArea localLockArea = getLockAreaNoEx(durableLockingID);
+ if (localLockArea != null && localLockArea.getLocks().size() > 0)
+ {
+ accessor.deleteLockArea(durableLockingID);
+ DurableView deletedView = durableViews.remove(durableLockingID);
+ CheckUtil.checkNull(deletedView, "deletedView");
+ }
+ }
+ else
+ {
+ accessor.updateLockArea(lockArea);
+ new DurableLockLoader().handleLockArea(lockArea);
+ }
+ }
+
+ /**
* @author Eike Stepper
*/
private final class DurableView extends PlatformObject implements IView, CDOCommonView.Options
@@ -855,7 +879,7 @@
IView view = getView(durableLockingID);
if (view != null)
{
- unlock2(view);
+ LockingManager.super.unlock(view, null, null, ALL_LOCKS, null, null);
}
else
{
@@ -888,9 +912,9 @@
try
{
- lock(LockType.READ, view, readLocks, 1000L);
- lock(LockType.WRITE, view, writeLocks, 1000L);
- lock(LockType.OPTION, view, writeOptions, 1000L);
+ LockingManager.super.lock(view, readLocks, LockType.READ, 1, 1000L, null, null);
+ LockingManager.super.lock(view, writeLocks, LockType.WRITE, 1, 1000L, null, null);
+ LockingManager.super.lock(view, writeOptions, LockType.OPTION, 1, 1000L, null, null);
}
catch (InterruptedException ex)
{
@@ -901,57 +925,196 @@
}
}
- @Override
- public synchronized LockGrade getLockGrade(Object key)
+ /**
+ * @author Eike Stepper
+ */
+ public static final class LockDeltaCollector extends ArrayList<CDOLockDelta> implements LockDeltaHandler<Object, IView>
{
- LockState<Object, IView> lockState = getObjectToLocksMap().get(key);
- LockGrade grade = LockGrade.NONE;
- if (lockState != null)
+ private static final long serialVersionUID = 1L;
+
+ private Operation operation;
+
+ public LockDeltaCollector(Operation operation)
{
- for (LockType type : ALL_LOCK_TYPES)
+ this.operation = operation;
+ }
+
+ public LockDeltaCollector()
+ {
+ }
+
+ public Operation getOperation()
+ {
+ return operation;
+ }
+
+ public void setOperation(Operation operation)
+ {
+ this.operation = operation;
+ }
+
+ @Override
+ public void handleLockDelta(IView context, Object object, LockType lockType, int oldCount, int newCount)
+ {
+ switch (operation)
{
- if (lockState.hasLock(type))
+ case LOCK:
+ if (oldCount == 0 && newCount > 0)
{
- grade = grade.getUpdated(type, true);
+ CDOLockOwner lockOwner = context.getLockOwner();
+ CDOLockDelta lockDelta = CDOLockUtil.createLockDelta(object, lockType, null, lockOwner);
+ add(lockDelta);
}
+ break;
+
+ case UNLOCK:
+ if (oldCount > 0 && newCount == 0)
+ {
+ CDOLockOwner lockOwner = context.getLockOwner();
+ CDOLockDelta lockDelta = CDOLockUtil.createLockDelta(object, lockType, lockOwner, null);
+ add(lockDelta);
+ }
+ break;
+
+ default:
+ throw new AssertionError();
}
}
-
- return grade;
}
- private LockArea getLockAreaNoEx(String durableLockingID)
+ /**
+ * @author Eike Stepper
+ */
+ public static final class LockStateCollector extends ArrayList<CDOLockState> implements Consumer<LockState<Object, IView>>
{
- try
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void accept(LockState<Object, IView> serverLockState)
{
- return getLockArea(durableLockingID);
+ CDOLockState commonLockState = CDOLockUtil.convertLockState(serverLockState);
+ add(commonLockState);
}
- catch (LockAreaNotFoundException e)
+ }
+
+ /**
+ * @deprecated
+ * @category Read Access
+ */
+ @Deprecated
+ @Override
+ public Object getLockEntryObject(Object key)
+ {
+ try (Access access = read.access())
{
- return null;
+ LockState<Object, IView> lockState = getObjectToLocksMap().get(key);
+ return lockState == null ? null : lockState.getLockedObject();
}
}
@Override
- public void updateLockArea(LockArea lockArea)
+ @Deprecated
+ public void lock(boolean explicit, LockType type, IView view, Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException
{
- String durableLockingID = lockArea.getDurableLockingID();
- DurableLocking2 accessor = getDurableLocking2();
+ throw new UnsupportedOperationException();
+ }
- if (lockArea.isMissing())
- {
- LockArea localLockArea = getLockAreaNoEx(durableLockingID);
- if (localLockArea != null && localLockArea.getLocks().size() > 0)
- {
- accessor.deleteLockArea(durableLockingID);
- DurableView deletedView = durableViews.remove(durableLockingID);
- CheckUtil.checkNull(deletedView, "deletedView");
- }
- }
- else
- {
- accessor.updateLockArea(lockArea);
- new DurableLockLoader().handleLockArea(lockArea);
- }
+ @Override
+ @Deprecated
+ public void unlock(boolean explicit, LockType type, IView view, Collection<? extends Object> objectsToUnlock)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(boolean explicit, IView view)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void lock(LockType type, IView view, Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void lock(LockType type, IView view, Object objectToLock, long timeout) throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> lock2(LockType type, IView view, Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> lock2(boolean explicit, LockType type, IView view, Collection<? extends Object> objectsToLock, boolean recursive,
+ long timeout) throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(IView view)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(LockType type, IView view, Collection<? extends Object> objectsToUnlock)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> unlock2(boolean explicit, LockType type, IView view, Collection<? extends Object> objects, boolean recursive)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> unlock2(boolean explicit, IView view)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<RWOLockManager.LockState<Object, IView>> unlock2(IView view)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<RWOLockManager.LockState<Object, IView>> unlock2(IView view, Collection<? extends Object> objectsToUnlock)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<RWOLockManager.LockState<Object, IView>> unlock2(LockType type, IView view, Collection<? extends Object> objectsToUnlock)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public IView openView(ISession session, int viewID, boolean readOnly, String durableLockingID)
+ {
+ throw new UnsupportedOperationException();
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
index 2dcb2d3..06d3613 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
@@ -15,7 +15,6 @@
*/
package org.eclipse.emf.cdo.internal.server;
-import org.eclipse.emf.cdo.common.CDOCommonView;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
import org.eclipse.emf.cdo.common.branch.CDOBranchManager.CDOTagList;
@@ -33,6 +32,7 @@
import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
@@ -57,6 +57,8 @@
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.etypes.EtypesPackage;
import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
+import org.eclipse.emf.cdo.internal.server.LockingManager.LockDeltaCollector;
+import org.eclipse.emf.cdo.internal.server.LockingManager.LockStateCollector;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
import org.eclipse.emf.cdo.server.IQueryHandler;
import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
@@ -118,7 +120,7 @@
import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+import org.eclipse.net4j.util.concurrent.IRWOLockManager;
import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import org.eclipse.net4j.util.container.Container;
import org.eclipse.net4j.util.container.IManagedContainer;
@@ -146,7 +148,6 @@
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -171,7 +172,9 @@
*/
public class Repository extends Container<Object> implements InternalRepository
{
- public static final CDOLockState[] NO_LOCK_STATES = new CDOLockState[0];
+ private static final List<CDOLockDelta> NO_LOCK_DELTAS = Collections.emptyList();
+
+ private static final List<CDOLockState> NO_LOCK_STATES = Collections.emptyList();
private static final int UNCHUNKED = CDORevision.UNCHUNKED;
@@ -421,13 +424,6 @@
}
@Override
- @Deprecated
- public boolean isSupportingEcore()
- {
- return true;
- }
-
- @Override
public boolean isSerializingCommits()
{
return serializingCommits;
@@ -613,20 +609,6 @@
}
@Override
- @Deprecated
- public void deleteBranch(int branchID)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void renameBranch(int branchID, String newName)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void renameBranch(int branchID, String oldName, String newName)
{
if (!isSupportingBranches())
@@ -763,13 +745,6 @@
}
@Override
- @Deprecated
- public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth,
boolean prefetchLockStates)
{
@@ -1383,17 +1358,6 @@
this.commitManager = commitManager;
}
- /**
- * @since 2.0
- * @deprecated
- */
- @Override
- @Deprecated
- public InternalLockManager getLockManager()
- {
- return getLockingManager();
- }
-
@Override
public InternalLockManager getLockingManager()
{
@@ -1535,45 +1499,11 @@
}
@Override
- @Deprecated
- public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo)
- {
- sendCommitNotification(sender, commitInfo, true);
- }
-
- @Override
- @Deprecated
- public CDOCommitInfoHandler[] getCommitInfoHandlers()
- {
- return commitInfoManager.getCommitInfoHandlers();
- }
-
- @Override
- @Deprecated
- public void addCommitInfoHandler(CDOCommitInfoHandler handler)
- {
- commitInfoManager.addCommitInfoHandler(handler);
- }
-
- @Override
- @Deprecated
- public void removeCommitInfoHandler(CDOCommitInfoHandler handler)
- {
- commitInfoManager.removeCommitInfoHandler(handler);
- }
-
- @Override
- @Deprecated
- public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo, boolean clearResourcePathCache)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void sendCommitNotification(CommitNotificationInfo info)
{
CDOCommitInfo commitInfo = info.getCommitInfo();
boolean isFailureCommitInfo = commitInfo.getBranch() == null;
+
if (isFailureCommitInfo || !commitInfo.isEmpty() || info.getLockChangeInfo() != null)
{
sessionManager.sendCommitNotification(info);
@@ -1994,17 +1924,6 @@
}
@Override
- @Deprecated
- public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
- CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor)
- {
- MergeDataResult result = getMergeData2(targetInfo, sourceInfo, targetBaseInfo, sourceBaseInfo, monitor);
- Set<CDOID> ids = result.getTargetIDs();
- ids.addAll(result.getSourceIDs());
- return ids;
- }
-
- @Override
public MergeDataResult getMergeData2(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor)
{
@@ -2283,81 +2202,6 @@
}
}
- public static List<Object> revisionKeysToObjects(List<CDORevisionKey> revisionKeys, CDOBranch viewedBranch, boolean isSupportingBranches)
- {
- List<Object> lockables = new ArrayList<>();
- for (CDORevisionKey revKey : revisionKeys)
- {
- CDOID id = revKey.getID();
- if (isSupportingBranches)
- {
- lockables.add(CDOIDUtil.createIDAndBranch(id, viewedBranch));
- }
- else
- {
- lockables.add(id);
- }
- }
-
- return lockables;
- }
-
- @Override
- public LockObjectsResult lock(InternalView view, LockType lockType, List<CDORevisionKey> revKeys, boolean recursive, long timeout)
- {
- List<Object> lockables = revisionKeysToObjects(revKeys, view.getBranch(), isSupportingBranches());
- return lock(view, lockType, lockables, revKeys, recursive, timeout);
- }
-
- protected LockObjectsResult lock(InternalView view, LockType type, List<Object> lockables, List<CDORevisionKey> loadedRevs, boolean recursive, long timeout)
- {
- List<LockState<Object, IView>> newLockStates = null;
-
- try
- {
- newLockStates = getLockingManager().lock2(true, type, view, lockables, recursive, timeout);
- }
- catch (TimeoutRuntimeException ex)
- {
- return new LockObjectsResult(false, true, false, 0, new CDORevisionKey[0], NO_LOCK_STATES, getTimeStamp());
- }
- catch (InterruptedException ex)
- {
- throw WrappedException.wrap(ex);
- }
-
- long[] requiredTimestamp = { 0L };
- CDORevisionKey[] staleRevisionsArray = null;
-
- try
- {
- staleRevisionsArray = checkStaleRevisions(view, loadedRevs, lockables, type, requiredTimestamp);
- }
- catch (IllegalArgumentException e)
- {
- getLockingManager().unlock2(true, type, view, lockables, recursive);
- throw e;
- }
-
- // If some of the clients' revisions are stale and it has passiveUpdates disabled,
- // then the locks are useless so we release them and report the stale revisions
- //
- InternalSession session = view.getSession();
- boolean staleNoUpdate = staleRevisionsArray.length > 0 && !session.isPassiveUpdateEnabled();
- if (staleNoUpdate)
- {
- getLockingManager().unlock2(true, type, view, lockables, recursive);
- return new LockObjectsResult(false, false, false, requiredTimestamp[0], staleRevisionsArray, NO_LOCK_STATES, getTimeStamp());
- }
-
- CDOLockState[] array = toCDOLockStates(newLockStates);
- List<CDOLockState> cdoLockStates = Arrays.asList(array);
- sendLockNotifications(view, Operation.LOCK, type, cdoLockStates);
-
- boolean waitForUpdate = staleRevisionsArray.length > 0;
- return new LockObjectsResult(true, false, waitForUpdate, requiredTimestamp[0], staleRevisionsArray, array, getTimeStamp());
- }
-
private CDORevisionKey[] checkStaleRevisions(InternalView view, List<CDORevisionKey> revisionKeys, List<Object> objectsToLock, LockType lockType,
long[] requiredTimestamp)
{
@@ -2392,39 +2236,82 @@
return staleRevisionsArray;
}
- private void sendLockNotifications(IView view, Operation operation, LockType lockType, Collection<? extends CDOLockState> cdoLockStates)
+ private void sendLockNotifications(IView view, List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
CDOBranchPoint branchPoint = view.getBranch().getPoint(getTimeStamp());
CDOLockOwner lockOwner = view.getLockOwner();
- CDOLockChangeInfo lockChangeInfo = CDOLockUtil.createLockChangeInfo(branchPoint, lockOwner, operation, lockType, cdoLockStates);
+ CDOLockChangeInfo lockChangeInfo = CDOLockUtil.createLockChangeInfo(branchPoint, lockOwner, lockDeltas, lockStates);
InternalSession sender = (InternalSession)view.getSession();
sessionManager.sendLockNotification(sender, lockChangeInfo);
}
- // TODO (CD) This doesn't really belong here.. but getting it into CDOLockUtil isn't possible
- public static CDOLockState[] toCDOLockStates(Collection<? extends LockState<Object, IView>> lockStates)
+ @Override
+ public LockObjectsResult lock(InternalView view, LockType lockType, List<CDORevisionKey> revKeys, boolean recursive, long timeout)
{
- CDOLockState[] cdoLockStates = new CDOLockState[lockStates.size()];
- int i = 0;
+ List<Object> lockables = revisionKeysToObjects(revKeys, view.getBranch(), isSupportingBranches());
+ return doLock(view, lockType, lockables, revKeys, recursive, timeout);
+ }
- for (LockState<Object, ? extends CDOCommonView> lockState : lockStates)
+ protected LockObjectsResult doLock(InternalView view, LockType lockType, List<Object> lockables, List<CDORevisionKey> loadedRevs, boolean recursive,
+ long timeout)
+ {
+ LockDeltaCollector lockDeltas = new LockDeltaCollector(Operation.LOCK);
+ LockStateCollector lockStates = new LockStateCollector();
+
+ try
{
- CDOLockState cdoLockState = CDOLockUtil.convertLockState(lockState);
- cdoLockStates[i++] = cdoLockState;
+ lockingManager.lock(view, lockables, lockType, 1, timeout, recursive, true, lockDeltas, lockStates);
+ }
+ catch (TimeoutRuntimeException ex)
+ {
+ return new LockObjectsResult(false, true, false, 0, new CDORevisionKey[0], NO_LOCK_DELTAS, NO_LOCK_STATES, getTimeStamp());
+ }
+ catch (InterruptedException ex)
+ {
+ throw WrappedException.wrap(ex);
}
- return cdoLockStates;
+ long[] requiredTimestamp = { 0L };
+ CDORevisionKey[] staleRevisionsArray = null;
+
+ try
+ {
+ staleRevisionsArray = checkStaleRevisions(view, loadedRevs, lockables, lockType, requiredTimestamp);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ lockingManager.unlock(view, lockables, lockType, 1, recursive, true, null, null);
+ throw ex;
+ }
+
+ // If some of the clients' revisions are stale and it has passiveUpdates disabled,
+ // then the locks are useless so we release them and report the stale revisions
+ //
+ InternalSession session = view.getSession();
+ boolean staleNoUpdate = staleRevisionsArray.length > 0 && !session.isPassiveUpdateEnabled();
+ if (staleNoUpdate)
+ {
+ lockingManager.unlock(view, lockables, lockType, 1, recursive, true, null, null);
+ return new LockObjectsResult(false, false, false, requiredTimestamp[0], staleRevisionsArray, NO_LOCK_DELTAS, NO_LOCK_STATES, getTimeStamp());
+ }
+
+ sendLockNotifications(view, lockDeltas, lockStates);
+
+ boolean waitForUpdate = staleRevisionsArray.length > 0;
+ return new LockObjectsResult(true, false, waitForUpdate, requiredTimestamp[0], staleRevisionsArray, lockDeltas, lockStates, getTimeStamp());
}
@Override
public UnlockObjectsResult unlock(InternalView view, LockType lockType, List<CDOID> objectIDs, boolean recursive)
{
List<Object> unlockables = null;
+
if (objectIDs != null)
{
unlockables = new ArrayList<>(objectIDs.size());
CDOBranch branch = view.getBranch();
+
for (CDOID id : objectIDs)
{
Object key = supportingBranches ? CDOIDUtil.createIDAndBranch(id, branch) : id;
@@ -2432,26 +2319,26 @@
}
}
- return doUnlock(view, lockType, unlockables, recursive);
+ return doUnlock(view, lockType, unlockables, recursive, 1);
}
- protected UnlockObjectsResult doUnlock(InternalView view, LockType lockType, List<Object> unlockables, boolean recursive)
+ @Override
+ public UnlockObjectsResult unlock(InternalView view)
{
- List<LockState<Object, IView>> newLockStates = null;
- if (lockType == null) // Signals an unlock-all operation
- {
- newLockStates = getLockingManager().unlock2(true, view);
- }
- else
- {
- newLockStates = getLockingManager().unlock2(true, lockType, view, unlockables, recursive);
- }
+ return doUnlock(view, null, null, false, IRWOLockManager.ALL_LOCKS);
+ }
+
+ protected UnlockObjectsResult doUnlock(InternalView view, LockType lockType, List<Object> unlockables, boolean recursive, int count)
+ {
+ LockDeltaCollector lockDeltas = new LockDeltaCollector(Operation.UNLOCK);
+ LockStateCollector lockStates = new LockStateCollector();
+
+ lockingManager.unlock(view, unlockables, lockType, count, recursive, true, lockDeltas, lockStates);
+
+ sendLockNotifications(view, lockDeltas, lockStates);
long timestamp = getTimeStamp();
- CDOLockState[] cdoLockStates = toCDOLockStates(newLockStates);
- sendLockNotifications(view, Operation.UNLOCK, lockType, Arrays.asList(cdoLockStates));
-
- return new UnlockObjectsResult(cdoLockStates, timestamp);
+ return new UnlockObjectsResult(timestamp, lockDeltas, lockStates);
}
@Override
@@ -2569,13 +2456,6 @@
}
@Override
- @Deprecated
- public void initSystemPackages()
- {
- initSystemPackages(true);
- }
-
- @Override
public void initSystemPackages(final boolean firstStart)
{
List<InternalCDOPackageUnit> newPackageUnits = new ArrayList<>();
@@ -3040,6 +2920,25 @@
super.doDeactivate();
}
+ public static List<Object> revisionKeysToObjects(List<CDORevisionKey> revisionKeys, CDOBranch viewedBranch, boolean isSupportingBranches)
+ {
+ List<Object> lockables = new ArrayList<>();
+ for (CDORevisionKey revKey : revisionKeys)
+ {
+ CDOID id = revKey.getID();
+ if (isSupportingBranches)
+ {
+ lockables.add(CDOIDUtil.createIDAndBranch(id, viewedBranch));
+ }
+ else
+ {
+ lockables.add(id);
+ }
+ }
+
+ return lockables;
+ }
+
public static Repository get(String uuid)
{
synchronized (REPOSITORIES)
@@ -3101,9 +3000,9 @@
setCommitManager(createCommitManager());
}
- if (getLockManager() == null)
+ if (getLockingManager() == null)
{
- setLockingManager(createLockManager());
+ setLockingManager(createLockingManager());
}
if (getUnitManager() == null)
@@ -3159,15 +3058,94 @@
return new UnitManager(this);
}
- @Deprecated
- protected InternalLockManager createLockManager()
- {
- return createLockingManager();
- }
-
public LockingManager createLockingManager()
{
return new LockingManager();
}
}
+
+ @Override
+ @Deprecated
+ public boolean isSupportingEcore()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void deleteBranch(int branchID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void renameBranch(int branchID, String newName)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public InternalLockManager getLockManager()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CDOCommitInfoHandler[] getCommitInfoHandlers()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void addCommitInfoHandler(CDOCommitInfoHandler handler)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void removeCommitInfoHandler(CDOCommitInfoHandler handler)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo, boolean clearResourcePathCache)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
+ CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void initSystemPackages()
+ {
+ throw new UnsupportedOperationException();
+ }
}
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 2ae3076..d70388a 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
@@ -195,13 +195,6 @@
}
@Override
- @Deprecated
- public boolean isInvalidationRunnerActive()
- {
- return isInvalidating();
- }
-
- @Override
public boolean isInvalidating()
{
return false;
@@ -298,13 +291,6 @@
}
@Override
- @Deprecated
- public String enableDurableLocking(boolean enable)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public String enableDurableLocking()
{
throw new UnsupportedOperationException();
@@ -337,22 +323,6 @@
}
@Override
- @Deprecated
- public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
- Map<CDOID, InternalCDORevision> oldRevisions, boolean async)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
- Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void invalidate(ViewInvalidationData invalidationData)
{
throw new UnsupportedOperationException();
@@ -365,19 +335,6 @@
}
@Override
- @Deprecated
- public void updateLockStates(CDOLockState[] newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer)
- {
- // Do nothing
- }
-
- @Override
- public void updateLockStates(Collection<? extends CDOLockState> newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer)
- {
- // Do nothing
- }
-
- @Override
public void resourceLoaded(CDOResourceImpl resource, boolean loaded)
{
// Do nothing
@@ -503,29 +460,6 @@
throw new UnsupportedOperationException();
}
- @Deprecated
- public org.eclipse.emf.internal.cdo.view.CDOLockStateLoadingPolicy getLockStateLoadingPolicy()
- {
- return null;
- }
-
- @Deprecated
- public void setLockStateLoadingPolicy(org.eclipse.emf.internal.cdo.view.CDOLockStateLoadingPolicy lockStateLoadingPolicy)
- {
- }
-
- @Deprecated
- public boolean isLockStatePrefetchEnabled()
- {
- return false;
- }
-
- @Deprecated
- public void setLockStatePrefetchEnabled(boolean enabled)
- {
- throw new UnsupportedOperationException();
- }
-
@Override
public CDOAdapterPolicy[] getChangeSubscriptionPolicies()
{
@@ -557,20 +491,6 @@
}
@Override
- @Deprecated
- public CDOStaleReferencePolicy getStaleReferenceBehaviour()
- {
- return getStaleReferencePolicy();
- }
-
- @Override
- @Deprecated
- public void setStaleReferenceBehaviour(CDOStaleReferencePolicy policy)
- {
- setStaleReferencePolicy(policy);
- }
-
- @Override
public CDOStaleReferencePolicy getStaleReferencePolicy()
{
return CDOStaleReferencePolicy.DEFAULT;
@@ -637,6 +557,81 @@
}
@Override
+ @Deprecated
+ public boolean isInvalidationRunnerActive()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public String enableDurableLocking(boolean enable)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
+ Map<CDOID, InternalCDORevision> oldRevisions, boolean async)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
+ Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void updateLockStates(CDOLockState[] newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ public org.eclipse.emf.internal.cdo.view.CDOLockStateLoadingPolicy getLockStateLoadingPolicy()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ public void setLockStateLoadingPolicy(org.eclipse.emf.internal.cdo.view.CDOLockStateLoadingPolicy lockStateLoadingPolicy)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ public boolean isLockStatePrefetchEnabled()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ public void setLockStatePrefetchEnabled(boolean enabled)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CDOStaleReferencePolicy getStaleReferenceBehaviour()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void setStaleReferenceBehaviour(CDOStaleReferencePolicy policy)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
protected void doBeforeDeactivate() throws Exception
{
closing = true;
@@ -768,20 +763,6 @@
/**
* Server sessions may not be used to change the user's credentials: it must
* be done client-side by interaction with the user.
- *
- * @since 4.3
- * @deprecated
- */
- @Override
- @Deprecated
- public void changeCredentials()
- {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Server sessions may not be used to change the user's credentials: it must
- * be done client-side by interaction with the user.
*/
@Override
public char[] changeServerPassword()
@@ -988,13 +969,6 @@
}
@Override
- @Deprecated
- public boolean isSupportingEcore()
- {
- return repository.isSupportingEcore();
- }
-
- @Override
public boolean isSerializingCommits()
{
return repository.isSerializingCommits();
@@ -1348,60 +1322,17 @@
}
@Override
- @Deprecated
- public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache, byte securityImpact,
- Map<CDOID, CDOPermission> newPermissions)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void invalidate(InvalidationData invalidationData)
{
throw new UnsupportedOperationException();
}
@Override
- @Deprecated
- public void handleCommitNotification(CDOCommitInfo commitInfo)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void handleCommitNotification(CDOCommitInfo commitInfo, boolean clearResourcePathCache)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void handleCommitNotification(CommitNotificationInfo info)
{
throw new UnsupportedOperationException();
}
- @Deprecated
- @Override
- public void handleLockNotification(CDOLockChangeInfo lockChangeInfo, InternalCDOView sender)
- {
- throw new UnsupportedOperationException();
- }
-
@Override
public void handleLockNotification(CDOLockChangeInfo lockChangeInfo, InternalCDOView sender, boolean async)
{
@@ -1409,13 +1340,6 @@
}
@Override
- @Deprecated
- public void handleBranchNotification(InternalCDOBranch branch)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void handleViewClosed(int viewID)
{
throw new UnsupportedOperationException();
@@ -1428,20 +1352,6 @@
}
@Override
- @Deprecated
- public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void setAuthenticator(org.eclipse.emf.cdo.common.protocol.CDOAuthenticator authenticator)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public IPasswordCredentialsProvider getCredentialsProvider()
{
throw new UnsupportedOperationException();
@@ -1508,20 +1418,6 @@
}
@Override
- @Deprecated
- public CDORevisionAvailabilityInfo createRevisionAvailabilityInfo(CDOBranchPoint branchPoint)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void cacheRevisions(CDORevisionAvailabilityInfo info)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public MergeData getMergeData(CDOBranchPoint target, CDOBranchPoint source, CDOBranchPoint sourceBase, boolean computeChangeSets)
{
throw new UnsupportedOperationException();
@@ -1670,5 +1566,97 @@
{
throw new UnsupportedOperationException();
}
+
+ @Override
+ @Deprecated
+ public void changeCredentials()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public boolean isSupportingEcore()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache, byte securityImpact,
+ Map<CDOID, CDOPermission> newPermissions)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void handleCommitNotification(CDOCommitInfo commitInfo)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void handleCommitNotification(CDOCommitInfo commitInfo, boolean clearResourcePathCache)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void handleLockNotification(CDOLockChangeInfo lockChangeInfo, InternalCDOView sender)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void handleBranchNotification(InternalCDOBranch branch)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void setAuthenticator(org.eclipse.emf.cdo.common.protocol.CDOAuthenticator authenticator)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CDORevisionAvailabilityInfo createRevisionAvailabilityInfo(CDOBranchPoint branchPoint)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void cacheRevisions(CDORevisionAvailabilityInfo info)
+ {
+ throw new UnsupportedOperationException();
+ }
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
index 9448ad9..625c212 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
@@ -24,7 +24,7 @@
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.protocol.CDOProtocol.CommitNotificationInfo;
@@ -764,9 +764,9 @@
{
Map<CDOID, LockGrade> locks = lockingManager.getLocks(view);
- for (CDOLockState lockState : lockChangeInfo.getNewLockStates())
+ for (CDOLockDelta delta : lockChangeInfo.getLockDeltas())
{
- Object lockedObject = lockState.getLockedObject();
+ Object lockedObject = delta.getTarget();
CDOID id = CDOLockUtil.getLockedObjectID(lockedObject);
LockGrade lockGrade = locks.get(id);
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 05a06ad..fbea64a 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
@@ -26,6 +26,7 @@
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
@@ -49,6 +50,8 @@
import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo;
import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
+import org.eclipse.emf.cdo.internal.server.LockingManager.LockDeltaCollector;
+import org.eclipse.emf.cdo.internal.server.LockingManager.LockStateCollector;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.IStoreAccessor;
@@ -82,11 +85,10 @@
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.IRWOLockManager;
import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
import org.eclipse.net4j.util.io.ExtendedDataInputStream;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
-import org.eclipse.net4j.util.om.monitor.Monitor;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.trace.ContextTracer;
@@ -97,7 +99,6 @@
import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -126,8 +127,6 @@
private InternalRepository repository;
- private InternalLockManager lockManager;
-
private InternalCDOPackageRegistry repositoryPackageRegistry;
private boolean packageRegistryLocked;
@@ -180,10 +179,6 @@
private CommitData originalCommmitData;
- private Set<Object> lockedObjects = new HashSet<>();
-
- private List<CDOID> lockedTargets;
-
private Map<CDOID, CDOID> idMappings = CDOIDUtil.createMap();
private CDOReferenceAdjuster idMapper = new CDOIDMapper(idMappings);
@@ -202,18 +197,49 @@
private ExtendedDataInputStream lobs;
- private CDOLockState[] locksOnNewObjects = Repository.NO_LOCK_STATES;
+ private long optimisticLockingTimeout;
+ private InternalLockManager lockManager;
+
+ /**
+ * The keys of objects that are locked in lockObjects().
+ */
+ private Set<Object> lockedObjects = new HashSet<>();
+
+ /**
+ * The IDs of referenced objects that are locked in lockObjects(), only relevant if ensuringReferentialIntegrity.
+ */
+ private List<CDOID> lockedTargets;
+
+ /**
+ * The lock states on new objects that the client wants to keep after the commit.
+ */
+ private CDOLockState[] locksOnNewObjects = CDOLockUtil.NO_LOCK_STATES;
+
+ /**
+ * The IDs of objects that the client wants to release after the commit, as per autoReleaseLocks.
+ */
private CDOID[] idsToUnlock = new CDOID[0];
+ /**
+ * The lock deltas that are visible after the commit.
+ */
+ private final LockDeltaCollector lockDeltas = new LockDeltaCollector();
+
+ /**
+ * The lock states that are visible after the commit.
+ */
+ private final LockStateCollector lockStates = new LockStateCollector();
+
+ /**
+ * The lock state changes that are visible after the commit.
+ */
+ private CDOLockChangeInfo lockChangeInfo;
+
private Map<Object, Object> data;
private CommitNotificationInfo commitNotificationInfo = new CommitNotificationInfo();
- private CDOLockChangeInfo lockChangeInfo;
-
- private final List<LockState<Object, IView>> postCommitLockStates = new ArrayList<>();
-
private boolean allowModify;
public TransactionCommitContext(InternalTransaction transaction)
@@ -659,6 +685,12 @@
}
@Override
+ public void setOptimisticLockingTimeout(long optimisticLockingTimeout)
+ {
+ this.optimisticLockingTimeout = optimisticLockingTimeout;
+ }
+
+ @Override
public void setCommitNumber(int commitNumber)
{
this.commitNumber = commitNumber;
@@ -689,20 +721,6 @@
}
@Override
- @Deprecated
- public boolean isAutoReleaseLocksEnabled()
- {
- return false;
- }
-
- @Override
- @Deprecated
- public void setAutoReleaseLocksEnabled(boolean on)
- {
- // Do nothing.
- }
-
- @Override
public CDOLockState[] getLocksOnNewObjects()
{
return locksOnNewObjects;
@@ -868,12 +886,6 @@
}
}
- @Override
- public List<LockState<Object, IView>> getPostCommmitLockStates()
- {
- return postCommitLockStates;
- }
-
protected void handleException(Throwable throwable)
{
try
@@ -955,16 +967,6 @@
return timeStamp;
}
- /**
- * @deprecated Does not seem to be used.
- */
- @Deprecated
- protected void setTimeStamp(long timeStamp)
- {
- repository.forceCommitTimeStamp(timeStamp, new Monitor());
- this.timeStamp = timeStamp;
- }
-
@Override
public long getPreviousTimeStamp()
{
@@ -972,6 +974,18 @@
}
@Override
+ public List<CDOLockDelta> getLockDeltas()
+ {
+ return lockDeltas;
+ }
+
+ @Override
+ public List<CDOLockState> getLockStates()
+ {
+ return lockStates;
+ }
+
+ @Override
public void postCommit(boolean success)
{
try
@@ -1195,11 +1209,13 @@
{
try
{
- long timeout = repository.getOptimisticLockingTimeout();
+ long timeout = optimisticLockingTimeout == CDOProtocolConstants.DEFAULT_OPTIMISTIC_LOCKING_TIMEOUT //
+ ? repository.getOptimisticLockingTimeout() //
+ : optimisticLockingTimeout;
// First lock all objects (incl. possible ref targets).
- // This is a transient operation, it does not check for existence!
- lockManager.lock2(LockType.WRITE, transaction, lockedObjects, timeout);
+ // This is a transient operation, it does not check for existence of the ref targets!
+ lockManager.lock(transaction, lockedObjects, LockType.WRITE, 1, timeout, false, false, null, null);
}
catch (Exception ex)
{
@@ -1254,7 +1270,7 @@
Object key = lockManager.getLockKey(id, branch);
lockedObjects.add(key);
- // Let this object be checked for existance after it has been locked
+ // Let this object be checked for existence after it has been locked
if (lockedTargets == null)
{
lockedTargets = new ArrayList<>();
@@ -1665,6 +1681,10 @@
return accessor;
}
+ /**
+ * Called from commit().
+ * Remembers the lockChangeInfo for postCommit().
+ */
protected void updateInfraStructure(OMMonitor monitor)
{
try
@@ -1678,18 +1698,21 @@
InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
commitInfoManager.setLastCommitOfBranch(branch, timeStamp);
- releaseImplicitLocks();
+ releaseImplicitLocks(); // These have no visible impact outside of this commit.
monitor.worked();
- acquireLocksOnNewObjects();
+ CDOLockOwner lockOwner = CDOLockUtil.createLockOwner(transaction);
+
+ acquireLocksOnNewObjects(lockOwner);
monitor.worked();
- autoReleaseExplicitLocks();
+ autoReleaseExplicitLocks(lockOwner);
monitor.worked();
- if (!postCommitLockStates.isEmpty())
+ if (!lockDeltas.isEmpty())
{
- lockChangeInfo = createLockChangeInfo(postCommitLockStates);
+ CDOBranchPoint branchPoint = getBranchPoint();
+ lockChangeInfo = CDOLockUtil.createLockChangeInfo(branchPoint, lockOwner, lockDeltas, lockStates);
}
repository.notifyWriteAccessHandlers(transaction, this, false, monitor.fork());
@@ -1704,24 +1727,24 @@
}
}
- protected synchronized void releaseImplicitLocks()
+ protected void releaseImplicitLocks()
{
// Unlock objects locked during commit
if (!lockedObjects.isEmpty())
{
- lockManager.unlock2(LockType.WRITE, transaction, lockedObjects);
+ lockManager.unlock(transaction, lockedObjects, LockType.WRITE, 1, false, false, null, null);
lockedObjects.clear();
}
}
- protected void acquireLocksOnNewObjects() throws InterruptedException
+ protected void acquireLocksOnNewObjects(CDOLockOwner lockOwner) throws InterruptedException
{
- final CDOLockOwner owner = CDOLockUtil.createLockOwner(transaction);
- final boolean mapIDs = transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE;
+ boolean mapIDs = transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE;
+ lockDeltas.setOperation(Operation.LOCK);
- for (CDOLockState lockState : locksOnNewObjects)
+ for (CDOLockState lockStateOnNewObject : locksOnNewObjects)
{
- Object target = lockState.getLockedObject();
+ Object target = lockStateOnNewObject.getLockedObject();
if (mapIDs)
{
@@ -1733,24 +1756,18 @@
target = idAndBranch != null ? CDOIDUtil.createIDAndBranch(newID, idAndBranch.getBranch()) : newID;
}
- LockState<Object, IView> postCommitLockState = null;
for (LockType type : ALL_LOCK_TYPES)
{
- if (lockState.isLocked(type, owner, false))
+ if (lockStateOnNewObject.isLocked(type, lockOwner, false))
{
- List<LockState<Object, IView>> lockStates = lockManager.lock2(type, transaction, Collections.singleton(target), 0);
- postCommitLockState = lockStates.get(0);
+ Set<Object> objects = Collections.singleton(target);
+ lockManager.lock(transaction, objects, type, 1, IRWOLockManager.NO_TIMEOUT, false, true, lockDeltas, lockStates);
}
}
-
- if (postCommitLockState != null)
- {
- postCommitLockStates.add(postCommitLockState);
- }
}
}
- protected void autoReleaseExplicitLocks() throws InterruptedException
+ protected void autoReleaseExplicitLocks(CDOLockOwner lockOwner) throws InterruptedException
{
List<Object> targets = new ArrayList<>();
@@ -1772,29 +1789,8 @@
}
}
- 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);
- }
- }
-
- protected CDOLockChangeInfo createLockChangeInfo(List<LockState<Object, IView>> newLockStates)
- {
- CDOBranchPoint branchPoint = getBranchPoint();
- CDOLockOwner lockOwner = transaction.getLockOwner();
- List<CDOLockState> newStates = Arrays.asList(Repository.toCDOLockStates(newLockStates));
-
- return CDOLockUtil.createLockChangeInfo(branchPoint, lockOwner, Operation.UNLOCK, null, newStates);
+ lockDeltas.setOperation(Operation.UNLOCK);
+ lockManager.unlock(transaction, targets, null, IRWOLockManager.ALL_LOCKS, false, true, lockDeltas, lockStates);
}
protected void addNewPackageUnits(OMMonitor monitor)
@@ -1905,6 +1901,36 @@
CDOCommonUtil.formatTimeStamp(timeStamp));
}
+ @Override
+ @Deprecated
+ public boolean isAutoReleaseLocksEnabled()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void setAutoReleaseLocksEnabled(boolean on)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> getPostCommmitLockStates()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Does not seem to be used.
+ */
+ @Deprecated
+ protected void setTimeStamp(long timeStamp)
+ {
+ throw new UnsupportedOperationException();
+ }
+
/**
* @author Eike Stepper
*/
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
index 517b521..5b62e06 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
@@ -160,13 +160,6 @@
}
@Override
- @Deprecated
- public boolean isLocal(CDOID id)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void ensureLastObjectID(CDOID id)
{
if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT)
@@ -275,7 +268,7 @@
@Override
public synchronized CDOBranch[] deleteBranches(int branchID, OMMonitor monitor)
{
- Set<CDOBranch> branches = getRepository().getBranchManager().getBranches(branchID);
+ Set<CDOBranch> deletedBranches = getRepository().getBranchManager().getBranches(branchID);
monitor.begin(revisions.size());
@@ -284,7 +277,7 @@
Map.Entry<Object, List<InternalCDORevision>> entry = it.next();
CDOBranch revisionBranch = getBranch(entry.getKey());
- if (branches.contains(revisionBranch))
+ if (deletedBranches.contains(revisionBranch))
{
it.remove();
}
@@ -292,26 +285,31 @@
monitor.worked();
}
- for (CDOBranch b : branches)
+ for (Iterator<CommitInfo> it = commitInfos.iterator(); it.hasNext();)
{
- branchInfos.remove(b.getID());
+ CommitInfo commitInfo = it.next();
+ if (deletedBranches.contains(commitInfo.getBranch()))
+ {
+ it.remove();
+ }
}
- return branches.toArray(new CDOBranch[branches.size()]);
- }
+ for (Iterator<Map.Entry<String, LockArea>> it = lockAreas.entrySet().iterator(); it.hasNext();)
+ {
+ Map.Entry<String, LockArea> entry = it.next();
+ LockArea lockArea = entry.getValue();
+ if (deletedBranches.contains(lockArea.getBranch()))
+ {
+ it.remove();
+ }
+ }
- @Override
- @Deprecated
- public void deleteBranch(int branchID)
- {
- throw new UnsupportedOperationException();
- }
+ for (CDOBranch branch : deletedBranches)
+ {
+ branchInfos.remove(branch.getID());
+ }
- @Override
- @Deprecated
- public void renameBranch(int branchID, String newName)
- {
- throw new UnsupportedOperationException();
+ return deletedBranches.toArray(new CDOBranch[deletedBranches.size()]);
}
@Override
@@ -978,30 +976,33 @@
LockArea area = getLockArea(durableLockingID);
Map<CDOID, LockGrade> locks = area.getLocks();
- InternalLockManager lockManager = getRepository().getLockingManager();
- for (Object objectToUnlock : objectsToUnlock)
+ if (objectsToUnlock == null)
{
- CDOID id = lockManager.getLockKeyID(objectToUnlock);
- LockGrade grade = locks.get(id);
- if (grade != null)
+ locks.clear();
+ }
+ else
+ {
+ InternalLockManager lockManager = getRepository().getLockingManager();
+ for (Object objectToUnlock : objectsToUnlock)
{
- grade = grade.getUpdated(type, false);
- if (grade == LockGrade.NONE)
+ CDOID id = lockManager.getLockKeyID(objectToUnlock);
+ LockGrade grade = locks.get(id);
+ if (grade != null)
{
- locks.remove(id);
+ grade = grade.getUpdated(type, false);
+ if (grade == LockGrade.NONE)
+ {
+ locks.remove(id);
+ }
+ else
+ {
+ locks.put(id, grade);
+ }
}
}
}
}
- @Override
- public synchronized void unlock(String durableLockingID)
- {
- LockArea area = getLockArea(durableLockingID);
- Map<CDOID, LockGrade> locks = area.getLocks();
- locks.clear();
- }
-
public synchronized void queryLobs(List<byte[]> ids)
{
for (Iterator<byte[]> it = ids.iterator(); it.hasNext();)
@@ -1517,4 +1518,32 @@
return MessageFormat.format("CommitInfo[{0}, {1}, {2}, {3}, {4}, {5}]", branch, getTimeStamp(), previousTimeStamp, userID, comment, mergeSource);
}
}
+
+ @Override
+ @Deprecated
+ public boolean isLocal(CDOID id)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void deleteBranch(int branchID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void renameBranch(int branchID, String newName)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(String durableLockingID)
+ {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java
index e750b1d..a401782 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java
@@ -142,20 +142,6 @@
}
@Override
- @Deprecated
- public void deleteBranch(int branchID)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void renameBranch(int branchID, String newName)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void renameBranch(int branchID, String oldName, String newName)
{
store.renameBranch(branchID, oldName, newName);
@@ -226,13 +212,6 @@
}
}
- @Deprecated
- @Override
- protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor)
- {
- throw new UnsupportedOperationException();
- }
-
@Override
protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, CDOBranchPoint mergeSource,
OMMonitor monitor)
@@ -460,12 +439,6 @@
}
@Override
- public void unlock(String durableLockingID)
- {
- store.unlock(durableLockingID);
- }
-
- @Override
public void queryLobs(List<byte[]> ids)
{
store.queryLobs(ids);
@@ -506,4 +479,32 @@
super.doDeactivate();
}
+
+ @Override
+ @Deprecated
+ public void deleteBranch(int branchID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void renameBranch(int branchID, String newName)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(String durableLockingID)
+ {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
index 36ad118..398aa5f 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
@@ -25,8 +25,6 @@
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lob.CDOLob;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-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.lock.IDurableLockingManager.LockArea;
@@ -59,7 +57,6 @@
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
-import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.InternalRepositorySynchronizer;
import org.eclipse.emf.cdo.spi.server.InternalSession;
@@ -68,7 +65,6 @@
import org.eclipse.emf.cdo.spi.server.InternalSynchronizableRepository;
import org.eclipse.emf.cdo.spi.server.InternalTransaction;
import org.eclipse.emf.cdo.spi.server.InternalView;
-import org.eclipse.emf.cdo.spi.server.SyncingUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.collection.IndexedList;
@@ -362,51 +358,53 @@
@Override
public void handleLockChangeInfo(CDOLockChangeInfo lockChangeInfo)
{
- CDOLockOwner owner = lockChangeInfo.getLockOwner();
- if (owner == null)
- {
- return;
- }
+ throw new UnsupportedOperationException("Needs reimplementation for CDOLockDeltas");
- String durableLockingID = owner.getDurableLockingID();
- CDOBranch viewedBranch = lockChangeInfo.getBranch();
- InternalLockManager lockManager = getLockingManager();
- LockType lockType = lockChangeInfo.getLockType();
-
- InternalView view = null;
-
- try
- {
- view = SyncingUtil.openViewWithLockArea(replicatorSession, lockManager, viewedBranch, durableLockingID);
- List<Object> lockables = new LinkedList<>();
-
- for (CDOLockState lockState : lockChangeInfo.getNewLockStates())
- {
- lockables.add(lockState.getLockedObject());
- }
-
- if (lockChangeInfo.getOperation() == Operation.LOCK)
- {
- // If we can't lock immediately, there's a conflict, which means we're in big
- // trouble: somehow locks were obtained on the clone but not on the master. What to do?
- // TODO (CD) Consider this problem further
- long timeout = 0;
-
- super.lock(view, lockType, lockables, null, false, timeout);
- }
- else if (lockChangeInfo.getOperation() == Operation.UNLOCK)
- {
- super.doUnlock(view, lockType, lockables, false);
- }
- else
- {
- throw new IllegalStateException("Unexpected: " + lockChangeInfo.getOperation());
- }
- }
- finally
- {
- LifecycleUtil.deactivate(view);
- }
+ // CDOLockOwner owner = lockChangeInfo.getLockOwner();
+ // if (owner == null)
+ // {
+ // return;
+ // }
+ //
+ // String durableLockingID = owner.getDurableLockingID();
+ // CDOBranch viewedBranch = lockChangeInfo.getBranch();
+ // InternalLockManager lockManager = getLockingManager();
+ // LockType lockType = lockChangeInfo.getLockType();
+ //
+ // InternalView view = null;
+ //
+ // try
+ // {
+ // view = SyncingUtil.openViewWithLockArea(replicatorSession, lockManager, viewedBranch, durableLockingID);
+ // List<Object> lockables = new LinkedList<>();
+ //
+ // for (CDOLockState lockState : lockChangeInfo.getNewLockStates())
+ // {
+ // lockables.add(lockState.getLockedObject());
+ // }
+ //
+ // if (lockChangeInfo.getOperation() == Operation.LOCK)
+ // {
+ // // If we can't lock immediately, there's a conflict, which means we're in big
+ // // trouble: somehow locks were obtained on the clone but not on the master. What to do?
+ // // TODO (CD) Consider this problem further
+ // long timeout = 0;
+ //
+ // super.doLock(view, lockType, lockables, null, false, timeout);
+ // }
+ // else if (lockChangeInfo.getOperation() == Operation.UNLOCK)
+ // {
+ // super.doUnlock(view, lockType, lockables, false);
+ // }
+ // else
+ // {
+ // throw new IllegalStateException("Unexpected: " + lockChangeInfo.getOperation());
+ // }
+ // }
+ // finally
+ // {
+ // LifecycleUtil.deactivate(view);
+ // }
}
@Override
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
index bc905a1..43e8bae 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
@@ -21,6 +21,7 @@
import org.eclipse.emf.cdo.common.lob.CDOClob;
import org.eclipse.emf.cdo.common.lob.CDOLob;
import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
@@ -425,14 +426,6 @@
public ExtendedDataInputStream getLobs();
/**
- *
- * @since 3.0
- * @deprecated As of 4.5 no longer supported. See {@link #getIDsToUnlock()}.
- */
- @Deprecated
- public boolean isAutoReleaseLocksEnabled();
-
- /**
* Returns an array of the locks on the new objects that are part of the commit operation represented by this
* <code>CommitContext</code>.
*
@@ -472,9 +465,14 @@
public List<CDOIDReference> getXRefs();
/**
- * @since 4.1
+ * @since 4.15
*/
- public List<LockState<Object, IView>> getPostCommmitLockStates();
+ public List<CDOLockDelta> getLockDeltas();
+
+ /**
+ * @since 4.15
+ */
+ public List<CDOLockState> getLockStates();
/**
* @since 4.3
@@ -492,6 +490,21 @@
public void modify(Consumer<ModificationContext> modifier);
/**
+ *
+ * @since 3.0
+ * @deprecated As of 4.5 no longer supported. See {@link #getIDsToUnlock()}.
+ */
+ @Deprecated
+ public boolean isAutoReleaseLocksEnabled();
+
+ /**
+ * @since 4.1
+ * @deprecated As of 4.15 use {@link #getLockStates()}.
+ */
+ @Deprecated
+ public List<LockState<Object, IView>> getPostCommmitLockStates();
+
+ /**
* A data and result context for the modifications in {@link CommitContext#modify(Consumer)}.
*
* @author Eike Stepper
@@ -858,6 +871,10 @@
public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock);
+ /**
+ * @deprecated As of 4.15 use {@link #unlock(String, LockType, Collection) unlock(durableLockingID, null, null)}.
+ */
+ @Deprecated
public void unlock(String durableLockingID);
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java
index d4b396a..8374cf5 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java
@@ -149,10 +149,9 @@
public void setLastUpdateTime(long lastUpdateTime);
/**
- * @deprecated As of 4.5 no longer supported. See {@link #setIDsToUnlock(CDOID[])}.
+ * @since 4.15
*/
- @Deprecated
- public void setAutoReleaseLocksEnabled(boolean on);
+ public void setOptimisticLockingTimeout(long optimisticLockingTimeout);
/**
* @since 4.1
@@ -189,4 +188,10 @@
* @since 4.3
*/
public void setSecurityImpact(byte securityImpact, Set<? extends Object> impactedRules);
+
+ /**
+ * @deprecated As of 4.5 no longer supported. See {@link #setIDsToUnlock(CDOID[])}.
+ */
+ @Deprecated
+ public void setAutoReleaseLocksEnabled(boolean on);
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
index 9e7a63a..1e9ee87 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
@@ -19,15 +19,24 @@
import org.eclipse.net4j.util.concurrent.IRWOLockManager;
import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
/**
* The type of the to-be-locked objects is either {@link CDOIDAndBranch} or {@link CDOID}, depending on whether
* branching is supported by the repository or not.
+ * <p>
+ * The following features are supported in addition to {@link IRWOLockManager}:
+ * <ul>
+ * <li> Recursive locking
+ * <li> Distinction between explicit and implicit locking
+ * <li> Durable locking
+ * </ul>
*
* @author Eike Stepper
* @since 3.0
@@ -43,11 +52,6 @@
/**
* @since 4.0
*/
- public Object getLockEntryObject(Object key);
-
- /**
- * @since 4.0
- */
public Object getLockKey(CDOID id, CDOBranch branch);
/**
@@ -56,49 +60,29 @@
public CDOID getLockKeyID(Object key);
/**
+ * @since 4.15
+ */
+ public CDOBranch getLockKeyBranch(Object key);
+
+ /**
* @since 4.0
*/
public Map<CDOID, LockGrade> getLocks(IView view);
/**
- * @since 4.0
+ * @since 4.15
*/
- @Deprecated
- public void lock(boolean explicit, LockType type, IView context, Collection<? extends Object> objects, long timeout) throws InterruptedException;
+ public long lock(IView view, Collection<? extends Object> objects, LockType lockType, int count, long timeout, //
+ boolean recursive, boolean explicit, //
+ LockDeltaHandler<Object, IView> deltaHandler, Consumer<LockState<Object, IView>> stateHandler) //
+ throws InterruptedException, TimeoutRuntimeException;
/**
- * @since 4.1
+ * @since 4.15
*/
- public List<LockState<Object, IView>> lock2(boolean explicit, LockType type, IView context, Collection<? extends Object> objects, boolean recursive,
- long timeout) throws InterruptedException;
-
- /**
- * Attempts to release for a given lock type, view and objects.
- *
- * @throws IllegalMonitorStateException
- * Unlocking objects without lock.
- * @since 4.0
- */
- @Deprecated
- public void unlock(boolean explicit, LockType type, IView context, Collection<? extends Object> objects);
-
- /**
- * @since 4.1
- */
- public List<LockState<Object, IView>> unlock2(boolean explicit, LockType type, IView context, Collection<? extends Object> objects, boolean recursive);
-
- /**
- * Attempts to release all locks(read and write) for a given view.
- *
- * @since 4.0
- */
- @Deprecated
- public void unlock(boolean explicit, IView context);
-
- /**
- * @since 4.1
- */
- public List<LockState<Object, IView>> unlock2(boolean explicit, IView context);
+ public long unlock(IView view, Collection<? extends Object> objects, LockType lockType, int count, //
+ boolean recursive, boolean explicit, //
+ LockDeltaHandler<Object, IView> deltaHandler, Consumer<LockState<Object, IView>> stateHandler);
/**
* @since 4.0
@@ -113,13 +97,13 @@
/**
* @since 4.1
*/
- // TODO (CD) I've also added this to DurableLocking2 Refactoring opportunity?
public void updateLockArea(LockArea lockArea);
/**
- * @since 4.0
+ * @since 4.15
*/
- public IView openView(ISession session, int viewID, boolean readOnly, String durableLockingID);
+ public void openView(ISession session, int viewID, boolean readOnly, String durableLockingID, Consumer<IView> viewConsumer,
+ BiConsumer<CDOID, LockGrade> lockConsumer);
/**
* @since 4.1
@@ -137,17 +121,86 @@
public void getLockStates(Collection<Object> keys, BiConsumer<Object, LockState<Object, IView>> consumer);
/**
- * @since 4.4
+ * @since 4.15
*/
- public List<LockState<Object, IView>> getLockStates();
-
- /**
- * @since 4.1
- */
- public void setLockState(Object key, LockState<Object, IView> lockState);
+ public void getLockStates(Consumer<LockState<Object, IView>> consumer);
/**
* @since 4.1
*/
public void reloadLocks();
+
+ @Deprecated
+ public List<LockState<Object, IView>> getLockStates();
+
+ @Deprecated
+ public void setLockState(Object key, LockState<Object, IView> lockState);
+
+ @Deprecated
+ public Object getLockEntryObject(Object key);
+
+ @Deprecated
+ public void lock(boolean explicit, LockType type, IView view, Collection<? extends Object> objects, long timeout) throws InterruptedException;
+
+ @Override
+ @Deprecated
+ public void lock(LockType type, IView context, Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException;
+
+ @Override
+ @Deprecated
+ public void lock(LockType type, IView context, Object objectToLock, long timeout) throws InterruptedException;
+
+ @Deprecated
+ public List<LockState<Object, IView>> lock2(boolean explicit, LockType type, IView view, Collection<? extends Object> objects, boolean recursive,
+ long timeout) throws InterruptedException;
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> lock2(LockType type, IView context, Collection<? extends Object> objectsToLock, long timeout)
+ throws InterruptedException;
+
+ @Deprecated
+ public void unlock(boolean explicit, LockType type, IView view, Collection<? extends Object> objects);
+
+ @Deprecated
+ public void unlock(boolean explicit, IView view);
+
+ @Override
+ @Deprecated
+ public void unlock(LockType type, IView context, Collection<? extends Object> objectsToUnlock);
+
+ @Override
+ @Deprecated
+ public void unlock(IView context);
+
+ @Deprecated
+ public List<LockState<Object, IView>> unlock2(boolean explicit, IView view);
+
+ @Deprecated
+ public List<LockState<Object, IView>> unlock2(boolean explicit, LockType type, IView view, Collection<? extends Object> objects, boolean recursive);
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> unlock2(LockType type, IView context, Collection<? extends Object> objectsToUnlock);
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> unlock2(IView context, Collection<? extends Object> objectsToUnlock);
+
+ @Override
+ @Deprecated
+ public List<LockState<Object, IView>> unlock2(IView context);
+
+ @Override
+ @Deprecated
+ public long lock(IView context, Collection<? extends Object> objects, LockType lockType, int count, long timeout,
+ LockDeltaHandler<Object, IView> deltaHandler, Consumer<LockState<Object, IView>> stateHandler) throws InterruptedException, TimeoutRuntimeException;
+
+ @Override
+ @Deprecated
+ public long unlock(IView context, Collection<? extends Object> objects, LockType lockType, int count, LockDeltaHandler<Object, IView> deltaHandler,
+ Consumer<LockState<Object, IView>> stateHandler);
+
+ @Deprecated
+ public IView openView(ISession session, int viewID, boolean readOnly, String durableLockingID);
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
index 9c17dab..04d0eb7 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
@@ -144,13 +144,6 @@
public void setSessionManager(InternalSessionManager sessionManager);
/**
- * @deprecated As of 4.1 use {@link #getLockingManager()}.
- */
- @Override
- @Deprecated
- public InternalLockManager getLockManager();
-
- /**
* @since 4.1
*/
@Override
@@ -229,20 +222,6 @@
public void commit(InternalCommitContext commitContext, OMMonitor monitor);
/**
- * @since 4.0
- * @deprecated As of 4.2 use {@link #sendCommitNotification(InternalSession, CDOCommitInfo, boolean)}.
- */
- @Deprecated
- public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo);
-
- /**
- * @since 4.2
- * @deprecated As of 4.3 use {@link #sendCommitNotification(ISessionProtocol.CommitNotificationInfo)}.
- */
- @Deprecated
- public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo, boolean clearResourcePathCache);
-
- /**
* @since 4.3
*/
public void sendCommitNotification(CommitNotificationInfo info);
@@ -272,14 +251,6 @@
public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint);
/**
- * @since 4.0
- * @deprecated As of 4.6 use {@link #getMergeData2(CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, OMMonitor)}.
- */
- @Deprecated
- public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
- CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor);
-
- /**
* @since 4.6
*/
public MergeDataResult getMergeData2(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
@@ -317,13 +288,6 @@
public void setSkipInitialization(boolean skipInitialization);
/**
- * @since 4.0
- * @deprecated As of 4.3 use {@link #initSystemPackages()}.
- */
- @Deprecated
- public void initSystemPackages();
-
- /**
* @since 4.3
*/
public void initSystemPackages(boolean firstStart);
@@ -344,6 +308,11 @@
public UnlockObjectsResult unlock(InternalView view, LockType type, List<CDOID> ids, boolean recursive);
/**
+ * @since 4.15
+ */
+ public UnlockObjectsResult unlock(InternalView view);
+
+ /**
* @since 4.2
*/
public long getOptimisticLockingTimeout();
@@ -363,9 +332,9 @@
{
@Override
public InternalRepository getSource();
-
+
public boolean isFirstStart();
-
+
/**
* @since 4.7
*/
@@ -390,4 +359,40 @@
*/
public void doPostActivate(InternalSession session);
}
+
+ /**
+ * @deprecated As of 4.1 use {@link #getLockingManager()}.
+ */
+ @Override
+ @Deprecated
+ public InternalLockManager getLockManager();
+
+ /**
+ * @since 4.0
+ * @deprecated As of 4.2 use {@link #sendCommitNotification(InternalSession, CDOCommitInfo, boolean)}.
+ */
+ @Deprecated
+ public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo);
+
+ /**
+ * @since 4.2
+ * @deprecated As of 4.3 use {@link #sendCommitNotification(ISessionProtocol.CommitNotificationInfo)}.
+ */
+ @Deprecated
+ public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo, boolean clearResourcePathCache);
+
+ /**
+ * @since 4.0
+ * @deprecated As of 4.6 use {@link #getMergeData2(CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, OMMonitor)}.
+ */
+ @Deprecated
+ public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
+ CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor);
+
+ /**
+ * @since 4.0
+ * @deprecated As of 4.3 use {@link #initSystemPackages()}.
+ */
+ @Deprecated
+ public void initSystemPackages();
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/SyncingUtil.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/SyncingUtil.java
index f775e7a..4d52677 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/SyncingUtil.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/SyncingUtil.java
@@ -13,8 +13,10 @@
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;
+import org.eclipse.emf.cdo.server.IView;
import org.eclipse.net4j.util.CheckUtil;
+import org.eclipse.net4j.util.concurrent.Holder;
/**
* Static methods that may help with classes related to repository synchronization.
@@ -31,29 +33,30 @@
public static InternalView openViewWithLockArea(InternalSession session, InternalLockManager lockManager, CDOBranch viewedBranch, String lockAreaID)
{
LockArea lockArea;
- InternalView view;
+ Holder<IView> viewHolder = new Holder<>();
try
{
lockArea = lockManager.getLockArea(lockAreaID);
// If we get here, the lockArea already exists.
- view = (InternalView)lockManager.openView(session, InternalSession.TEMP_VIEW_ID, true, lockAreaID);
+ lockManager.openView(session, InternalSession.TEMP_VIEW_ID, true, lockAreaID, viewHolder, null);
}
catch (LockAreaNotFoundException e)
{
// If we get here, the lockArea does not yet exist, so we open
// a view without a lockArea first, then create a lockArea with the given ID,
// and associate it with the view.
- view = session.openView(InternalSession.TEMP_VIEW_ID, viewedBranch.getHead());
+ InternalView view = session.openView(InternalSession.TEMP_VIEW_ID, viewedBranch.getHead());
lockArea = lockManager.createLockArea(view, lockAreaID);
view.setDurableLockingID(lockAreaID);
+ viewHolder.set(view);
}
CheckUtil.checkNull(lockAreaID, "lockAreaID");
CheckUtil.checkNull(lockArea, "lockArea");
CheckUtil.checkState(lockAreaID.equals(lockArea.getDurableLockingID()), "lockAreaID has incorrect value");
- return view;
+ return (InternalView)viewHolder.get();
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Branching.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Branching.java
index de8b5b8..7ee3ff5 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Branching.java
+++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Branching.java
@@ -29,7 +29,8 @@
public static void initConfigSuites(ConfigTestSuite suite, TestSuite parent, IDGenerationLocation idGenerationLocation)
{
// Without ranges
- suite.addScenario(parent, new H2Config().supportingBranches(true).idGenerationLocation(idGenerationLocation), JVM, NATIVE);
+ // suite.addScenario(parent, new H2Config().supportingBranches(true).idGenerationLocation(idGenerationLocation),
+ // JVM, NATIVE);
// With ranges
suite.addScenario(parent, new H2Config().supportingBranches(true).idGenerationLocation(idGenerationLocation).withRanges(true), JVM, NATIVE);
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BranchingTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BranchingTest.java
index b84f634..3a36359 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BranchingTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/BranchingTest.java
@@ -943,7 +943,7 @@
}
@CleanRepositoriesBefore(reason = "Revision counting")
- public void testhandleRevisionsAfterDetachInSubBranch() throws Exception
+ public void testHandleRevisionsAfterDetachInSubBranch() throws Exception
{
String name = getBranchName("subBranch");
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockStateCacheTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockStateCacheTest.java
index ae98719..77c3cff 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockStateCacheTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockStateCacheTest.java
@@ -55,54 +55,54 @@
InternalCDOLockState lockState4 = getLockState(cache, view4);
// Write lock.
- lockState1.setWriteLockOwner(owner1);
+ lockState1.addOwner(owner1, LockType.WRITE);
assertEquals(owner1, lockState1.getWriteLockOwner());
assertEquals(owner1, lockState2.getWriteLockOwner());
assertEquals(owner1, lockState3.getWriteLockOwner());
assertEquals(owner1, lockState4.getWriteLockOwner());
// Another write lock is not possible.
- assertException(IllegalStateException.class, () -> lockState2.setWriteLockOwner(owner2));
+ assertException(IllegalStateException.class, () -> lockState2.addOwner(owner2, LockType.WRITE));
// A read lock is not possible.
- assertException(IllegalStateException.class, () -> lockState3.addReadLockOwner(owner3));
+ assertException(IllegalStateException.class, () -> lockState3.addOwner(owner3, LockType.READ));
// A write option is not possible.
- assertException(IllegalStateException.class, () -> lockState4.setWriteOptionOwner(owner4));
+ assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.OPTION));
// Release write lock.
- lockState1.setWriteLockOwner(null);
+ lockState1.removeOwner(owner1, LockType.WRITE);
assertEquals(null, lockState1.getWriteLockOwner());
// Read lock first time.
- lockState1.addReadLockOwner(owner1);
+ lockState1.addOwner(owner1, LockType.READ);
assertEquals(1, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
// A write lock is not possible.
- assertException(IllegalStateException.class, () -> lockState4.setWriteLockOwner(owner4));
+ assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.WRITE));
// Read lock second time.
- lockState1.addReadLockOwner(owner2);
+ lockState1.addOwner(owner2, LockType.READ);
assertEquals(2, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
assertTrue(lockState1.getReadLockOwners().contains(owner2));
// A write lock is not possible.
- assertException(IllegalStateException.class, () -> lockState4.setWriteLockOwner(owner4));
+ assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.WRITE));
// Read lock third time.
- lockState1.addReadLockOwner(owner3);
+ lockState1.addOwner(owner3, LockType.READ);
assertEquals(3, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
assertTrue(lockState1.getReadLockOwners().contains(owner2));
assertTrue(lockState1.getReadLockOwners().contains(owner3));
// A write lock is not possible.
- assertException(IllegalStateException.class, () -> lockState4.setWriteLockOwner(owner4));
+ assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.WRITE));
// Write option.
- lockState1.setWriteOptionOwner(owner1);
+ lockState1.addOwner(owner1, LockType.OPTION);
assertEquals(3, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
assertTrue(lockState1.getReadLockOwners().contains(owner2));
@@ -457,7 +457,7 @@
// Write locked by same owner.
initial(1, 0) //
.modify(0, 0, 1) //
- .verify(IllegalStateException.class);
+ .verify(1, 0, 1);
// Write locked by same owner and read locked by same owner.
initial(1, 0, 1) //
@@ -840,36 +840,36 @@
int reader = readers[i];
if (reader > 0)
{
- lockState.addReadLockOwner(lockOwners[reader]);
+ lockState.addOwner(lockOwners[reader], LockType.READ);
}
else
{
- lockState.removeReadLockOwner(lockOwners[-reader]);
+ lockState.removeOwner(lockOwners[-reader], LockType.READ);
}
}
if (writer == -1)
{
- lockState.setWriteLockOwner(null);
+ lockState.removeOwner(lockState.getWriteLockOwner(), LockType.WRITE);
}
else if (writer > 0)
{
- lockState.setWriteLockOwner(lockOwners[writer]);
+ lockState.addOwner(lockOwners[writer], LockType.WRITE);
}
if (optioner == -1)
{
- lockState.setWriteOptionOwner(null);
+ lockState.removeOwner(lockState.getWriteOptionOwner(), LockType.OPTION);
}
else if (optioner > 0)
{
- lockState.setWriteOptionOwner(lockOwners[optioner]);
+ lockState.addOwner(lockOwners[optioner], LockType.OPTION);
}
}
private void update(int ownerToRemove)
{
- lockState.removeOwner(lockOwners[ownerToRemove]);
+ lockState.clearOwner(lockOwners[ownerToRemove]);
}
public TestExecution modify(int writer, int optioner, int... readers)
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java
index 275d4b1..65f3969 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java
@@ -27,7 +27,9 @@
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.tests.model1.Category;
import org.eclipse.emf.cdo.tests.model1.Company;
+import org.eclipse.emf.cdo.tests.model1.Customer;
import org.eclipse.emf.cdo.tests.model1.Product1;
+import org.eclipse.emf.cdo.tests.model1.Supplier;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitException;
@@ -44,13 +46,18 @@
import org.eclipse.net4j.util.event.EventUtil;
import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.spi.cdo.CDOLockStateCache;
import org.eclipse.emf.spi.cdo.InternalCDOSession;
import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
+import org.eclipse.ocl.util.CollectionUtil;
+
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -104,8 +111,8 @@
keys.add(2);
keys.add(3);
- lockingManager.lock(LockType.READ, 1, keys, 100);
- lockingManager.unlock(1);
+ lockingManager.lock(1, keys, LockType.READ, 1, 100, null, null);
+ lockingManager.unlock(1, (Collection<Integer>)null, (LockType)null, 1, null, null);
}
public void testWriteOptions() throws Exception
@@ -114,7 +121,7 @@
Set<Integer> keys = new HashSet<>();
keys.add(1);
- lockingManager.lock(LockType.OPTION, 1, keys, 100);
+ lockingManager.lock(1, keys, LockType.OPTION, 1, 100, null, null);
// (R=Read, W=Write, WO=WriteOption)
// Scenario 1: 1 has WO, 2 requests W -> fail
@@ -123,7 +130,7 @@
try
{
- lockingManager.lock(LockType.WRITE, 2, keys, 100); // Must fail
+ lockingManager.lock(2, keys, LockType.WRITE, 1, 100, null, null); // Must fail
fail("Should have thrown an exception");
}
catch (TimeoutRuntimeException e)
@@ -133,7 +140,7 @@
// Scenario 2: 1 has WO, 2 requests R -> succeed
try
{
- lockingManager.lock(LockType.READ, 2, keys, 100); // Must succeed
+ lockingManager.lock(2, keys, LockType.READ, 1, 100, null, null); // Must succeed
}
catch (TimeoutRuntimeException e)
{
@@ -143,7 +150,7 @@
// Scenario 3: 1 has WO, 2 has R, 1 requests W -> fail
try
{
- lockingManager.lock(LockType.WRITE, 1, keys, 100); // Must fail
+ lockingManager.lock(1, keys, LockType.WRITE, 1, 100, null, null); // Must fail
fail("Should have thrown an exception");
}
catch (TimeoutRuntimeException e)
@@ -153,7 +160,7 @@
// Scenario 4: 1 has WO, 2 has R, 2 requests WO -> fail
try
{
- lockingManager.lock(LockType.OPTION, 2, keys, 100); // Must fail
+ lockingManager.lock(2, keys, LockType.OPTION, 1, 100, null, null); // Must fail
fail("Should have thrown an exception");
}
catch (TimeoutRuntimeException e)
@@ -161,10 +168,10 @@
}
// Scenario 5: 1 has WO, 2 has nothing, 2 requests WO -> fail
- lockingManager.unlock(LockType.READ, 2, keys);
+ lockingManager.unlock(2, keys, LockType.READ, 1, null, null);
try
{
- lockingManager.lock(LockType.OPTION, 2, keys, 100); // Must fail
+ lockingManager.lock(2, keys, LockType.OPTION, 1, 100, null, null); // Must fail
fail("Should have thrown an exception");
}
catch (TimeoutRuntimeException e)
@@ -172,11 +179,11 @@
}
// Scenario 6: 1 has W, 2 has nothing, 2 requests WO -> fail
- lockingManager.unlock(LockType.OPTION, 1, keys);
- lockingManager.lock(LockType.WRITE, 1, keys, 100);
+ lockingManager.unlock(1, keys, LockType.OPTION, 1, null, null);
+ lockingManager.lock(1, keys, LockType.WRITE, 1, 100, null, null);
try
{
- lockingManager.lock(LockType.OPTION, 2, keys, 100); // Must fail
+ lockingManager.lock(2, keys, LockType.OPTION, 1, 100, null, null); // Must fail
fail("Should have thrown an exception");
}
catch (TimeoutRuntimeException e)
@@ -186,7 +193,7 @@
// Scenario 7: 1 has W, 1 request WO -> succeed
try
{
- lockingManager.lock(LockType.OPTION, 1, keys, 100); // Must succeed
+ lockingManager.lock(1, keys, LockType.OPTION, 1, 100, null, null); // Must succeed
}
catch (TimeoutRuntimeException e)
{
@@ -194,11 +201,11 @@
}
// Scenario 8: 1 has W, 2 has R, 1 request WO -> succeed
- lockingManager.unlock(LockType.OPTION, 1, keys);
- lockingManager.lock(LockType.READ, 1, keys, 100);
+ lockingManager.unlock(1, keys, LockType.OPTION, 1, null, null);
+ lockingManager.lock(1, keys, LockType.READ, 1, 100, null, null);
try
{
- lockingManager.lock(LockType.OPTION, 1, keys, 100); // Must succeed
+ lockingManager.lock(1, keys, LockType.OPTION, 1, 100, null, null); // Must succeed
}
catch (TimeoutRuntimeException e)
{
@@ -219,7 +226,7 @@
keys.add(1);
try
{
- lockingManager.lock(LockType.WRITE, 1, keys, 50000);
+ lockingManager.lock(1, keys, LockType.WRITE, 1, 50000, null, null);
}
catch (InterruptedException ex)
{
@@ -236,7 +243,7 @@
keys.add(4);
msg("Context 1 have readlock 1,2,3,4");
- lockingManager.lock(LockType.READ, 1, keys, 1000);
+ lockingManager.lock(1, keys, LockType.READ, 1, 1000, null, null);
assertEquals(true, lockingManager.hasLock(LockType.READ, 1, 1));
assertEquals(true, lockingManager.hasLock(LockType.READ, 1, 2));
assertEquals(true, lockingManager.hasLock(LockType.READ, 1, 3));
@@ -248,7 +255,7 @@
keys.add(3);
msg("Context 2 have readlock 1,2,3");
- lockingManager.lock(LockType.READ, 2, keys, 1000);
+ lockingManager.lock(2, keys, LockType.READ, 1, 1000, null, null);
assertEquals(true, lockingManager.hasLock(LockType.READ, 2, 1));
assertEquals(true, lockingManager.hasLock(LockType.READ, 2, 2));
assertEquals(true, lockingManager.hasLock(LockType.READ, 2, 3));
@@ -259,7 +266,7 @@
keys.add(4);
msg("Context 1 have readlock 1,2,3,4 and writeLock 4");
- lockingManager.lock(LockType.WRITE, 1, keys, 1000);
+ lockingManager.lock(1, keys, LockType.WRITE, 1, 1000, null, null);
assertEquals(true, lockingManager.hasLock(LockType.READ, 1, 4));
assertEquals(true, lockingManager.hasLock(LockType.WRITE, 1, 4));
@@ -268,7 +275,7 @@
try
{
- lockingManager.lock(LockType.WRITE, 1, keys, 1000);
+ lockingManager.lock(1, keys, LockType.WRITE, 1, 1000, null, null);
fail("Should not have exception");
}
catch (RuntimeException expected)
@@ -284,7 +291,7 @@
keys.add(1);
keys.add(2);
keys.add(3);
- lockingManager.unlock(LockType.READ, 2, keys);
+ lockingManager.unlock(2, keys, LockType.READ, 1, null, null);
new PollingTimeOuter()
{
@@ -301,11 +308,11 @@
RWOLockManager<Integer, Integer> lockingManager = new RWOLockManager<>();
Set<Integer> keys = new HashSet<>();
keys.add(1);
- lockingManager.lock(LockType.READ, 1, keys, 10000);
- lockingManager.unlock(LockType.READ, 1, keys);
+ lockingManager.lock(1, keys, LockType.READ, 1, 10000, null, null);
+ lockingManager.unlock(1, keys, LockType.READ, 1, null, null);
// As of 4.4 should not fail anymore.
- lockingManager.unlock(LockType.READ, 1, keys);
+ lockingManager.unlock(1, keys, LockType.READ, 1, null, null);
}
public void testReadTimeout() throws Exception
@@ -463,7 +470,7 @@
CDOObject cdoCompany = CDOUtil.getCDOObject(company);
CDOObject cdoCompany2 = CDOUtil.getCDOObject(company2);
- transaction.lockObjects(Collections.singletonList(cdoCompany), LockType.WRITE, CDOLock.WAIT);
+ transaction.lockObjects(Collections.singletonList(cdoCompany), LockType.WRITE, CDOLock.NO_TIMEOUT);
try
{
@@ -1171,7 +1178,7 @@
objects.add(CDOUtil.getCDOObject(category));
}
- public void _testLockContention() throws Exception
+ public void testLockContention() throws Exception
{
Company company1 = getModel1Factory().createCompany();
@@ -1227,12 +1234,155 @@
CDOLockStateCache lockStateCache2 = ((InternalCDOSession)session2).getLockStateCache();
CDOLockState lockState = lockStateCache2.getLockState(mainBranch, id);
CDOLockOwner expectedLockOwner = transaction2.getLockOwner();
- assertEquals("1", expectedLockOwner, lockState.getWriteLockOwner());
+ assertEquals(expectedLockOwner, lockState.getWriteLockOwner());
sleep(200);
- assertEquals("2", expectedLockOwner, lockState.getWriteLockOwner());
+ assertEquals(expectedLockOwner, lockState.getWriteLockOwner());
+ }
- System.out.println();
+ public void testLockContentionRecursive() throws Exception
+ {
+ Company company21 = getModel1Factory().createCompany();
+
+ Supplier supplier21 = getModel1Factory().createSupplier();
+ company21.getSuppliers().add(supplier21);
+
+ Customer customer21 = getModel1Factory().createCustomer();
+ company21.getCustomers().add(customer21);
+
+ Category category21 = getModel1Factory().createCategory();
+ category21.getCategories().add(getModel1Factory().createCategory());
+ category21.getCategories().add(getModel1Factory().createCategory());
+ category21.getCategories().add(getModel1Factory().createCategory());
+ category21.getCategories().add(getModel1Factory().createCategory());
+ company21.getCategories().add(category21);
+
+ CDOSession session2 = openSession();
+ CDOTransaction transaction21 = session2.openTransaction();
+ transaction21.options().setLockNotificationEnabled(true);
+
+ CDOResource resource21 = transaction21.createResource(getResourcePath("/res1"));
+ resource21.getContents().add(company21);
+ transaction21.commit();
+
+ @SuppressWarnings("unused")
+ Set<Object> objects21 = loadView(transaction21);
+ CDOView view22 = openAndLoadView(session2);
+
+ CDOSession session3 = openSession();
+ CDOTransaction transaction31 = session3.openTransaction();
+ transaction31.options().setLockNotificationEnabled(true);
+ Company company31 = (Company)transaction31.getResource(getResourcePath("/res1")).getContents().get(0);
+ Category category31 = company31.getCategories().get(0);
+
+ @SuppressWarnings("unused")
+ Set<Object> objects31 = loadView(transaction31);
+ CDOView view32 = openAndLoadView(session3);
+
+ System.out.println(transaction21.getLockOwner() + " locking " + category21);
+ transaction21.lockObjects(CDOUtil.getCDOObjects(category21), LockType.WRITE, DEFAULT_TIMEOUT, true);
+ assertRecursiveWriteLock(transaction21.getLockOwner(), category21);
+
+ sleep(500); // Wait until all other views must have been notified.
+ assertRecursiveWriteLock(transaction21.getLockOwner(), view22.getObject(category21));
+ assertRecursiveWriteLock(transaction21.getLockOwner(), category31);
+ assertRecursiveWriteLock(transaction21.getLockOwner(), view32.getObject(category31));
+
+ Throwable[] exception = { null };
+ Thread client3 = new Thread("Client 3")
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ System.out.println(transaction21.getLockOwner() + " locking " + company31);
+ transaction31.lockObjects(CDOUtil.getCDOObjects(company31), LockType.WRITE, DEFAULT_TIMEOUT, true);
+ assertRecursiveWriteLock(transaction31.getLockOwner(), company31);
+
+ sleep(500); // Wait until all other views must have been notified.
+ assertRecursiveWriteLock(transaction31.getLockOwner(), view32.getObject(company31));
+ assertRecursiveWriteLock(transaction31.getLockOwner(), company21);
+ assertRecursiveWriteLock(transaction31.getLockOwner(), view22.getObject(company21));
+ }
+ catch (Throwable ex)
+ {
+ exception[0] = ex;
+ }
+ }
+ };
+
+ client3.start();
+ sleep(100); // Wait until client3 must have called lock().
+
+ // Unblock client3.
+ System.out.println(transaction21.getLockOwner() + " unlocking " + category21);
+ transaction21.unlockObjects(CDOUtil.getCDOObjects(category21), LockType.WRITE, true);
+ client3.join(DEFAULT_TIMEOUT);
+
+ if (exception[0] instanceof Error)
+ {
+ throw (Error)exception[0];
+ }
+
+ if (exception[0] instanceof Exception)
+ {
+ throw (Exception)exception[0];
+ }
+ }
+
+ private static CDOView openAndLoadView(CDOSession session)
+ {
+ CDOView view = session.openView();
+ view.options().setLockNotificationEnabled(true);
+
+ Set<Object> objects = loadView(view);
+ view.properties().put("objects", objects);
+
+ return view;
+ }
+
+ private static Set<Object> loadView(CDOView view)
+ {
+ Set<Object> objects = new HashSet<>();
+
+ CDOResource rootResource = view.getRootResource();
+ objects.add(rootResource);
+
+ for (Iterator<?> it = rootResource.eAllContents(); it.hasNext();)
+ {
+ objects.add(it.next());
+ }
+
+ return objects;
+ }
+
+ protected static void assertRecursiveWriteLock(CDOLockOwner owner, EObject object)
+ {
+ CDOObject cdoObject = CDOUtil.getCDOObject(object);
+ CDOLockOwner objectLockOwner = cdoObject.cdoView().getLockOwner();
+ assertRecursiveWriteLock(owner, objectLockOwner, cdoObject);
+
+ for (Iterator<?> it = cdoObject.eAllContents(); it.hasNext();)
+ {
+ CDOObject o = CDOUtil.getCDOObject((EObject)it.next());
+ assertRecursiveWriteLock(owner, objectLockOwner, o);
+ }
+ }
+
+ private static void assertRecursiveWriteLock(CDOLockOwner owner, CDOLockOwner objectLockOwner, CDOObject cdoObject)
+ {
+ CDOLock lock = cdoObject.cdoWriteLock();
+ assertEquals("owner of " + cdoObject, owner, CollectionUtil.first(lock.getOwners()));
+
+ if (objectLockOwner == owner)
+ {
+ assertEquals("isLocked of " + cdoObject, true, lock.isLocked());
+ }
+ else
+ {
+ assertEquals("isLockedByOthers of " + cdoObject, true, lock.isLockedByOthers());
+ }
}
public void testRecursiveLock() throws Exception
@@ -1548,23 +1698,25 @@
public void testLockRefreshForHeldLock() throws Exception
{
// Client 1 creates and read-locks a resource.
- CDOTransaction tx1 = openSession().openTransaction();
+ CDOSession session1 = openSession();
+ CDOTransaction tx1 = session1.openTransaction();
CDOResource resource1 = tx1.createResource(getResourcePath("/res1"));
tx1.commit();
resource1.cdoReadLock().lock();
- // Client 2 gets the resource created and read-locked by Client 1.
- CDOTransaction tx2 = openSession().openTransaction();
+ // Client 2 loads the resource created and read-locked by Client 1.
+ CDOSession session2 = openSession();
+ CDOTransaction tx2 = session2.openTransaction();
CDOResource resource2 = tx2.getResource(getResourcePath("/res1"));
- // Get the lock and lock it.
+ // Client 2 gets the lock and locks it.
CDOLock readLockBeforeClose = resource2.cdoReadLock();
readLockBeforeClose.lock(DEFAULT_TIMEOUT);
boolean isLockedByOthersBeforeClose = readLockBeforeClose.isLockedByOthers();
assertTrue(isLockedByOthersBeforeClose);
- tx1.close(); // Client 1 release read lock.
+ tx1.close(); // Client 1 releases its read lock.
new PollingTimeOuter()
{
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java
index b8469c2..ddb1862 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java
@@ -14,9 +14,8 @@
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
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.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.session.CDOSession;
@@ -31,58 +30,55 @@
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.tests.TestListener2;
-import java.util.List;
+import java.util.Collections;
/**
* @author Caspar De Groot
*/
public class LockingNotificationsTest extends AbstractLockingTest
{
- /**
- * FIXME Disabled until bug 358603 is addressed.
- */
- public void _testSameBranchDifferentSession_explicitRelease() throws Exception
+ public void testSameBranchDifferentSession_WithoutAutoRelease() throws Exception
{
- sameBranchDifferentSession(LockReleaseMode.EXPLICIT);
+ sameBranchDifferentSession(false);
}
- public void testSameBranchDifferentSession_autoRelease() throws Exception
+ public void testSameBranchDifferentSession_WithAutoRelease() throws Exception
{
- sameBranchDifferentSession(LockReleaseMode.AUTO);
+ sameBranchDifferentSession(true);
}
- public void testSameBranchSameSession_explicitRelease() throws Exception
+ public void testSameBranchSameSession_WithoutAutoRelease() throws Exception
{
- sameBranchSameSession(LockReleaseMode.EXPLICIT);
+ sameBranchSameSession(false);
}
- public void testSameBranchSameSession_autoRelease() throws Exception
+ public void testSameBranchSameSession_WithAutoRelease() throws Exception
{
- sameBranchSameSession(LockReleaseMode.AUTO);
+ sameBranchSameSession(true);
}
@Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
public void testDifferentBranchDifferentSession() throws Exception
{
- differentBranchDifferentSession(LockReleaseMode.EXPLICIT);
+ differentBranchDifferentSession(false);
}
@Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
- public void testDifferentBranchDifferentSession_autoRelease() throws Exception
+ public void testDifferentBranchDifferentSession_WithAutoRelease() throws Exception
{
- differentBranchDifferentSession(LockReleaseMode.AUTO);
+ differentBranchDifferentSession(true);
}
@Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
public void testDifferentBranchSameSession() throws Exception
{
- differentBranchSameSession(LockReleaseMode.EXPLICIT);
+ differentBranchSameSession(false);
}
@Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
- public void testDifferentBranchSameSession_autoRelease() throws Exception
+ public void testDifferentBranchSameSession_WithAutoRelease() throws Exception
{
- differentBranchSameSession(LockReleaseMode.AUTO);
+ differentBranchSameSession(true);
}
public void testEnableDisableNotifications() throws Exception
@@ -90,13 +86,13 @@
CDOSession session1 = openSession();
CDOSession session2 = openSession();
CDOView controlView = session2.openView();
- withExplicitRelease(session1, controlView, false);
+ withoutAutoRelease(session1, controlView, false);
controlView.options().setLockNotificationEnabled(true);
- withExplicitRelease(session1, controlView, true);
+ withoutAutoRelease(session1, controlView, true);
controlView.options().setLockNotificationEnabled(false);
- withExplicitRelease(session1, controlView, false);
+ withoutAutoRelease(session1, controlView, false);
session1.close();
session2.close();
@@ -106,13 +102,13 @@
{
CDOSession session1 = openSession();
CDOView controlView = session1.openView();
- withExplicitRelease(session1, controlView, false);
+ withoutAutoRelease(session1, controlView, false);
controlView.options().setLockNotificationEnabled(true);
- withExplicitRelease(session1, controlView, true);
+ withoutAutoRelease(session1, controlView, true);
controlView.options().setLockNotificationEnabled(false);
- withExplicitRelease(session1, controlView, false);
+ withoutAutoRelease(session1, controlView, false);
session1.close();
}
@@ -188,7 +184,7 @@
resource.getContents().add(company);
assertNew(company, transaction);
- TestListener2 listener = new TestListener2(CDOViewLocksChangedEvent.class);
+ TestListener2 listener = new TestListener2(CDOViewLocksChangedEvent.class).dump(true, false);
transaction.addListener(listener);
lockWrite(company);
@@ -210,43 +206,43 @@
return view;
}
- private void sameBranchDifferentSession(LockReleaseMode mode) throws Exception
+ private void sameBranchDifferentSession(boolean autoRelease) throws Exception
{
CDOSession session = openSession();
CDOSession controlSession = openSession();
CDOView controlView = openViewWithLockNotifications(controlSession, null);
- if (mode == LockReleaseMode.EXPLICIT)
- {
- withExplicitRelease(session, controlView, true);
- }
- else if (mode == LockReleaseMode.AUTO)
+ if (autoRelease)
{
withAutoRelease(session, controlView, true);
}
+ else
+ {
+ withoutAutoRelease(session, controlView, true);
+ }
controlSession.close();
session.close();
}
- private void sameBranchSameSession(LockReleaseMode mode) throws Exception
+ private void sameBranchSameSession(boolean autoRelease) throws Exception
{
CDOSession session = openSession();
CDOView controlView = openViewWithLockNotifications(session, null);
- if (mode == LockReleaseMode.EXPLICIT)
- {
- withExplicitRelease(session, controlView, true);
- }
- else if (mode == LockReleaseMode.AUTO)
+ if (autoRelease)
{
withAutoRelease(session, controlView, true);
}
+ else
+ {
+ withoutAutoRelease(session, controlView, true);
+ }
session.close();
}
- private void differentBranchDifferentSession(LockReleaseMode mode) throws Exception
+ private void differentBranchDifferentSession(boolean autoRelease) throws Exception
{
CDOSession session = openSession();
CDOBranch subBranch = session.getBranchManager().getMainBranch().createBranch("sub1");
@@ -254,54 +250,56 @@
CDOSession controlSession = openSession();
CDOView controlView = openViewWithLockNotifications(controlSession, subBranch);
- if (mode == LockReleaseMode.EXPLICIT)
- {
- withExplicitRelease(session, controlView, false);
- }
- else if (mode == LockReleaseMode.AUTO)
+ if (autoRelease)
{
withAutoRelease(session, controlView, false);
}
+ else
+ {
+ withoutAutoRelease(session, controlView, false);
+ }
controlSession.close();
session.close();
}
- private void differentBranchSameSession(LockReleaseMode mode) throws Exception
+ private void differentBranchSameSession(boolean autoRelease) throws Exception
{
CDOSession session = openSession();
CDOBranch subBranch = session.getBranchManager().getMainBranch().createBranch("sub2");
CDOView controlView = openViewWithLockNotifications(session, subBranch);
- if (mode == LockReleaseMode.EXPLICIT)
- {
- withExplicitRelease(session, controlView, false);
- }
- else if (mode == LockReleaseMode.AUTO)
+ if (autoRelease)
{
withAutoRelease(session, controlView, false);
}
+ else
+ {
+ withoutAutoRelease(session, controlView, false);
+ }
session.close();
}
- private void withExplicitRelease(CDOSession session1, CDOView controlView, boolean mustReceiveNotifications) throws Exception
+ private void withoutAutoRelease(CDOSession session, CDOView controlView, boolean sameBranch) throws Exception
{
- TestListener2 controlViewListener = new TestListener2(CDOViewLocksChangedEvent.class).dump(true, true);
+ TestListener2 controlViewListener = new TestListener2(CDOViewLocksChangedEvent.class).dump(true, false);
controlView.addListener(controlViewListener);
- CDOTransaction transaction1 = session1.openTransaction();
- CDOResource res1 = transaction1.getOrCreateResource(getResourcePath("r1"));
- TestListener2 transactionListener = new TestListener2(CDOViewLocksChangedEvent.class);
- transaction1.addListener(transactionListener);
- res1.getContents().clear();
+ CDOTransaction transaction = session.openTransaction();
+ transaction.options().setAutoReleaseLocksEnabled(false);
+
+ CDOResource resource = transaction.getOrCreateResource(getResourcePath("r1"));
+ TestListener2 transactionListener = new TestListener2(CDOViewLocksChangedEvent.class).dump(true, false);
+ transaction.addListener(transactionListener);
+ resource.getContents().clear();
Company company = getModel1Factory().createCompany();
- res1.getContents().add(company);
- transaction1.commit();
+ resource.getContents().add(company);
+ transaction.commit();
CDOObject cdoCompany = CDOUtil.getCDOObject(company);
CDOObject cdoCompanyInControlView = null;
- if (mustReceiveNotifications)
+ if (sameBranch)
{
cdoCompanyInControlView = controlView.getObject(cdoCompany.cdoID());
}
@@ -311,124 +309,128 @@
cdoCompany.cdoWriteLock().lock();
waitForActiveLockNotifications();
- if (mustReceiveNotifications)
+ if (sameBranch)
{
IEvent[] events = controlViewListener.waitFor(1);
assertEquals(1, events.length);
CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
- assertLockOwner(transaction1, event.getLockOwner());
+ assertLockOwner(transaction, event.getLockOwner());
- List<CDOLockState> lockStates = event.getNewLockStates();
- assertEquals(1, lockStates.size());
- assertLockedObject(cdoCompany, lockStates.get(0));
- assertLockOwner(transaction1, lockStates.get(0).getWriteLockOwner());
- assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates.get(0));
+ CDOLockDelta[] lockDeltas = event.getLockDeltas();
+ assertEquals(1, lockDeltas.length);
+ assertLockedObject(cdoCompany, lockDeltas[0]);
+ assertLockOwner(transaction, lockDeltas[0].getNewOwner());
+ assertEquals(cdoCompanyInControlView.cdoLockState(), event.getLockStates()[0]);
+ }
+ else
+ {
+ sleep(100);
+ assertEquals(0, controlViewListener.getEvents().size());
}
+ controlViewListener.clearEvents();
cdoCompany.cdoWriteLock().unlock();
waitForActiveLockNotifications();
- if (mustReceiveNotifications)
+ if (sameBranch)
{
- IEvent[] events = controlViewListener.waitFor(2);
- assertEquals(2, events.length);
+ IEvent[] events = controlViewListener.waitFor(1);
+ assertEquals(1, events.length);
- CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(1);
- assertLockOwner(transaction1, event.getLockOwner());
+ CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
+ assertLockOwner(transaction, event.getLockOwner());
- List<CDOLockState> lockStates = event.getNewLockStates();
- assertEquals(1, lockStates.size());
- assertLockedObject(cdoCompany, lockStates.get(0));
- assertNull(lockStates.get(0).getWriteLockOwner());
- assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates.get(0));
+ CDOLockDelta[] lockDeltas = event.getLockDeltas();
+ assertEquals(1, lockDeltas.length);
+ assertLockedObject(cdoCompany, lockDeltas[0]);
+ assertLockOwner(transaction, lockDeltas[0].getOldOwner());
+ assertEquals(cdoCompanyInControlView.cdoLockState(), event.getLockStates()[0]);
}
/* Test read lock */
+ controlViewListener.clearEvents();
cdoCompany.cdoReadLock().lock();
waitForActiveLockNotifications();
- if (mustReceiveNotifications)
+
+ if (sameBranch)
{
- IEvent[] events = controlViewListener.waitFor(3);
- assertEquals(3, events.length);
+ IEvent[] events = controlViewListener.waitFor(1);
+ assertEquals(1, events.length);
- CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(2);
- assertLockOwner(transaction1, event.getLockOwner());
+ CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
+ assertLockOwner(transaction, event.getLockOwner());
- List<CDOLockState> lockStates = event.getNewLockStates();
- assertEquals(1, lockStates.size());
- assertLockedObject(cdoCompany, lockStates.get(0));
- assertEquals(1, lockStates.get(0).getReadLockOwners().size());
- CDOLockOwner tx1Lo = CDOLockUtil.createLockOwner(transaction1);
- assertEquals(true, lockStates.get(0).getReadLockOwners().contains(tx1Lo));
- assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates.get(0));
+ CDOLockDelta[] lockDeltas = event.getLockDeltas();
+ assertEquals(1, lockDeltas.length);
+ assertLockedObject(cdoCompany, lockDeltas[0]);
+ assertLockOwner(transaction, lockDeltas[0].getNewOwner());
+ assertEquals(cdoCompanyInControlView.cdoLockState(), event.getLockStates()[0]);
}
+ controlViewListener.clearEvents();
cdoCompany.cdoReadLock().unlock();
waitForActiveLockNotifications();
- if (mustReceiveNotifications)
+
+ if (sameBranch)
{
- IEvent[] events = controlViewListener.waitFor(4);
- assertEquals(4, events.length);
+ IEvent[] events = controlViewListener.waitFor(1);
+ assertEquals(1, events.length);
- CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(3);
- assertLockOwner(transaction1, event.getLockOwner());
+ CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
+ assertLockOwner(transaction, event.getLockOwner());
- List<CDOLockState> lockStates = event.getNewLockStates();
- assertEquals(1, lockStates.size());
- assertEquals(0, lockStates.get(0).getReadLockOwners().size());
- assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates.get(0));
+ CDOLockDelta[] lockDeltas = event.getLockDeltas();
+ assertEquals(1, lockDeltas.length);
+ assertLockOwner(transaction, lockDeltas[0].getOldOwner());
+ assertEquals(cdoCompanyInControlView.cdoLockState(), event.getLockStates()[0]);
}
/* Test write option */
+ controlViewListener.clearEvents();
cdoCompany.cdoWriteOption().lock();
waitForActiveLockNotifications();
- if (mustReceiveNotifications)
+
+ if (sameBranch)
{
- IEvent[] events = controlViewListener.waitFor(5);
- assertEquals(5, events.length);
+ IEvent[] events = controlViewListener.waitFor(1);
+ assertEquals(1, events.length);
- CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(4);
- assertLockOwner(transaction1, event.getLockOwner());
+ CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
+ assertLockOwner(transaction, event.getLockOwner());
- List<CDOLockState> lockStates = event.getNewLockStates();
- assertEquals(1, lockStates.size());
- assertLockedObject(cdoCompany, lockStates.get(0));
- assertLockOwner(transaction1, lockStates.get(0).getWriteOptionOwner());
- assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates.get(0));
+ CDOLockDelta[] lockDeltas = event.getLockDeltas();
+ assertEquals(1, lockDeltas.length);
+ assertLockedObject(cdoCompany, lockDeltas[0]);
+ assertLockOwner(transaction, lockDeltas[0].getNewOwner());
+ assertEquals(cdoCompanyInControlView.cdoLockState(), event.getLockStates()[0]);
}
+ controlViewListener.clearEvents();
cdoCompany.cdoWriteOption().unlock();
waitForActiveLockNotifications();
- if (mustReceiveNotifications)
+
+ if (sameBranch)
{
- IEvent[] events = controlViewListener.waitFor(6);
- assertEquals(6, events.length);
+ IEvent[] events = controlViewListener.waitFor(1);
+ assertEquals(1, events.length);
- CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(5);
- assertLockOwner(transaction1, event.getLockOwner());
+ CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
+ assertLockOwner(transaction, event.getLockOwner());
- List<CDOLockState> lockStates = event.getNewLockStates();
- assertEquals(1, lockStates.size());
- assertLockedObject(cdoCompany, lockStates.get(0));
- assertNull(lockStates.get(0).getWriteOptionOwner());
- assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates.get(0));
- }
-
- List<IEvent> events = transactionListener.getEvents();
- assertEquals(6, events.size());
-
- if (!mustReceiveNotifications)
- {
- assertEquals(0, controlViewListener.getEvents().size());
+ CDOLockDelta[] lockDeltas = event.getLockDeltas();
+ assertEquals(1, lockDeltas.length);
+ assertLockedObject(cdoCompany, lockDeltas[0]);
+ assertLockOwner(transaction, lockDeltas[0].getOldOwner());
+ assertEquals(cdoCompanyInControlView.cdoLockState(), event.getLockStates()[0]);
}
}
- private void withAutoRelease(CDOSession session, CDOView controlView, boolean mustReceiveNotifications) throws Exception
+ private void withAutoRelease(CDOSession session, CDOView controlView, boolean sameBranch) throws Exception
{
- TestListener2 controlViewListener = new TestListener2(CDOViewLocksChangedEvent.class);
+ TestListener2 controlViewListener = new TestListener2(CDOViewLocksChangedEvent.class).dump(true, true);
controlView.addListener(controlViewListener);
CDOTransaction transaction = session.openTransaction();
@@ -441,48 +443,69 @@
resource.getContents().add(company);
transaction.commit();
- implicitRelease(company, LockType.WRITE, transaction, controlViewListener, mustReceiveNotifications);
- implicitRelease(company, LockType.READ, transaction, controlViewListener, mustReceiveNotifications);
- implicitRelease(company, LockType.OPTION, transaction, controlViewListener, mustReceiveNotifications);
+ withAutoRelease(company, LockType.READ, transaction, controlViewListener, sameBranch);
+ withAutoRelease(company, LockType.WRITE, transaction, controlViewListener, sameBranch);
+ withAutoRelease(company, LockType.OPTION, transaction, controlViewListener, sameBranch);
}
- private void implicitRelease(Company company, LockType type, CDOTransaction transaction, TestListener2 controlViewListener, boolean mustReceiveNotifications)
+ private void withAutoRelease(Company company, LockType lockType, CDOTransaction transaction, TestListener2 controlViewListener, boolean sameBranch)
throws Exception
{
CDOViewLocksChangedEvent event;
CDOObject cdoCompany = CDOUtil.getCDOObject(company);
-
company.setName(company.getName() + "x"); // Make object DIRTY.
- cdoCompany.cdoWriteLock().lock();
+
+ switch (lockType)
+ {
+ case READ:
+ cdoCompany.cdoReadLock().lock();
+ break;
+
+ case WRITE:
+ cdoCompany.cdoWriteLock().lock();
+ break;
+
+ case OPTION:
+ cdoCompany.cdoWriteOption().lock();
+ break;
+ }
+
+ controlViewListener.clearEvents();
waitForActiveLockNotifications();
- if (mustReceiveNotifications)
+ if (sameBranch)
{
controlViewListener.waitFor(1);
event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
- assertEquals(Operation.LOCK, event.getOperation());
- assertEquals(LockType.WRITE, event.getLockType());
- }
-
- transaction.commit();
-
- if (mustReceiveNotifications)
- {
- controlViewListener.waitFor(2);
- event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(1);
- assertEquals(Operation.UNLOCK, event.getOperation());
- assertNull(event.getLockType());
+ assertEquals(Collections.singleton(Operation.LOCK), event.getOperations());
+ assertEquals(Collections.singleton(lockType), event.getLockTypes());
}
else
{
- sleep(1000);
+ sleep(100);
+ assertEquals(0, controlViewListener.getEvents().size());
+ }
+
+ controlViewListener.clearEvents();
+ transaction.commit();
+
+ if (sameBranch)
+ {
+ controlViewListener.waitFor(1);
+ event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
+ assertEquals(Collections.singleton(Operation.UNLOCK), event.getOperations());
+ assertEquals(Collections.singleton(lockType), event.getLockTypes());
+ }
+ else
+ {
+ sleep(100);
assertEquals(0, controlViewListener.getEvents().size());
}
}
- public static void assertLockedObject(CDOObject expected, CDOLockState actual)
+ public static void assertLockedObject(CDOObject expected, CDOLockDelta actual)
{
- Object lockedObject = actual.getLockedObject();
+ Object lockedObject = actual.getTarget();
if (lockedObject instanceof CDOIDAndBranch)
{
CDOIDAndBranch idAndBranch = (CDOIDAndBranch)lockedObject;
@@ -497,15 +520,6 @@
public static void assertLockOwner(CDOView expected, CDOLockOwner actual)
{
- CDOLockOwner lockOwner = CDOLockUtil.createLockOwner(expected);
- assertEquals(lockOwner, actual);
- }
-
- /**
- * @author Caspar De Groot
- */
- private static enum LockReleaseMode
- {
- EXPLICIT, AUTO
+ assertEquals(expected.getLockOwner(), actual);
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingSequenceTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingSequenceTest.java
index 4c0ffb8..5bdca87 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingSequenceTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingSequenceTest.java
@@ -11,6 +11,7 @@
package org.eclipse.emf.cdo.tests;
import org.eclipse.emf.cdo.CDOLock;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.tests.model1.SalesOrder;
@@ -50,20 +51,22 @@
public void testSafeCounter() throws Exception
{
disableConsole();
- final SalesOrder sequence = getModel1Factory().createSalesOrder();
+ SalesOrder sequence = getModel1Factory().createSalesOrder();
+ sequence.setId(-1);
- final CDOSession session = openSession();
+ CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/res1"));
resource.getContents().add(sequence);
transaction.commit();
- CountDownLatch latch = new CountDownLatch(USERS);
User[] users = new User[USERS];
+ CountDownLatch latch = new CountDownLatch(USERS);
+ CDOLockOwner[] allocators = new CDOLockOwner[USERS * ALLOCATIONS];
for (int userID = 0; userID < USERS; userID++)
{
- users[userID] = new User(userID, latch, sequence);
+ users[userID] = new User(latch, allocators, session.openTransaction(), sequence);
}
for (int userID = 0; userID < USERS; userID++)
@@ -100,17 +103,20 @@
{
private final CountDownLatch latch;
+ private final CDOLockOwner[] allocators;
+
private final CDOTransaction transaction;
private final SalesOrder sequence;
private Exception exception;
- public User(int userID, CountDownLatch latch, SalesOrder sequence)
+ public User(CountDownLatch latch, CDOLockOwner[] allocators, CDOTransaction transaction, SalesOrder sequence)
{
- super("User" + userID);
+ super(transaction.getLockOwner().toString());
this.latch = latch;
- transaction = CDOUtil.getCDOObject(sequence).cdoView().getSession().openTransaction();
+ this.allocators = allocators;
+ this.transaction = transaction;
this.sequence = transaction.getObject(sequence);
}
@@ -127,7 +133,7 @@
CDOLock lock = CDOUtil.getCDOObject(sequence).cdoWriteLock();
for (int allocation = 0; allocation < ALLOCATIONS; allocation++)
{
- for (int retry = 0; retry < RETRIES; retry++)
+ for (int retry = RETRIES; retry >= 0; --retry)
{
try
{
@@ -136,7 +142,7 @@
}
catch (TimeoutException ex)
{
- if (retry == RETRIES)
+ if (retry == 0)
{
exception = ex;
return;
@@ -146,14 +152,21 @@
}
}
- int id = sequence.getId() + 1;
- sequence.setId(id);
- msg("Allocated " + id);
-
try
{
+ int id = sequence.getId() + 1;
+ if (allocators[id] != null)
+ {
+ throw new IllegalStateException(id + " already allocated by " + allocators[id]);
+ }
+
+ allocators[id] = transaction.getLockOwner();
+ sequence.setId(id);
+ msg("Allocated " + id);
+
transaction.commit();
- yield();
+ msg("Committed");
+ // yield();
}
catch (Exception ex)
{
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_321986_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_321986_Test.java
index 08b0e47..f28546d 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_321986_Test.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_321986_Test.java
@@ -29,27 +29,26 @@
public void testRollback() throws CommitException
{
CDOSession session1 = openSession();
- CDOTransaction tx1 = session1.openTransaction();
+ CDOTransaction transaction1 = session1.openTransaction();
- CDOResource resource1 = tx1.createResource(getResourcePath("test"));
+ CDOResource resource1 = transaction1.createResource(getResourcePath("test"));
Address address = getModel1Factory().createAddress();
resource1.getContents().add(address);
- tx1.commit();
+ transaction1.commit();
CDOObject cdoAddress = CDOUtil.getCDOObject(address);
cdoAddress.cdoWriteLock().lock();
- msg("Address: " + cdoAddress.cdoID());
-
CDOSession session2 = openSession();
- CDOTransaction tx2 = session2.openTransaction();
- CDOResource resource2 = tx2.getResource(getResourcePath("test"));
+ CDOTransaction transaction2 = session2.openTransaction();
+ transaction2.options().setOptimisticLockingTimeout(200);
+ CDOResource resource2 = transaction2.getResource(getResourcePath("test"));
resource2.getContents().clear();
try
{
// We must fail here, because object was locked
- tx2.commit();
+ transaction2.commit();
fail("Commit should have failed");
}
catch (CommitException e)
@@ -59,11 +58,11 @@
// Remove in the 1st transaction
EcoreUtil.delete(address);
- tx1.commit();
+ transaction1.commit();
try
{
- tx2.rollback();
+ transaction2.rollback();
}
catch (Exception ex)
{
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_469301_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_469301_Test.java
index 6c04c70..ca7a262 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_469301_Test.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_469301_Test.java
@@ -12,7 +12,8 @@
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta.Kind;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.eresource.CDOResource;
@@ -33,6 +34,7 @@
import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
import org.eclipse.emf.spi.cdo.InternalCDOView;
+import java.util.Collections;
import java.util.List;
/**
@@ -116,14 +118,21 @@
controlListener.waitFor(1, DEFAULT_TIMEOUT);
CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlListener.getEvents().get(0);
- assertEquals(operation, event.getOperation());
- assertEquals(LockType.WRITE, event.getLockType());
+ assertEquals(Collections.singleton(operation), event.getOperations());
+ assertEquals(Collections.singleton(LockType.WRITE), event.getLockTypes());
assertEquals(lockOwner, event.getLockOwner());
- assertEquals(2, event.getNewLockStates().size());
+ assertEquals(2, event.getLockDeltas().length);
- for (CDOLockState lockState : event.getNewLockStates())
+ for (CDOLockDelta lockDelta : event.getLockDeltas())
{
- assertEquals(event.getOperation() == Operation.LOCK ? lockOwner : null, lockState.getWriteLockOwner());
+ if (lockDelta.getKind() == Kind.ADDED)
+ {
+ assertEquals(lockOwner, lockDelta.getNewOwner());
+ }
+ else
+ {
+ assertEquals(lockOwner, lockDelta.getOldOwner());
+ }
}
controlListener.clearEvents();
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java
index 85d9091..8cb9b55 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java
@@ -27,6 +27,8 @@
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.tests.TestListener2;
+import java.util.Collections;
+
/**
* @author Caspar De Groot
*/
@@ -122,8 +124,8 @@
session1lockListener.waitFor(1);
e = (CDOSessionLocksChangedEvent)session1lockListener.getEvents().get(0);
- assertSame(LockType.WRITE, e.getLockType());
- assertSame(Operation.LOCK, e.getOperation());
+ assertEquals(Collections.singleton(LockType.WRITE), e.getLockTypes());
+ assertEquals(Collections.singleton(Operation.LOCK), e.getOperations());
assertEquals(true, companyA_session1.cdoWriteLock().isLockedByOthers());
// Perform the unlock in session 2, connected to clone 2
@@ -133,8 +135,8 @@
session1lockListener.waitFor(2);
e = (CDOSessionLocksChangedEvent)session1lockListener.getEvents().get(1);
- assertSame(LockType.WRITE, e.getLockType());
- assertSame(Operation.UNLOCK, e.getOperation());
+ assertEquals(Collections.singleton(LockType.WRITE), e.getLockTypes());
+ assertEquals(Collections.singleton(Operation.UNLOCK), e.getOperations());
assertEquals(false, companyA_session1.cdoWriteLock().isLockedByOthers());
// Now vice versa . . .
@@ -148,8 +150,8 @@
session2lockListener.waitFor(1);
e = (CDOSessionLocksChangedEvent)session2lockListener.getEvents().get(0);
- assertSame(LockType.WRITE, e.getLockType());
- assertSame(Operation.LOCK, e.getOperation());
+ assertEquals(Collections.singleton(LockType.WRITE), e.getLockTypes());
+ assertEquals(Collections.singleton(Operation.LOCK), e.getOperations());
assertEquals(true, companyA_session2.cdoWriteLock().isLockedByOthers());
// Perform the unlock in session 1, connected to clone 1
@@ -159,8 +161,8 @@
session2lockListener.waitFor(2);
e = (CDOSessionLocksChangedEvent)session2lockListener.getEvents().get(1);
- assertSame(LockType.WRITE, e.getLockType());
- assertSame(Operation.UNLOCK, e.getOperation());
+ assertEquals(Collections.singleton(LockType.WRITE), e.getLockTypes());
+ assertEquals(Collections.singleton(Operation.UNLOCK), e.getOperations());
assertEquals(false, companyA_session2.cdoWriteLock().isLockedByOthers());
// Now try an unlock-all . . .
diff --git a/plugins/org.eclipse.emf.cdo/.settings/.api_filters b/plugins/org.eclipse.emf.cdo/.settings/.api_filters
index 85a8a56..472390b 100644
--- a/plugins/org.eclipse.emf.cdo/.settings/.api_filters
+++ b/plugins/org.eclipse.emf.cdo/.settings/.api_filters
@@ -862,22 +862,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/emf/internal/cdo/session/CDOLockStateCache.java" type="org.eclipse.emf.internal.cdo.session.CDOLockStateCache$LockState">
- <filter id="571473929">
- <message_arguments>
- <message_argument value="AbstractCDOLockState"/>
- <message_argument value="LockState"/>
- </message_arguments>
- </filter>
- </resource>
- <resource path="src/org/eclipse/emf/internal/cdo/session/CDOLockStateCache.java" type="org.eclipse.emf.internal.cdo.session.CDOLockStateCache$MutableLockState">
- <filter id="574619656">
- <message_arguments>
- <message_argument value="InternalCDOLockState"/>
- <message_argument value="MutableLockState"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/emf/internal/cdo/session/CDOLockStateCacheImpl.java" type="org.eclipse.emf.internal.cdo.session.CDOLockStateCacheImpl$LockState">
<filter id="571473929">
<message_arguments>
@@ -886,14 +870,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/emf/internal/cdo/session/CDOLockStateCacheImpl.java" type="org.eclipse.emf.internal.cdo.session.CDOLockStateCacheImpl$MutableLockState">
- <filter id="574619656">
- <message_arguments>
- <message_argument value="InternalCDOLockState"/>
- <message_argument value="MutableLockState"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java" type="org.eclipse.emf.internal.cdo.session.CDOSessionImpl">
<filter id="574668824">
<message_arguments>
@@ -944,14 +920,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java" type="org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent">
- <filter id="574619656">
- <message_arguments>
- <message_argument value="CDOLockChangeInfo"/>
- <message_argument value="DefaultLocksChangedEvent"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java" type="org.eclipse.emf.internal.cdo.view.AbstractCDOView">
<filter id="574668824">
<message_arguments>
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java
index 369a103..05c5413 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java
@@ -11,11 +11,14 @@
*/
package org.eclipse.emf.cdo;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.net4j.util.concurrent.IRWLockManager;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.IRWOLockManager;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Lock;
@@ -31,9 +34,10 @@
*/
public interface CDOLock extends Lock
{
- public static final int WAIT = IRWLockManager.WAIT;
-
- public static final int NO_WAIT = IRWLockManager.NO_WAIT;
+ /**
+ * @since 4.15
+ */
+ public static final long NO_TIMEOUT = IRWOLockManager.NO_TIMEOUT;
/**
* @since 4.8
@@ -71,4 +75,15 @@
* from the requesting one), <code>false</code> otherwise.
*/
public boolean isLockedByOthers();
+
+ /**
+ * @since 4.15
+ */
+ public Set<CDOLockOwner> getOwners();
+
+ @Deprecated
+ public static final int WAIT = IRWLockManager.WAIT;
+
+ @Deprecated
+ public static final int NO_WAIT = IRWLockManager.NO_WAIT;
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java
index d9cb710..040bbce 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java
@@ -24,6 +24,7 @@
import org.eclipse.emf.cdo.common.commit.CDOChangeSetDataProvider;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.common.util.CDOResourceNodeNotFoundException;
@@ -37,6 +38,7 @@
import org.eclipse.emf.cdo.view.CDOQuery;
import org.eclipse.emf.cdo.view.CDOView;
+import org.eclipse.net4j.util.concurrent.IRWOLockManager;
import org.eclipse.net4j.util.options.IOptionsEvent;
import org.eclipse.emf.common.util.URI;
@@ -331,6 +333,18 @@
public static final long DEFAULT_COMMIT_INFO_TIMEOUT = 60000;
/**
+ * Indicates to use the timeout value that is configured on the server.
+ *
+ * @since 4.15
+ */
+ public static final long DEFAULT_OPTIMISTIC_LOCKING_TIMEOUT = CDOProtocolConstants.DEFAULT_OPTIMISTIC_LOCKING_TIMEOUT;
+
+ /**
+ * @since 4.15
+ */
+ public static final long NO_OPTIMISTIC_LOCKING_TIMEOUT = IRWOLockManager.NO_TIMEOUT;
+
+ /**
* Returns the {@link CDOTransaction transaction} of this options object.
*
* @since 4.0
@@ -494,6 +508,26 @@
public void setAttachedRevisionsMap(Map<CDOID, CDORevision> attachedRevisionsMap);
/**
+ * Returns the number of milliseconds to wait for the successful acquisition of all required implicit locks on the server
+ * when {@link CDOTransaction#commit()} is called.
+ * <p>
+ * Default value is {@link #DEFAULT_OPTIMISTIC_LOCKING_TIMEOUT}.
+ *
+ * @since 4.15
+ */
+ public long getOptimisticLockingTimeout();
+
+ /**
+ * Returns the number of milliseconds to wait for the successful acquisition of all required implicit locks on the server
+ * when {@link CDOTransaction#commit()} is called.
+ * <p>
+ * Default value is {@link #DEFAULT_OPTIMISTIC_LOCKING_TIMEOUT}.
+ *
+ * @since 4.15
+ */
+ public void setOptimisticLockingTimeout(long optimisticLockingTimeout);
+
+ /**
* Returns the number of milliseconds to wait for the transaction update when {@link CDOTransaction#commit()} is called.
* <p>
* Default value is 10000.
@@ -603,6 +637,19 @@
/**
* An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the
+ * {@link Options#setOptimisticLockingTimeout(long) optimistic locking timeout} option has changed.
+ *
+ * @author Eike Stepper
+ * @since 4.15
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+ public interface OptimisticLockingTimeout extends IOptionsEvent
+ {
+ }
+
+ /**
+ * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the
* {@link Options#setCommitInfoTimeout(long) commit info timeout} option has changed.
*
* @author Eike Stepper
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOLockStatePrefetcher.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOLockStatePrefetcher.java
index 73e1b4e..1bc205d 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOLockStatePrefetcher.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOLockStatePrefetcher.java
@@ -11,6 +11,7 @@
package org.eclipse.emf.cdo.view;
import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
@@ -27,12 +28,11 @@
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
+import org.eclipse.emf.spi.cdo.CDOLockStateCache;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
import org.eclipse.emf.spi.cdo.InternalCDOView;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -208,9 +208,9 @@
{
// Direct call the session protocol.
CDOSessionProtocol sessionProtocol = view.getSession().getSessionProtocol();
- CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(view.getBranch().getID(), ids, event.getPrefetchDepth());
+ List<CDOLockState> loadedLockStates = sessionProtocol.getLockStates2(view.getBranch().getID(), ids, event.getPrefetchDepth());
- updateLockStates(Arrays.asList(loadedLockStates), true);
+ updateLockStates(loadedLockStates, true);
// Add missing lock states.
List<CDOLockState> missingLockStates = new ArrayList<>();
@@ -265,11 +265,13 @@
});
}
- private void updateLockStates(Collection<? extends CDOLockState> lockStates, boolean loadOnDemand)
+ private void updateLockStates(List<CDOLockState> lockStates, boolean loadOnDemand)
{
try
{
- view.updateLockStates(lockStates, loadOnDemand, null);
+ CDOBranch branch = view.getBranch();
+ CDOLockStateCache lockStateCache = view.getSession().getLockStateCache();
+ lockStateCache.addLockStates(branch, lockStates, null);
}
catch (Exception ex)
{
@@ -278,39 +280,5 @@
OM.LOG.error(ex);
}
}
-
- if (updateOtherViews)
- {
- for (InternalCDOView otherView : view.getSession().getViews())
- {
- if (asyncUpdate)
- {
- ExecutorService executorService = view.getExecutorService();
- executorService.submit(() -> updateLockStatesForOtherView(lockStates, loadOnDemand, otherView));
- }
- else
- {
- updateLockStatesForOtherView(lockStates, loadOnDemand, otherView);
- }
- }
- }
- }
-
- private void updateLockStatesForOtherView(Collection<? extends CDOLockState> lockStates, boolean loadOnDemand, InternalCDOView otherview)
- {
- try
- {
- if (otherview != view && otherview.isActive() && otherview.getBranch() == view.getBranch())
- {
- otherview.updateLockStates(lockStates, loadOnDemand, null);
- }
- }
- catch (Exception ex)
- {
- if (otherview.isActive())
- {
- OM.LOG.error(ex);
- }
- }
}
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLockImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLockImpl.java
index fde3d4e..93015ab 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLockImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLockImpl.java
@@ -13,6 +13,8 @@
import org.eclipse.emf.cdo.CDOLock;
import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.util.LockTimeoutException;
import org.eclipse.net4j.util.WrappedException;
@@ -23,6 +25,7 @@
import java.text.MessageFormat;
import java.util.Collections;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
@@ -35,6 +38,8 @@
{
public static final CDOLock NOOP = new NOOPLockImpl();
+ private static final Set<CDOLockOwner> NO_OWNERS = Collections.emptySet();
+
private final InternalCDOObject object;
private final LockType type;
@@ -73,12 +78,35 @@
}
@Override
+ public Set<CDOLockOwner> getOwners()
+ {
+ CDOLockState lockState = object.cdoLockState();
+
+ switch (type)
+ {
+ case READ:
+ return lockState.getReadLockOwners();
+
+ case WRITE:
+ CDOLockOwner writeLockOwner = lockState.getWriteLockOwner();
+ return writeLockOwner == null ? NO_OWNERS : Collections.singleton(writeLockOwner);
+
+ case OPTION:
+ CDOLockOwner writeOptionOwner = lockState.getWriteOptionOwner();
+ return writeOptionOwner == null ? NO_OWNERS : Collections.singleton(writeOptionOwner);
+
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ @Override
public void lock()
{
try
{
InternalCDOView view = object.cdoView();
- view.lockObjects(Collections.singletonList(object), type, WAIT);
+ view.lockObjects(Collections.singletonList(object), type, NO_TIMEOUT);
}
catch (InterruptedException ex)
{
@@ -132,7 +160,7 @@
try
{
InternalCDOView view = object.cdoView();
- view.lockObjects(Collections.singletonList(object), type, NO_WAIT);
+ view.lockObjects(Collections.singletonList(object), type, 0);
return true;
}
catch (LockTimeoutException ex)
@@ -216,6 +244,12 @@
}
@Override
+ public Set<CDOLockOwner> getOwners()
+ {
+ return NO_OWNERS;
+ }
+
+ @Override
public void lock()
{
throw new UnsupportedOperationException();
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOLockStateCacheImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOLockStateCacheImpl.java
index ded628c..9033d37 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOLockStateCacheImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOLockStateCacheImpl.java
@@ -14,20 +14,20 @@
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
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.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockState;
-import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewTargetChangedEvent;
import org.eclipse.net4j.util.CheckUtil;
import org.eclipse.net4j.util.ImplementationError;
import org.eclipse.net4j.util.ObjectUtil;
-import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.ReflectUtil;
import org.eclipse.net4j.util.collection.CollectionUtil;
import org.eclipse.net4j.util.collection.CollectionUtil.KeepMappedValue;
import org.eclipse.net4j.util.collection.HashBag;
@@ -37,8 +37,10 @@
import org.eclipse.net4j.util.container.IContainer;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.OMPlatform;
import org.eclipse.emf.spi.cdo.CDOLockStateCache;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
@@ -53,6 +55,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiFunction;
@@ -65,6 +68,11 @@
{
private static final Class<CDOLockOwner[]> ARRAY_CLASS = CDOLockOwner[].class;
+ private static final boolean DEBUG = OMPlatform.INSTANCE.isProperty("org.eclipse.emf.internal.cdo.session.CDOLockStateCacheImpl.DEBUG");
+
+ private static final boolean DEBUG_STACK_TRACE = //
+ OMPlatform.INSTANCE.isProperty("org.eclipse.emf.internal.cdo.session.CDOLockStateCacheImpl.DEBUG_STACK_TRACE");
+
private final Map<CDOBranch, ConcurrentMap<CDOID, OwnerInfo>> ownerInfosPerBranch = new HashMap<>();
private final ConcurrentMap<CDOID, OwnerInfo> ownerInfosOfMainBranch = new ConcurrentHashMap<>();
@@ -152,7 +160,7 @@
public CDOLockState getLockState(CDOBranch branch, CDOID id)
{
Object key = createKey(branch, id);
- return new MutableLockState(key, this);
+ return new LockState(key, this);
}
@Override
@@ -162,7 +170,7 @@
{
if (loadOnDemand)
{
- loadAndCacheLockStates(branch, null, consumer);
+ loadLockStates(branch, null, consumer);
}
else
{
@@ -176,7 +184,7 @@
if (!ObjectUtil.isEmpty(missingIDs))
{
- loadAndCacheLockStates(branch, missingIDs, lockState -> {
+ loadLockStates(branch, missingIDs, lockState -> {
missingIDs.remove(lockState.getID());
consumer.accept(lockState);
});
@@ -188,8 +196,7 @@
for (CDOID id : missingIDs)
{
- Object key = createKey(branch, id);
- CDOLockState defaultLockStateToCache = new ImmutableLockState(key, NoOwnerInfo.INSTANCE);
+ CDOLockState defaultLockStateToCache = getLockState(branch, id);
defaultLockStatesToCache.add(defaultLockStateToCache);
}
@@ -212,33 +219,111 @@
}
@Override
- public void addLockStates(CDOBranch branch, Collection<? extends CDOLockState> newLockStates, Consumer<CDOLockState> consumer)
+ public synchronized void updateLockStates(CDOBranch branch, Collection<CDOLockDelta> lockDeltas, Collection<CDOLockState> lockStates,
+ Consumer<CDOLockState> consumer)
+ {
+ try
+ {
+ ConcurrentMap<CDOID, OwnerInfo> infos = getOwnerInfoMap(branch);
+
+ delta_loop: for (CDOLockDelta delta : lockDeltas)
+ {
+ CDOID id = delta.getID();
+
+ OwnerInfo info = null;
+ OwnerInfo newInfo = null;
+
+ for (int i = 50; i >= 0; --i)
+ {
+ info = infos.get(id);
+ if (info == null || delta.getType() == null)
+ {
+ for (CDOLockState lockState : lockStates)
+ {
+ if (lockState.getID() == id)
+ {
+ addLockState(infos, lockState, consumer);
+ continue delta_loop;
+ }
+ }
+
+ continue delta_loop;
+ }
+
+ try
+ {
+ newInfo = info.applyDelta(this, delta);
+ break;
+ }
+ catch (ObjectAlreadyLockedException ex)
+ {
+ if (i == 0)
+ {
+ throw new ObjectAlreadyLockedException(id, branch, ex);
+ }
+
+ try
+ {
+ wait(100);
+ }
+ catch (InterruptedException ex1)
+ {
+ throw new Error(ex1);
+ }
+ }
+ }
+
+ if (newInfo != info)
+ {
+ trace(id, info, newInfo);
+ infos.put(id, newInfo);
+ }
+
+ if (consumer != null)
+ {
+ Object target = delta.getTarget();
+ CDOLockState lockState = new LockState(target, this);
+ consumer.accept(lockState);
+ }
+ }
+ }
+ finally
+ {
+ notifyAll();
+ }
+ }
+
+ @Override
+ public void addLockStates(CDOBranch branch, Collection<? extends CDOLockState> lockStates, Consumer<CDOLockState> consumer)
{
ConcurrentMap<CDOID, OwnerInfo> infos = getOwnerInfoMap(branch);
- for (CDOLockState loadedLockState : newLockStates)
+ for (CDOLockState lockState : lockStates)
{
- CDOID id = loadedLockState.getID();
- OwnerInfo info = createOwnerInfo(loadedLockState);
- infos.put(id, info);
-
- if (consumer != null)
+ try
{
- consumer.accept(loadedLockState);
+ addLockState(infos, lockState, consumer);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
}
}
}
@Override
- public void removeOwner(CDOBranch branch, CDOLockOwner owner, Consumer<CDOLockState> changeConsumer)
+ public List<CDOLockDelta> removeOwner(CDOBranch branch, CDOLockOwner owner, Consumer<CDOLockState> consumer)
{
+ List<CDOLockDelta> deltas = new ArrayList<>();
List<Pair<CDOID, OwnerInfo>> newInfos = new ArrayList<>();
+
ConcurrentMap<CDOID, OwnerInfo> infos = getOwnerInfoMap(branch);
infos.forEach((id, info) -> {
- OwnerInfo newInfo = info.removeOwner(this, owner);
+ OwnerInfo newInfo = info.removeOwner(this, owner, lockType -> appendRemoveDelta(deltas, branch, id, lockType, owner));
if (newInfo != info)
{
newInfos.add(Pair.create(id, newInfo));
+ notifyConsumer(branch, id, consumer);
}
});
@@ -247,35 +332,39 @@
CDOID id = pair.getElement1();
OwnerInfo newInfo = pair.getElement2();
- if (newInfo == NoOwnerInfo.INSTANCE)
- {
- infos.remove(id);
- }
- else
- {
- infos.put(id, newInfo);
- }
-
- notifyConsumer(branch, id, changeConsumer);
+ OwnerInfo oldInfo = infos.put(id, newInfo);
+ trace(id, oldInfo, newInfo);
}
+
+ return deltas;
}
@Override
public void remapOwner(CDOBranch branch, CDOLockOwner oldOwner, CDOLockOwner newOwner)
{
- removeSingleOwnerInfos(oldOwner);
- addSingleOwnerInfos(newOwner, -1);
+ for (int type = 0; type < singleOwnerInfos.length; type++)
+ {
+ for (SingleOwnerInfo info : singleOwnerInfos[type].values())
+ {
+ remapOwnerInfo(info, oldOwner, newOwner);
+ }
+ }
ConcurrentMap<CDOID, OwnerInfo> infos = getOwnerInfoMap(branch);
for (OwnerInfo info : infos.values())
{
- info.remapOwner(oldOwner, newOwner);
+ remapOwnerInfo(info, oldOwner, newOwner);
}
}
@Override
public void removeLockStates(CDOBranch branch, Collection<CDOID> ids, Consumer<CDOLockState> consumer)
{
+ if (ObjectUtil.isEmpty(ids))
+ {
+ return;
+ }
+
ConcurrentMap<CDOID, OwnerInfo> infos = getOwnerInfoMap(branch);
for (CDOID id : ids)
@@ -377,6 +466,34 @@
}
}
+ private SingleOwnerInfo addSingleOwnerInfos(CDOLockOwner owner, int typeToReturn)
+ {
+ SingleOwnerInfo infoToReturn = null;
+
+ for (int type = 0; type < singleOwnerInfos.length; type++)
+ {
+ int finalType = type;
+
+ // Don't overwrite existing infos. Infos can exist if the owning view is durable.
+ SingleOwnerInfo info = singleOwnerInfos[type].computeIfAbsent(owner, o -> SingleOwnerInfo.create(o, finalType));
+
+ if (type == typeToReturn)
+ {
+ infoToReturn = info;
+ }
+ }
+
+ return infoToReturn;
+ }
+
+ private void removeSingleOwnerInfos(CDOLockOwner owner)
+ {
+ for (int type = 0; type < singleOwnerInfos.length; type++)
+ {
+ singleOwnerInfos[type].remove(owner);
+ }
+ }
+
private <T> T withKey(Object key, BiFunction<CDOBranch, CDOID, T> function)
{
CDOBranch branch;
@@ -401,40 +518,11 @@
{
if (consumer != null)
{
- Object key = createKey(branch, id);
- CDOLockState lockState = new MutableLockState(key, this);
+ CDOLockState lockState = getLockState(branch, id);
consumer.accept(lockState);
}
}
- private SingleOwnerInfo addSingleOwnerInfos(CDOLockOwner owner, int typeToReturn)
- {
- CheckUtil.checkArg(owner, "owner");
- SingleOwnerInfo infoToReturn = null;
-
- for (int type = 0; type < singleOwnerInfos.length; type++)
- {
- SingleOwnerInfo info = SingleOwnerInfo.create(owner, type);
- singleOwnerInfos[type].put(owner, info);
-
- if (type == typeToReturn)
- {
- infoToReturn = info;
- }
- }
-
- return infoToReturn;
- }
-
- private void removeSingleOwnerInfos(CDOLockOwner owner)
- {
- CheckUtil.checkArg(owner, "owner");
- for (int type = 0; type < singleOwnerInfos.length; type++)
- {
- singleOwnerInfos[type].remove(owner);
- }
- }
-
private SingleOwnerInfo getSingleOwnerInfo(CDOLockOwner owner, int type)
{
SingleOwnerInfo info = singleOwnerInfos[type].get(owner);
@@ -502,6 +590,7 @@
OwnerInfo newInfo = changer.apply(info, owner);
if (newInfo != info)
{
+ trace(id, info, newInfo);
changed[0] = true;
return newInfo;
}
@@ -513,6 +602,14 @@
});
}
+ private void remapOwnerInfo(OwnerInfo info, CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ {
+ if (info.remapOwner(oldOwner, newOwner) && DEBUG)
+ {
+ IOUtil.OUT().println("Remap owner: " + info);
+ }
+ }
+
private void collectLockStates(CDOBranch branch, Collection<CDOID> ids, Set<CDOID> missingIDs, Consumer<CDOLockState> consumer)
{
if (branch != null)
@@ -548,12 +645,26 @@
}
}
- private void loadAndCacheLockStates(CDOBranch branch, Set<CDOID> ids, Consumer<CDOLockState> consumer)
+ private void loadLockStates(CDOBranch branch, Set<CDOID> ids, Consumer<CDOLockState> consumer)
{
CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
- CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(branch.getID(), ids, CDOLockState.DEPTH_NONE);
+ List<CDOLockState> lockStates = sessionProtocol.getLockStates2(branch.getID(), ids, CDOLockState.DEPTH_NONE);
- addLockStates(branch, Arrays.asList(loadedLockStates), consumer);
+ addLockStates(branch, lockStates, consumer);
+ }
+
+ private void addLockState(ConcurrentMap<CDOID, OwnerInfo> infos, CDOLockState lockState, Consumer<CDOLockState> consumer)
+ {
+ CDOID id = lockState.getID();
+ OwnerInfo info = createOwnerInfo(lockState);
+
+ trace(id, null, info);
+ infos.put(id, info);
+
+ if (consumer != null)
+ {
+ consumer.accept(lockState);
+ }
}
private OwnerInfo createOwnerInfo(CDOLockState lockState)
@@ -570,8 +681,18 @@
info = info.addReadLockOwner(this, readLockOwner);
}
- info = info.setWriteLockOwner(this, lockState.getWriteLockOwner());
- info = info.setWriteOptionOwner(this, lockState.getWriteOptionOwner());
+ info = info.addWriteLockOwner(this, lockState.getWriteLockOwner());
+ info = info.addWriteOptionOwner(this, lockState.getWriteOptionOwner());
+ }
+ catch (ObjectAlreadyLockedException ex)
+ {
+ CDOBranch branch = lockState.getBranch();
+ if (branch == null)
+ {
+ branch = mainBranch;
+ }
+
+ throw new ObjectAlreadyLockedException(lockState.getID(), branch, ex);
}
catch (RuntimeException | Error ex)
{
@@ -581,6 +702,11 @@
return info;
}
+ private boolean appendRemoveDelta(List<CDOLockDelta> deltas, CDOBranch branch, CDOID id, LockType lockType, CDOLockOwner owner)
+ {
+ return deltas.add(CDOLockUtil.createLockDelta(createKey(branch, id), lockType, owner, null));
+ }
+
private static boolean isOwnerInfoLocked(OwnerInfo info, LockType lockType, CDOLockOwner lockOwner, boolean others)
{
if (lockType == null)
@@ -664,6 +790,21 @@
return writeOptionOwner == by ^ others;
}
+ private void trace(CDOID id, OwnerInfo oldInfo, OwnerInfo newInfo)
+ {
+ if (DEBUG)
+ {
+ String message = "[" + session.getSessionID() + "] " + id + ": " + oldInfo + " --> " + newInfo;
+
+ if (DEBUG_STACK_TRACE)
+ {
+ message += "\n" + ReflectUtil.dumpThread();
+ }
+
+ IOUtil.OUT().println(message);
+ }
+ }
+
/**
* @author Eike Stepper
*/
@@ -688,19 +829,78 @@
public abstract OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
- public abstract OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
+ public abstract OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
- public abstract OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
+ public abstract OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
- public abstract OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
+ public abstract OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
- public abstract void remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner);
+ public abstract OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner);
+
+ public abstract OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner, Consumer<LockType> consumer);
+
+ public abstract boolean remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner);
+
+ public final OwnerInfo applyDelta(CDOLockStateCacheImpl cache, CDOLockDelta delta)
+ {
+ OwnerInfo info = this;
+
+ CDOLockOwner oldOwner = delta.getOldOwner();
+ CDOLockOwner newOwner = delta.getNewOwner();
+
+ switch (delta.getType())
+ {
+ case READ:
+ if (oldOwner != null)
+ {
+ info = info.removeReadLockOwner(cache, oldOwner);
+ }
+
+ if (newOwner != null)
+ {
+ info = info.addReadLockOwner(cache, newOwner);
+ }
+
+ break;
+
+ case OPTION:
+ if (oldOwner != null)
+ {
+ info = info.removeWriteOptionOwner(cache, oldOwner);
+ }
+
+ if (newOwner != null)
+ {
+ info = info.addWriteOptionOwner(cache, newOwner);
+ }
+
+ break;
+
+ case WRITE:
+ if (oldOwner != null)
+ {
+ info = info.removeWriteLockOwner(cache, oldOwner);
+ }
+
+ if (newOwner != null)
+ {
+ info = info.addWriteLockOwner(cache, newOwner);
+ }
+
+ break;
+
+ default:
+ throw new AssertionError();
+ }
+
+ return info;
+ }
@Override
public String toString()
{
String name = getClass().getName();
- name = StringUtil.replace(name, CDOLockStateCache.class.getName() + "$", "");
+ name = name.replace(CDOLockStateCacheImpl.class.getName() + "$", "");
name = name.replace('$', '.');
return name;
}
@@ -738,19 +938,22 @@
@Override
public OwnerInfo addReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
+ if (owner == null)
+ {
+ return this;
+ }
+
return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.ReadLock.TYPE);
}
@Override
public OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
return this;
}
@Override
- public OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
@@ -761,7 +964,13 @@
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ @Override
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
@@ -772,15 +981,22 @@
}
@Override
- public OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
return this;
}
@Override
- public void remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ public OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner, Consumer<LockType> consumer)
+ {
+ return this;
+ }
+
+ @Override
+ public boolean remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
{
// Do nothing.
+ return false;
}
}
@@ -815,10 +1031,11 @@
}
@Override
- public final OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public final OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner, Consumer<LockType> consumer)
{
if (owner == this.owner)
{
+ notifyLockTypes(consumer);
return NoOwnerInfo.INSTANCE;
}
@@ -826,12 +1043,15 @@
}
@Override
- public final void remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ public final boolean remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
{
if (owner == oldOwner)
{
owner = newOwner;
+ return true;
}
+
+ return false;
}
@Override
@@ -840,6 +1060,21 @@
return super.toString() + "[" + owner + "]";
}
+ protected final ObjectAlreadyLockedException failure(CDOLockOwner owner, LockType lockType)
+ {
+ StringJoiner joiner = new StringJoiner(" and the ", //
+ owner + " could not acquire the " + lockType + " lock because the ", //
+ " is already acquired by " + this.owner);
+
+ notifyLockTypes(type -> {
+ joiner.add(type + " lock");
+ });
+
+ return new ObjectAlreadyLockedException(joiner.toString());
+ }
+
+ protected abstract void notifyLockTypes(Consumer<LockType> consumer);
+
public static SingleOwnerInfo create(CDOLockOwner owner, int type)
{
switch (type)
@@ -885,7 +1120,10 @@
@Override
public OwnerInfo addReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
+ if (owner == null)
+ {
+ return this;
+ }
if (owner == this.owner)
{
@@ -898,12 +1136,11 @@
@Override
public OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
- return removeOwner(cache, owner);
+ return removeOwner(cache, owner, null);
}
@Override
- public OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
@@ -915,11 +1152,17 @@
return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.ReadLockAndWriteLock.TYPE);
}
- throw new IllegalStateException("Read lock already obtained");
+ throw failure(owner, LockType.WRITE);
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ @Override
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
@@ -933,6 +1176,21 @@
return new MultiOwnerInfo.ReadLockAndWriteOption(owner, this.owner);
}
+
+ @Override
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ @Override
+ protected void notifyLockTypes(Consumer<LockType> consumer)
+ {
+ if (consumer != null)
+ {
+ consumer.accept(LockType.READ);
+ }
+ }
}
/**
@@ -962,19 +1220,22 @@
@Override
public OwnerInfo addReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
+ if (owner == null)
+ {
+ return this;
+ }
+
if (owner == this.owner)
{
return this;
}
- throw new IllegalStateException("Write lock already obtained");
+ throw failure(owner, LockType.READ);
}
@Override
public OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
if (owner == this.owner)
{
return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.WriteLock.TYPE);
@@ -984,11 +1245,11 @@
}
@Override
- public OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
- return cache.getSingleOwnerInfo(this.owner, SingleOwnerInfo.ReadLock.TYPE);
+ return this;
}
if (owner == this.owner)
@@ -996,18 +1257,42 @@
return this;
}
- throw new IllegalStateException("Read lock already obtained");
+ throw failure(owner, LockType.WRITE);
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ if (owner == this.owner)
+ {
+ return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.ReadLock.TYPE);
+ }
+
+ return this;
+ }
+
+ @Override
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
return this;
}
- throw new IllegalStateException("Write lock already obtained");
+ throw failure(owner, LockType.OPTION);
+ }
+
+ @Override
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ @Override
+ protected void notifyLockTypes(Consumer<LockType> consumer)
+ {
+ consumer.accept(LockType.READ);
+ consumer.accept(LockType.WRITE);
}
}
@@ -1038,7 +1323,11 @@
@Override
public OwnerInfo addReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
+ if (owner == null)
+ {
+ return this;
+ }
+
if (owner == this.owner)
{
return this;
@@ -1050,7 +1339,6 @@
@Override
public OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
if (owner == this.owner)
{
return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.WriteOption.TYPE);
@@ -1060,7 +1348,7 @@
}
@Override
- public OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
@@ -1072,15 +1360,21 @@
return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.WriteLock.TYPE);
}
- throw new IllegalStateException("Read lock already obtained");
+ throw failure(owner, LockType.WRITE);
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ @Override
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
- return cache.getSingleOwnerInfo(this.owner, SingleOwnerInfo.ReadLock.TYPE);
+ return this;
}
if (owner == this.owner)
@@ -1088,7 +1382,25 @@
return this;
}
- throw new IllegalStateException("Write option already obtained");
+ throw failure(owner, LockType.OPTION);
+ }
+
+ @Override
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ if (owner == this.owner)
+ {
+ return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.ReadLock.TYPE);
+ }
+
+ return this;
+ }
+
+ @Override
+ protected void notifyLockTypes(Consumer<LockType> consumer)
+ {
+ consumer.accept(LockType.READ);
+ consumer.accept(LockType.OPTION);
}
}
@@ -1113,23 +1425,31 @@
@Override
public OwnerInfo addReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
- throw new IllegalStateException("Write lock already obtained");
+ if (owner == null)
+ {
+ return this;
+ }
+
+ if (owner == this.owner)
+ {
+ return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.ReadLockAndWriteLock.TYPE);
+ }
+
+ throw failure(owner, LockType.READ);
}
@Override
public OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
return this;
}
@Override
- public OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
- return NoOwnerInfo.INSTANCE;
+ return this;
}
if (owner == this.owner)
@@ -1137,18 +1457,41 @@
return this;
}
- throw new IllegalStateException("Write lock already obtained");
+ throw failure(owner, LockType.WRITE);
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ if (owner == this.owner)
+ {
+ return NoOwnerInfo.INSTANCE;
+ }
+
+ return this;
+ }
+
+ @Override
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
return this;
}
- throw new IllegalStateException("Write lock already obtained");
+ throw failure(owner, LockType.OPTION);
+ }
+
+ @Override
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ @Override
+ protected void notifyLockTypes(Consumer<LockType> consumer)
+ {
+ consumer.accept(LockType.WRITE);
}
}
@@ -1173,7 +1516,11 @@
@Override
public OwnerInfo addReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
+ if (owner == null)
+ {
+ return this;
+ }
+
if (owner == this.owner)
{
return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.ReadLockAndWriteOption.TYPE);
@@ -1185,12 +1532,11 @@
@Override
public OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
return this;
}
@Override
- public OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
@@ -1202,15 +1548,21 @@
return cache.getSingleOwnerInfo(owner, SingleOwnerInfo.WriteLock.TYPE);
}
- throw new IllegalStateException("Write option already obtained");
+ throw failure(owner, LockType.WRITE);
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ @Override
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
- return NoOwnerInfo.INSTANCE;
+ return this;
}
if (owner == this.owner)
@@ -1218,7 +1570,24 @@
return this;
}
- throw new IllegalStateException("Write option already obtained");
+ throw failure(owner, LockType.OPTION);
+ }
+
+ @Override
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ if (owner == this.owner)
+ {
+ return NoOwnerInfo.INSTANCE;
+ }
+
+ return this;
+ }
+
+ @Override
+ protected void notifyLockTypes(Consumer<LockType> consumer)
+ {
+ consumer.accept(LockType.OPTION);
}
}
}
@@ -1239,14 +1608,33 @@
}
@Override
- public final OwnerInfo setWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public final OwnerInfo addWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
return this;
}
- throw new IllegalStateException();
+ throw failure(owner, LockType.WRITE);
+ }
+
+ @Override
+ public final OwnerInfo removeWriteLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ return this;
+ }
+
+ protected final ObjectAlreadyLockedException failure(CDOLockOwner owner, LockType lockType)
+ {
+ String message = owner + " could not acquire the " + lockType + " lock because the READ lock is already acquired by " + getReadLockOwners();
+
+ CDOLockOwner writeOptionOwner = getWriteOptionOwner();
+ if (writeOptionOwner != null)
+ {
+ message += " and the OPTION lock is already acquired by " + writeOptionOwner;
+ }
+
+ return new ObjectAlreadyLockedException(message);
}
/**
@@ -1271,7 +1659,10 @@
@Override
public OwnerInfo addReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
+ if (owner == null)
+ {
+ return this;
+ }
CDOLockOwner[] owners = readLockOwners;
if (CDOLockUtil.indexOf(owners, owner) == -1)
@@ -1289,8 +1680,6 @@
@Override
public OwnerInfo removeReadLockOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- CheckUtil.checkArg(owner, "owner");
-
CDOLockOwner[] owners = readLockOwners;
int index = CDOLockUtil.indexOf(owners, owner);
if (index != -1)
@@ -1343,7 +1732,7 @@
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
@@ -1354,20 +1743,42 @@
}
@Override
- public OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
- return removeReadLockOwner(cache, owner);
+ return this;
}
@Override
- public void remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ public OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner, Consumer<LockType> consumer)
+ {
+ OwnerInfo newInfo = removeReadLockOwner(cache, owner);
+
+ if (newInfo != this)
+ {
+ consumer.accept(LockType.READ);
+ }
+
+ return newInfo;
+ }
+
+ @Override
+ public boolean remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
{
CDOLockOwner[] owners = readLockOwners;
int index = CDOLockUtil.indexOf(owners, oldOwner);
if (index != -1)
{
readLockOwners[index] = newOwner;
+ return true;
}
+
+ return false;
+ }
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + "[readLockOwners=" + Arrays.asList(readLockOwners) + "]";
}
private static MultiOwnerInfo createMultiOwnerInfo(CDOLockOwner writeOptionOwner, CDOLockOwner... readLockOwners)
@@ -1401,43 +1812,64 @@
}
@Override
- public OwnerInfo setWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo addWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
{
if (owner == null)
{
- return new MultiOwnerInfo.ReadLock(readLockOwners);
+ return this;
}
- if (writeOptionOwner != owner)
+ if (owner == writeOptionOwner)
{
- throw new IllegalStateException();
+ return this;
+ }
+
+ throw failure(owner, LockType.OPTION);
+ }
+
+ @Override
+ public OwnerInfo removeWriteOptionOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ {
+ if (owner == writeOptionOwner)
+ {
+ return new MultiOwnerInfo.ReadLock(readLockOwners);
}
return this;
}
@Override
- public OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner)
+ public OwnerInfo removeOwner(CDOLockStateCacheImpl cache, CDOLockOwner owner, Consumer<LockType> consumer)
{
- OwnerInfo newInfo = super.removeOwner(cache, owner);
+ OwnerInfo newInfo = super.removeOwner(cache, owner, consumer);
if (owner == newInfo.getWriteOptionOwner())
{
- return newInfo.setWriteOptionOwner(cache, null);
+ consumer.accept(LockType.OPTION);
+ return newInfo.removeWriteOptionOwner(cache, owner);
}
return newInfo;
}
@Override
- public void remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ public boolean remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
{
- super.remapOwner(oldOwner, newOwner);
+ boolean remapped = super.remapOwner(oldOwner, newOwner);
if (writeOptionOwner == oldOwner)
{
writeOptionOwner = newOwner;
+ remapped = true;
}
+
+ return remapped;
+ }
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + "[readLockOwners=" + Arrays.asList(readLockOwners) + ", writeOptionOwner=" + writeOptionOwner + "]";
}
}
}
@@ -1445,21 +1877,16 @@
/**
* @author Eike Stepper
*/
- private static abstract class LockState extends AbstractCDOLockState
+ private static final class LockState extends AbstractCDOLockState
{
private static final Set<CDOLockOwner> NO_LOCK_OWNERS = Collections.emptySet();
- protected final Object key;
+ private final CDOLockStateCacheImpl cache;
- public LockState(Object key)
+ public LockState(Object lockedObject, CDOLockStateCacheImpl cache)
{
- this.key = key;
- }
-
- @Override
- public final Object getLockedObject()
- {
- return key;
+ super(lockedObject);
+ this.cache = cache;
}
@Override
@@ -1509,50 +1936,75 @@
return info.getWriteOptionOwner();
}
- protected abstract OwnerInfo getInfo();
- }
-
- /**
- * @author Eike Stepper
- */
- private static final class MutableLockState extends LockState implements InternalCDOLockState
- {
- private final CDOLockStateCacheImpl cache;
-
- public MutableLockState(Object key, CDOLockStateCacheImpl cache)
+ @Override
+ protected CDOLockDelta addReadOwner(CDOLockOwner owner)
{
- super(key);
- this.cache = cache;
+ if (cache.changeOwnerInfo(lockedObject, owner, (i, o) -> i.addReadLockOwner(cache, o)))
+ {
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.READ, null, owner);
+ }
+
+ return null;
}
@Override
- public void addReadLockOwner(CDOLockOwner owner)
+ protected CDOLockDelta addWriteOwner(CDOLockOwner owner)
{
- cache.changeOwnerInfo(key, owner, (i, o) -> i.addReadLockOwner(cache, o));
+ if (cache.changeOwnerInfo(lockedObject, owner, (i, o) -> i.addWriteLockOwner(cache, o)))
+ {
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.WRITE, null, owner);
+ }
+
+ return null;
}
@Override
- public boolean removeReadLockOwner(CDOLockOwner owner)
+ protected CDOLockDelta addOptionOwner(CDOLockOwner owner)
{
- return cache.changeOwnerInfo(key, owner, (i, o) -> i.removeReadLockOwner(cache, o));
+ if (cache.changeOwnerInfo(lockedObject, owner, (i, o) -> i.addWriteOptionOwner(cache, o)))
+ {
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.OPTION, null, owner);
+ }
+
+ return null;
}
@Override
- public void setWriteLockOwner(CDOLockOwner owner)
+ protected CDOLockDelta removeReadOwner(CDOLockOwner owner)
{
- cache.changeOwnerInfo(key, owner, (i, o) -> i.setWriteLockOwner(cache, o));
+ if (cache.changeOwnerInfo(lockedObject, owner, (i, o) -> i.removeReadLockOwner(cache, o)))
+ {
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.READ, owner, null);
+ }
+
+ return null;
}
@Override
- public void setWriteOptionOwner(CDOLockOwner owner)
+ protected CDOLockDelta removeWriteOwner(CDOLockOwner owner)
{
- cache.changeOwnerInfo(key, owner, (i, o) -> i.setWriteOptionOwner(cache, o));
+ if (cache.changeOwnerInfo(lockedObject, owner, (i, o) -> i.removeWriteLockOwner(cache, o)))
+ {
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.WRITE, owner, null);
+ }
+
+ return null;
}
@Override
- public boolean removeOwner(CDOLockOwner owner)
+ protected CDOLockDelta removeOptionOwner(CDOLockOwner owner)
{
- return cache.changeOwnerInfo(key, owner, (i, o) -> i.removeOwner(cache, o));
+ if (cache.changeOwnerInfo(lockedObject, owner, (i, o) -> i.removeWriteOptionOwner(cache, o)))
+ {
+ return CDOLockUtil.createLockDelta(lockedObject, LockType.OPTION, owner, null);
+ }
+
+ return null;
+ }
+
+ private OwnerInfo getInfo()
+ {
+ return cache.getOwnerInfo(lockedObject);
}
/**
@@ -1560,59 +2012,9 @@
*/
@Deprecated
@Override
- public boolean remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
+ public CDOLockDelta[] remapOwner(CDOLockOwner oldOwner, CDOLockOwner newOwner)
{
throw new UnsupportedOperationException();
}
-
- @Deprecated
- @Override
- public void updateFrom(Object object, CDOLockState source)
- {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @deprecated Only used for new objects and those are local to a transaction, i.e., not cached.
- */
- @Deprecated
- @Override
- public void updateFrom(CDOLockState source)
- {
- throw new UnsupportedOperationException();
- }
-
- @Deprecated
- @Override
- public void dispose()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected OwnerInfo getInfo()
- {
- return cache.getOwnerInfo(key);
- }
- }
-
- /**
- * @author Eike Stepper
- */
- private static final class ImmutableLockState extends LockState
- {
- private final OwnerInfo info;
-
- public ImmutableLockState(Object key, OwnerInfo info)
- {
- super(key);
- this.info = info;
- }
-
- @Override
- protected OwnerInfo getInfo()
- {
- return info;
- }
}
}
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 a389bc3..65759c4 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
@@ -34,6 +34,7 @@
import org.eclipse.emf.cdo.common.lob.CDOLobInfo;
import org.eclipse.emf.cdo.common.lob.CDOLobStore;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.protocol.CDOProtocol.CommitNotificationInfo;
@@ -95,13 +96,12 @@
import org.eclipse.emf.internal.cdo.messages.Messages;
import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl;
import org.eclipse.emf.internal.cdo.session.remote.CDORemoteSessionManagerImpl;
-import org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent;
+import org.eclipse.emf.internal.cdo.util.AbstractLocksChangedEvent;
import org.eclipse.net4j.util.AdapterUtil;
import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
-import org.eclipse.net4j.util.concurrent.IRWLockManager;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.concurrent.IRWOLockManager;
import org.eclipse.net4j.util.concurrent.RWOLockManager;
@@ -153,6 +153,7 @@
import java.io.Reader;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -687,7 +688,7 @@
{
try
{
- lockManager.lock(LockType.WRITE, key, this, IRWLockManager.WAIT);
+ lockManager.lock(key, singletonCollection, LockType.WRITE, 1, IRWOLockManager.NO_TIMEOUT, null, null);
}
catch (InterruptedException ex)
{
@@ -698,7 +699,7 @@
@Override
public void releaseAtomicRequestLock(Object key)
{
- lockManager.unlock(LockType.WRITE, key, singletonCollection);
+ lockManager.unlock(key, singletonCollection, LockType.WRITE, 1, null, null);
}
@Override
@@ -1172,8 +1173,9 @@
}
else
{
- List<CDOLockState> lockStates = lockChangeInfo.getNewLockStates();
- lockStateCache.addLockStates(branch, lockStates, null);
+ CDOLockDelta[] lockDeltas = lockChangeInfo.getLockDeltas();
+ CDOLockState[] lockStates = lockChangeInfo.getLockStates();
+ lockStateCache.updateLockStates(branch, Arrays.asList(lockDeltas), Arrays.asList(lockStates), null);
}
}
@@ -2763,7 +2765,7 @@
* @author Caspar De Groot
* @since 4.1
*/
- private final class SessionLocksChangedEvent extends DefaultLocksChangedEvent implements CDOSessionLocksChangedEvent
+ private final class SessionLocksChangedEvent extends AbstractLocksChangedEvent implements CDOSessionLocksChangedEvent
{
private static final long serialVersionUID = 1L;
@@ -2779,6 +2781,12 @@
}
@Override
+ protected InternalCDOSession getSession()
+ {
+ return (InternalCDOSession)getSource();
+ }
+
+ @Override
protected String formatEventName()
{
return "CDOSessionLocksChangedEvent";
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java
index 0492efa..807529e 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java
@@ -28,6 +28,7 @@
import org.eclipse.emf.cdo.common.lob.CDOLob;
import org.eclipse.emf.cdo.common.lob.CDOLobInfo;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevision;
@@ -77,6 +78,7 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
@@ -190,14 +192,14 @@
}
@Override
- public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID)
+ public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID, BiConsumer<CDOID, LockGrade> consumer)
{
int attempt = 0;
for (;;)
{
try
{
- return delegate.openView(viewID, readOnly, durableLockingID);
+ return delegate.openView(viewID, readOnly, durableLockingID, consumer);
}
catch (Exception ex)
{
@@ -301,14 +303,6 @@
}
@Override
- @Deprecated
- public CommitTransactionResult commitTransaction(int transactionID, String comment, boolean releaseLocks, CDOIDProvider idProvider, CDOCommitData commitData,
- Collection<CDOLob<?>> lobs, OMMonitor monitor)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public CommitTransactionResult commitTransaction(InternalCDOCommitContext context, OMMonitor monitor)
{
int attempt = 0;
@@ -326,14 +320,6 @@
}
@Override
- @Deprecated
- public CommitTransactionResult commitDelegation(CDOBranch branch, String userID, String comment, CDOCommitData commitData,
- Map<CDOID, EClass> detachedObjectTypes, Collection<CDOLob<?>> lobs, OMMonitor monitor)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public CommitTransactionResult commitDelegation(InternalCDOCommitContext context, OMMonitor monitor)
{
int attempt = 0;
@@ -471,21 +457,14 @@
}
@Override
- @Deprecated
- public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids, int depth)
+ public List<CDOLockState> getLockStates2(int branchID, Collection<CDOID> ids, int depth)
{
int attempt = 0;
for (;;)
{
try
{
- return delegate.getLockStates(branchID, ids, depth);
+ return delegate.getLockStates2(branchID, ids, depth);
}
catch (Exception ex)
{
@@ -649,20 +628,6 @@
}
@Override
- @Deprecated
- public void deleteBranch(int branchID)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void renameBranch(int branchID, String newName)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void renameBranch(int branchID, String oldName, String newName)
{
int attempt = 0;
@@ -768,13 +733,6 @@
}
@Override
- @Deprecated
- public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth,
boolean prefetchLockStates)
{
@@ -826,14 +784,6 @@
}
}
- @Override
- @Deprecated
- public LockObjectsResult lockObjects(List<InternalCDORevision> viewedRevisions, int viewID, CDOBranch viewedBranch, LockType lockType, long timeout)
- throws InterruptedException
- {
- throw new UnsupportedOperationException();
- }
-
/**
* @since 4.1
*/
@@ -982,13 +932,6 @@
}
@Override
- @Deprecated
- public void unlockObjects(CDOView view, Collection<CDOID> objectIDs, LockType lockType)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public UnlockObjectsResult unlockObjects2(CDOView view, Collection<CDOID> objectIDs, LockType lockType, boolean recursive)
{
int attempt = 0;
@@ -1110,14 +1053,6 @@
}
@Override
- @Deprecated
- public Set<CDOID> loadMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
- CDORevisionAvailabilityInfo sourceBaseInfo)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public MergeDataResult loadMergeData2(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo)
{
@@ -1170,13 +1105,6 @@
}
@Override
- @Deprecated
- public void requestChangeCredentials()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public void requestChangeServerPassword(AtomicReference<char[]> receiver)
{
int attempt = 0;
@@ -1266,4 +1194,92 @@
throw WrappedException.wrap(ex);
}
}
+
+ @Override
+ @Deprecated
+ public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CommitTransactionResult commitTransaction(int transactionID, String comment, boolean releaseLocks, CDOIDProvider idProvider, CDOCommitData commitData,
+ Collection<CDOLob<?>> lobs, OMMonitor monitor)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CommitTransactionResult commitDelegation(CDOBranch branch, String userID, String comment, CDOCommitData commitData,
+ Map<CDOID, EClass> detachedObjectTypes, Collection<CDOLob<?>> lobs, OMMonitor monitor)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids, int depth)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void deleteBranch(int branchID)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void renameBranch(int branchID, String newName)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public LockObjectsResult lockObjects(List<InternalCDORevision> viewedRevisions, int viewID, CDOBranch viewedBranch, LockType lockType, long timeout)
+ throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlockObjects(CDOView view, Collection<CDOID> objectIDs, LockType lockType)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public Set<CDOID> loadMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
+ CDORevisionAvailabilityInfo sourceBaseInfo)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void requestChangeCredentials()
+ {
+ throw new UnsupportedOperationException();
+ }
}
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 0b87b70..0981774 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
@@ -39,6 +39,7 @@
import org.eclipse.emf.cdo.common.lob.CDOLob;
import org.eclipse.emf.cdo.common.lob.CDOLobStore;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
@@ -150,7 +151,7 @@
import org.eclipse.net4j.util.collection.ConcurrentArray;
import org.eclipse.net4j.util.collection.DelegatingCloseableIterator;
import org.eclipse.net4j.util.collection.Pair;
-import org.eclipse.net4j.util.concurrent.IRWLockManager;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
@@ -224,6 +225,8 @@
private static final boolean X_COMPRESSION = OMPlatform.INSTANCE.isProperty("org.eclipse.emf.cdo.transaction.X_COMPRESSION");
+ private static final LockType[] ALL_LOCK_TYPES = LockType.values();
+
private static final Method COPY_OBJECT_METHOD;
static
@@ -4258,14 +4261,10 @@
{
InternalCDOObject object = super.remapObjectUnsynced(oldID);
- InternalCDOLockState oldLockState = lockStatesOfNewObjects.remove(object);
- if (oldLockState != null)
+ InternalCDOLockState lockState = lockStatesOfNewObjects.get(object);
+ if (lockState != null)
{
- Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch
- InternalCDOLockState newLockState = (InternalCDOLockState)CDOLockUtil.createLockState(lockedObject);
- newLockState.updateFrom(oldLockState);
-
- lockStatesOfNewObjects.put(object, newLockState);
+ lockState.remapID(object.cdoID());
}
return object;
@@ -4342,61 +4341,35 @@
}
@Override
- protected InternalCDOLockState createUpdatedLockStateForNewObject(CDOObject object, IRWLockManager.LockType lockType, boolean on)
+ protected boolean updateLockStateOfNewObject(CDOObject object, LockType lockType, boolean on, List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
if (!FSMUtil.isNew(object))
{
- return null;
+ return false;
}
- InternalCDOLockState lockStateOfNewObject = getLockStateOfNewObject(object);
+ InternalCDOLockState lockState = getLockStateOfNewObject(object);
+ CDOLockOwner lockOwner = getLockOwner();
- switch (lockType)
- {
- case READ:
- if (on)
- {
- lockStateOfNewObject.addReadLockOwner(getLockOwner());
- }
- else
- {
- lockStateOfNewObject.removeReadLockOwner(getLockOwner());
- }
- break;
+ CDOLockDelta lockDelta = on ? lockState.addOwner(lockOwner, lockType) : lockState.removeOwner(lockOwner, lockType);
- case WRITE:
- lockStateOfNewObject.setWriteLockOwner(on ? getLockOwner() : null);
- break;
-
- case OPTION:
- lockStateOfNewObject.setWriteOptionOwner(on ? getLockOwner() : null);
- break;
-
- default:
- throw new IllegalArgumentException("Unknown lock type " + lockType);
- }
-
- return lockStateOfNewObject;
+ lockDeltas.add(lockDelta);
+ lockStates.add(lockState);
+ return true;
}
@Override
- protected List<CDOLockState> createUnlockedLockStatesForAllNewObjects()
+ protected void unlockAllNewObjects(List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
- Collection<CDOObject> newObjects = getNewObjects().values();
- if (newObjects.isEmpty())
+ for (Map.Entry<CDOObject, InternalCDOLockState> entry : lockStatesOfNewObjects.entrySet())
{
- return null;
- }
+ CDOObject object = entry.getKey();
- List<CDOLockState> locksOnNewObjects = new ArrayList<>();
- for (CDOObject object : newObjects)
- {
- Object lockTarget = getLockTarget(object);
- CDOLockState lockState = CDOLockUtil.createLockState(lockTarget);
- locksOnNewObjects.add(lockState);
+ for (LockType lockType : ALL_LOCK_TYPES)
+ {
+ updateLockStateOfNewObject(object, lockType, false, lockDeltas, lockStates);
+ }
}
-
- return locksOnNewObjects;
}
@Override
@@ -5073,9 +5046,11 @@
CDOLockStateCache lockStateCache = getSession().getLockStateCache();
CDOLockOwner lockOwner = getLockOwner();
- List<CDOLockState> lockStatesToChangeInOldBranch = new ArrayList<>();
- List<CDOLockState> lockStatesToChangeInNewBranch = new ArrayList<>();
- List<CDOLockState> releasedLocks = new ArrayList<>();
+ List<CDOLockDelta> lockDeltasOldBranch = new ArrayList<>();
+ List<CDOLockState> lockStatesOldBranch = new ArrayList<>();
+
+ List<CDOLockDelta> lockDeltasNewBranch = new ArrayList<>();
+ List<CDOLockState> lockStatesNewBranch = new ArrayList<>();
// 1. Process detached objects.
lockStateCache.removeLockStates(oldBranch, detachedObjectIDs, null);
@@ -5087,6 +5062,11 @@
for (Map.Entry<CDOObject, InternalCDOLockState> entry : lockStatesOfNewObjects.entrySet())
{
CDOObject object = entry.getKey();
+ if (FSMUtil.isTransient(object))
+ {
+ continue;
+ }
+
InternalCDOLockState lockState = entry.getValue();
CDOID id = lockState.getID();
@@ -5096,27 +5076,43 @@
newID = id;
}
- // Remember to remap the lock target in old branch.
if (newID != id || branchChanged)
{
- Object newLockTarget = getLockTarget(newID);
- lockState = (InternalCDOLockState)CDOLockUtil.copyLockState(lockState, newLockTarget);
- lockStatesToChangeInOldBranch.add(lockState);
+ lockState.remapID(newID);
}
+ Object lockTarget = lockState.getLockedObject();
+ boolean deltaAdded = false;
+
// Auto-release locks.
if (options().isEffectiveAutoReleaseLock(object))
{
- if (lockState.removeOwner(lockOwner))
+ for (CDOLockDelta lockDelta : lockState.clearOwner(lockOwner))
{
- releasedLocks.add(lockState);
+ lockDeltasNewBranch.add(lockDelta);
+ deltaAdded = true;
}
}
else
{
// Transfer lock state of the new object into the session-scoped lock state cache.
- lockStatesToChangeInNewBranch.add(lockState);
+ for (LockType lockType : ALL_LOCK_TYPES)
+ {
+ if (lockState.isLocked(lockType, lockOwner, false))
+ {
+ lockDeltasNewBranch.add(CDOLockUtil.createLockDelta(lockTarget, lockType, null, lockOwner));
+ deltaAdded = true;
+ }
+ }
}
+
+ if (!deltaAdded)
+ {
+ // Add a Null delta to make sure that lockStateCache.updateLockStates() does not ignore the lock state.
+ lockDeltasNewBranch.add(CDOLockUtil.createLockDelta(lockTarget));
+ }
+
+ lockStatesNewBranch.add(lockState);
}
// 3. Process all other locks.
@@ -5124,31 +5120,47 @@
// Auto-release locks.
if (options().isEffectiveAutoReleaseLock(object))
{
- if (((InternalCDOLockState)lockState).removeOwner(lockOwner))
+ for (CDOLockDelta lockDelta : ((InternalCDOLockState)lockState).clearOwner(lockOwner))
{
- releasedLocks.add(lockState);
+ lockDeltasOldBranch.add(lockDelta);
}
+
+ lockStatesOldBranch.add(lockState);
}
});
lockStatesOfNewObjects.clear();
- if (!lockStatesToChangeInOldBranch.isEmpty())
+ if (!lockDeltasNewBranch.isEmpty())
{
- lockStateCache.addLockStates(oldBranch, lockStatesToChangeInOldBranch, null);
+ lockStateCache.updateLockStates(newBranch, lockDeltasNewBranch, lockStatesNewBranch, null);
+
+ // Remove the Null deltas before makeLockChangeInfo() is called.
+ for (Iterator<CDOLockDelta> it = lockDeltasNewBranch.iterator(); it.hasNext();)
+ {
+ CDOLockDelta delta = it.next();
+ if (delta.getType() == null)
+ {
+ it.remove();
+ }
+ }
}
- if (!lockStatesToChangeInNewBranch.isEmpty())
+ if (!lockDeltasOldBranch.isEmpty())
{
- lockStateCache.addLockStates(newBranch, lockStatesToChangeInNewBranch, null);
+ lockStateCache.updateLockStates(oldBranch, lockDeltasOldBranch, lockStatesOldBranch, null);
+
+ // Make sure that the changes on the old branch end up in the lockChangeInfo below.
+ lockDeltasNewBranch.addAll(lockDeltasOldBranch);
+ lockStatesNewBranch.addAll(lockStatesOldBranch);
}
- if (!releasedLocks.isEmpty())
+ if (lockDeltasNewBranch.isEmpty())
{
- return makeLockChangeInfo(CDOLockChangeInfo.Operation.UNLOCK, null, result.getTimeStamp(), releasedLocks);
+ return null;
}
- return null;
+ return makeLockChangeInfo(result.getTimeStamp(), lockDeltasNewBranch, lockStatesNewBranch);
}
private void collectLobs(InternalCDORevision revision, Map<ByteArrayWrapper, CDOLob<?>> lobs)
@@ -5372,6 +5384,8 @@
private final Map<EObject, Boolean> autoReleaseLocksExemptions = new WeakHashMap<>();
+ private long optimisticLockingTimeout = DEFAULT_OPTIMISTIC_LOCKING_TIMEOUT;
+
private long commitInfoTimeout = DEFAULT_COMMIT_INFO_TIMEOUT;
private Map<CDOID, CDORevision> attachedRevisionsMap;
@@ -5819,6 +5833,40 @@
}
@Override
+ public long getOptimisticLockingTimeout()
+ {
+ return optimisticLockingTimeout;
+ }
+
+ @Override
+ public void setOptimisticLockingTimeout(long optimisticLockingTimeout)
+ {
+ checkActive();
+
+ IEvent event = null;
+ synchronized (getViewMonitor())
+ {
+ lockView();
+
+ try
+ {
+ if (this.optimisticLockingTimeout != optimisticLockingTimeout)
+ {
+ this.optimisticLockingTimeout = optimisticLockingTimeout;
+ event = new OptimisticLockingTimeoutImpl();
+ }
+ }
+ finally
+ {
+ unlockView();
+ }
+ }
+
+ fireEvent(event);
+
+ }
+
+ @Override
public long getCommitInfoTimeout()
{
return commitInfoTimeout;
@@ -5932,6 +5980,19 @@
/**
* @author Eike Stepper
*/
+ private final class OptimisticLockingTimeoutImpl extends OptionsEvent implements CommitInfoTimeout
+ {
+ private static final long serialVersionUID = 1L;
+
+ public OptimisticLockingTimeoutImpl()
+ {
+ super(OptionsImpl.this);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
private final class CommitInfoTimeoutImpl extends OptionsEvent implements CommitInfoTimeout
{
private static final long serialVersionUID = 1L;
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/AbstractLocksChangedEvent.java
similarity index 65%
rename from plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java
rename to plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/AbstractLocksChangedEvent.java
index f4d13d3..7f70a27 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/AbstractLocksChangedEvent.java
@@ -12,22 +12,21 @@
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.spi.common.lock.AbstractCDOLockChangeInfo;
-import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
-import org.eclipse.net4j.util.event.Event;
import org.eclipse.net4j.util.event.INotifier;
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
import org.eclipse.emf.spi.cdo.InternalCDOView;
-import java.util.List;
-
/**
* @author Caspar De Groot
* @since 4.1
*/
-public class DefaultLocksChangedEvent extends Event implements CDOLockChangeInfo
+public abstract class AbstractLocksChangedEvent extends AbstractCDOLockChangeInfo
{
private static final long serialVersionUID = 1L;
@@ -35,7 +34,7 @@
private final CDOLockChangeInfo lockChangeInfo;
- public DefaultLocksChangedEvent(INotifier notifier, InternalCDOView sender, CDOLockChangeInfo lockChangeInfo)
+ public AbstractLocksChangedEvent(INotifier notifier, InternalCDOView sender, CDOLockChangeInfo lockChangeInfo)
{
super(notifier);
this.sender = sender;
@@ -60,34 +59,21 @@
}
@Override
- public final Operation getOperation()
- {
- return lockChangeInfo.getOperation();
- }
-
- @Override
- public final LockType getLockType()
- {
- return lockChangeInfo.getLockType();
- }
-
- @Override
- public final CDOLockOwner getLockOwner()
+ public CDOLockOwner getLockOwner()
{
return lockChangeInfo.getLockOwner();
}
- @Deprecated
@Override
- public final CDOLockState[] getLockStates()
+ public final CDOLockDelta[] getLockDeltas()
{
- return lockChangeInfo.getLockStates();
+ return lockChangeInfo.getLockDeltas();
}
@Override
- public List<CDOLockState> getNewLockStates()
+ public CDOLockState[] getLockStates()
{
- return lockChangeInfo.getNewLockStates();
+ return lockChangeInfo.getLockStates();
}
@Override
@@ -96,14 +82,11 @@
return lockChangeInfo.isInvalidateAll();
}
- protected final CDOLockChangeInfo getLockChangeInfo()
- {
- return lockChangeInfo;
- }
-
@Override
protected String formatAdditionalParameters()
{
- return "sender=" + getSender() + ", " + getLockChangeInfo();
+ return "sender=" + sender + ", " + lockChangeInfo;
}
+
+ protected abstract InternalCDOSession getSession();
}
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 65bb255..9db7916 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
@@ -22,10 +22,11 @@
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
-import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
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.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.protocol.CDOProtocol.CommitNotificationInfo;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants.UnitOpcode;
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
@@ -72,7 +73,7 @@
import org.eclipse.emf.internal.cdo.object.CDONotificationBuilder;
import org.eclipse.emf.internal.cdo.object.CDOObjectWrapperBase;
import org.eclipse.emf.internal.cdo.session.SessionUtil;
-import org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent;
+import org.eclipse.emf.internal.cdo.util.AbstractLocksChangedEvent;
import org.eclipse.net4j.util.CheckUtil;
import org.eclipse.net4j.util.ObjectUtil;
@@ -131,7 +132,6 @@
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.Set;
@@ -183,6 +183,8 @@
@ExcludeFromDump
private boolean inverseClosing;
+ private DurableLockProcessor durableLockProcessor;
+
/**
* @since 2.0
*/
@@ -384,8 +386,12 @@
checkActive();
checkState(!isHistorical(), "Locking not supported for historial views");
- List<CDOLockState> newLockStates = null;
- List<CDOLockState> locksOnNewObjects = new ArrayList<>();
+ List<CDOLockDelta> newObjectLockDeltas = new ArrayList<>();
+ List<CDOLockState> newObjectLockStates = new ArrayList<>();
+
+ List<CDOLockDelta> sessionLockDeltas = null;
+ List<CDOLockState> sessionLockStates = null;
+
long timeStamp = CDOBranchPoint.UNSPECIFIED_DATE;
synchronized (getViewMonitor())
@@ -399,21 +405,14 @@
// TODO For recursive locking consider local tree changes (NEW, DIRTY).
for (CDOObject object : CollectionUtil.setOf(objects))
{
- CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, true);
- if (lockState != null)
+ if (updateLockStateOfNewObject(object, lockType, true, newObjectLockDeltas, newObjectLockStates))
{
- locksOnNewObjects.add(lockState);
-
if (recursive)
{
for (TreeIterator<EObject> it = object.eAllContents(); it.hasNext();)
{
CDOObject child = CDOUtil.getCDOObject(it.next());
- lockState = createUpdatedLockStateForNewObject(child, lockType, true);
- if (lockState != null)
- {
- locksOnNewObjects.add(lockState);
- }
+ updateLockStateOfNewObject(child, lockType, true, newObjectLockDeltas, newObjectLockStates);
}
}
}
@@ -484,10 +483,14 @@
if (result != null)
{
- newLockStates = Arrays.asList(result.getNewLockStates());
timeStamp = result.getTimestamp();
- updateLockStates(newLockStates, false, null);
+ sessionLockDeltas = result.getLockDeltas();
+ if (!ObjectUtil.isEmpty(sessionLockDeltas))
+ {
+ sessionLockStates = result.getLockStates();
+ updateLockStates(sessionLockDeltas, sessionLockStates);
+ }
}
}
finally
@@ -496,57 +499,43 @@
}
}
- if (!locksOnNewObjects.isEmpty())
+ if (!newObjectLockDeltas.isEmpty())
{
- CDOLockChangeInfo lockChangeInfo = makeLockChangeInfo(Operation.LOCK, lockType, getTimeStamp(), locksOnNewObjects);
+ CDOLockChangeInfo lockChangeInfo = makeLockChangeInfo(getTimeStamp(), newObjectLockDeltas, newObjectLockStates);
fireLocksChangedEvent(this, lockChangeInfo);
}
- if (newLockStates != null)
+ if (!ObjectUtil.isEmpty(sessionLockDeltas))
{
- notifyLockChanges(Operation.LOCK, lockType, timeStamp, newLockStates);
+ notifyLockChanges(timeStamp, sessionLockDeltas, sessionLockStates);
}
}
- @Deprecated
- @Override
- public void updateLockStates(CDOLockState[] newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer)
- {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Updates the lock states of objects held in this view.
- * <p>
- * The caller must hold the view lock!
- *
- * @param newLockStates new {@link CDOLockState lockStates} to integrate in cache
- * @param loadObjectsOnDemand true to load corresponding {@link CDOObject} if not already loaded to be able to store lockState in cache, false otherwise
- * @since 4.5
- */
- @Override
- public final void updateLockStates(Collection<? extends CDOLockState> newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer)
+ private void updateLockStates(List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
CDOBranch branch = getBranch();
CDOLockStateCache lockStateCache = session.getLockStateCache();
- lockStateCache.addLockStates(branch, newLockStates, consumer);
+ lockStateCache.updateLockStates(branch, lockDeltas, lockStates, null);
}
- protected final void notifyLockChanges(Operation op, LockType type, long timestamp, Collection<? extends CDOLockState> lockStates)
+ protected final void notifyLockChanges(long timestamp, Collection<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
- if (isActive() && !lockStates.isEmpty())
+ if (isActive() && !lockDeltas.isEmpty())
{
- CDOLockChangeInfo lockChangeInfo = makeLockChangeInfo(op, type, timestamp, lockStates);
+ CDOLockChangeInfo lockChangeInfo = makeLockChangeInfo(timestamp, lockDeltas, lockStates);
notifyLockChanges(lockChangeInfo);
}
}
+ /**
+ * Notifies the session (including other views) and this view.
+ */
protected final void notifyLockChanges(CDOLockChangeInfo lockChangeInfo)
{
if (isActive() && lockChangeInfo != null)
{
- List<CDOLockState> lockStates = lockChangeInfo.getNewLockStates();
- if (!ObjectUtil.isEmpty(lockStates) || lockChangeInfo.isInvalidateAll())
+ CDOLockDelta[] lockDeltas = lockChangeInfo.getLockDeltas();
+ if (!ObjectUtil.isEmpty(lockDeltas) || lockChangeInfo.isInvalidateAll())
{
// Do not call out from the current thread to other views while this view is holding its view lock!
session.handleLockNotification(lockChangeInfo, this, true);
@@ -555,10 +544,11 @@
}
}
- protected final CDOLockChangeInfo makeLockChangeInfo(Operation op, LockType type, long timestamp, Collection<? extends CDOLockState> newLockStates)
+ protected final CDOLockChangeInfo makeLockChangeInfo(long timestamp, Collection<CDOLockDelta> lockDeltas, Collection<CDOLockState> lockStates)
{
CDOBranchPoint branchPoint = getBranch().getPoint(timestamp);
- return CDOLockUtil.createLockChangeInfo(branchPoint, getLockOwner(), op, type, newLockStates);
+ CDOLockOwner lockOwner = getLockOwner();
+ return CDOLockUtil.createLockChangeInfo(branchPoint, lockOwner, lockDeltas, lockStates);
}
@Override
@@ -622,8 +612,12 @@
{
checkActive();
- Collection<? extends CDOLockState> newLockStates = null;
- List<CDOLockState> locksOnNewObjects = new LinkedList<>();
+ List<CDOLockDelta> newObjectLockDeltas = new ArrayList<>();
+ List<CDOLockState> newObjectLockStates = new ArrayList<>();
+
+ List<CDOLockDelta> sessionLockDeltas = null;
+ List<CDOLockState> sessionLockStates = null;
+
long timeStamp = CDOBranchPoint.UNSPECIFIED_DATE;
synchronized (getViewMonitor())
@@ -640,18 +634,15 @@
for (CDOObject object : CollectionUtil.setOf(objects))
{
- CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, false);
- if (lockState != null)
+ updateLockStateOfNewObject(object, lockType, false, newObjectLockDeltas, newObjectLockStates);
+ if (updateLockStateOfNewObject(object, lockType, false, newObjectLockDeltas, newObjectLockStates))
{
- locksOnNewObjects.add(lockState);
-
if (recursive)
{
for (TreeIterator<EObject> it = object.eAllContents(); it.hasNext();)
{
CDOObject child = CDOUtil.getCDOObject(it.next());
- lockState = createUpdatedLockStateForNewObject(child, lockType, false);
- locksOnNewObjects.add(lockState);
+ updateLockStateOfNewObject(child, lockType, false, newObjectLockDeltas, newObjectLockStates);
}
}
}
@@ -671,11 +662,7 @@
}
else
{
- Collection<CDOLockState> lockStates = createUnlockedLockStatesForAllNewObjects();
- if (!ObjectUtil.isEmpty(lockStates))
- {
- locksOnNewObjects.addAll(lockStates);
- }
+ unlockAllNewObjects(newObjectLockDeltas, newObjectLockStates);
}
UnlockObjectsResult result = null;
@@ -687,10 +674,13 @@
if (result != null)
{
- newLockStates = Arrays.asList(result.getNewLockStates());
timeStamp = result.getTimestamp();
-
- updateLockStates(newLockStates, false, null);
+ sessionLockDeltas = result.getLockDeltas();
+ if (!ObjectUtil.isEmpty(sessionLockDeltas))
+ {
+ sessionLockStates = result.getLockStates();
+ updateLockStates(sessionLockDeltas, sessionLockStates);
+ }
}
}
finally
@@ -699,28 +689,27 @@
}
}
- if (!locksOnNewObjects.isEmpty())
+ if (!newObjectLockDeltas.isEmpty())
{
- CDOLockChangeInfo lockChangeInfo = makeLockChangeInfo(Operation.UNLOCK, lockType, getTimeStamp(), locksOnNewObjects);
+ CDOLockChangeInfo lockChangeInfo = makeLockChangeInfo(getTimeStamp(), newObjectLockDeltas, newObjectLockStates);
fireLocksChangedEvent(this, lockChangeInfo);
}
- if (newLockStates != null)
+ if (!ObjectUtil.isEmpty(sessionLockDeltas))
{
- notifyLockChanges(Operation.UNLOCK, lockType, timeStamp, newLockStates);
+ notifyLockChanges(timeStamp, sessionLockDeltas, sessionLockStates);
}
}
- protected InternalCDOLockState createUpdatedLockStateForNewObject(CDOObject object, LockType lockType, boolean on)
+ protected boolean updateLockStateOfNewObject(CDOObject object, LockType lockType, boolean on, List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
// We have no new objects, CDOTransactionImpl overrides.
- return null;
+ return false;
}
- protected Collection<CDOLockState> createUnlockedLockStatesForAllNewObjects()
+ protected void unlockAllNewObjects(List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
// We have no new objects, CDOTransactionImpl overrides.
- return null;
}
/**
@@ -792,13 +781,6 @@
}
@Override
- @Deprecated
- public String enableDurableLocking(boolean enable)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public String enableDurableLocking()
{
String oldID = null;
@@ -892,50 +874,6 @@
* @since 2.0
*/
@Override
- @Deprecated
- public CDOFeatureAnalyzer getFeatureAnalyzer()
- {
- synchronized (getViewMonitor())
- {
- lockView();
-
- try
- {
- return options().getFeatureAnalyzer();
- }
- finally
- {
- unlockView();
- }
- }
- }
-
- /**
- * @since 2.0
- */
- @Override
- @Deprecated
- public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer)
- {
- synchronized (getViewMonitor())
- {
- lockView();
-
- try
- {
- options.setFeatureAnalyzer(featureAnalyzer);
- }
- finally
- {
- unlockView();
- }
- }
- }
-
- /**
- * @since 2.0
- */
- @Override
public InternalCDOTransaction toTransaction()
{
checkActive();
@@ -1001,11 +939,11 @@
if (!ids.isEmpty())
{
CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
- CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(viewID, ids, CDOLockState.DEPTH_NONE);
+ List<CDOLockState> loadedLockStates = sessionProtocol.getLockStates2(viewID, ids, CDOLockState.DEPTH_NONE);
if (!ObjectUtil.isEmpty(loadedLockStates))
{
- lockStateCache.addLockStates(branch, Arrays.asList(loadedLockStates), null);
+ lockStateCache.addLockStates(branch, loadedLockStates, null);
}
}
}
@@ -1118,22 +1056,6 @@
revisionManager.getRevision(id, this, initialChunkSize, depth, true);
}
- @Override
- @Deprecated
- public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
- Map<CDOID, InternalCDORevision> oldRevisions, boolean async)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- @Deprecated
- public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
- Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache)
- {
- throw new UnsupportedOperationException();
- }
-
/*
* Must not by synchronized on the view!
*/
@@ -1241,7 +1163,9 @@
CDOLockChangeInfo lockChangeInfo = invalidationData.getLockChangeInfo();
if (lockChangeInfo != null)
{
- updateLockStates(lockChangeInfo.getNewLockStates(), false, null);
+ List<CDOLockDelta> lockDeltas = Arrays.asList(lockChangeInfo.getLockDeltas());
+ List<CDOLockState> lockStates = Arrays.asList(lockChangeInfo.getLockStates());
+ updateLockStates(lockDeltas, lockStates);
fireLocksChangedEvent(null, lockChangeInfo);
}
}
@@ -1266,13 +1190,6 @@
}
@Override
- @Deprecated
- public boolean isInvalidationRunnerActive()
- {
- return isInvalidating();
- }
-
- @Override
public boolean isInvalidating()
{
return invalidating;
@@ -1591,10 +1508,13 @@
{
super.doActivate();
+ lockOwner = CDOLockUtil.createLockOwner(this);
CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
+
if (durableLockingID != null)
{
- CDOBranchPoint branchPoint = sessionProtocol.openView(viewID, isReadOnly(), durableLockingID);
+ durableLockProcessor = createDurableLockProcessor();
+ CDOBranchPoint branchPoint = sessionProtocol.openView(viewID, isReadOnly(), durableLockingID, durableLockProcessor);
basicSetBranchPoint(branchPoint);
}
else
@@ -1610,8 +1530,6 @@
runnable.run();
}
- lockOwner = CDOLockUtil.createLockOwner(this);
-
if (viewLock != null && Boolean.getBoolean("org.eclipse.emf.cdo.sync.tester"))
{
new SyncTester().start();
@@ -1625,6 +1543,12 @@
{
super.doAfterActivate();
+ if (durableLockProcessor != null)
+ {
+ durableLockProcessor.run();
+ durableLockProcessor = null;
+ }
+
ExecutorService executorService = getExecutorService();
invalidator.setDelegate(executorService);
@@ -1694,6 +1618,9 @@
}
finally
{
+ List<CDOLockDelta> lockDeltas = null;
+ List<CDOLockState> lockStates = new ArrayList<>();
+
synchronized (getViewMonitor())
{
lockView();
@@ -1702,23 +1629,21 @@
{
if (session.isActive())
{
- List<CDOLockState> result = new ArrayList<>();
-
- CDOLockStateCache lockStateCache = session.getLockStateCache();
CDOBranch branch = getBranch();
- lockStateCache.removeOwner(branch, lockOwner, result::add);
-
- if (!result.isEmpty())
- {
- long timeStamp = session.getLastUpdateTime();
- notifyLockChanges(Operation.UNLOCK, null, timeStamp, result);
- }
+ CDOLockStateCache lockStateCache = session.getLockStateCache();
+ lockDeltas = lockStateCache.removeOwner(branch, lockOwner, lockStates::add);
}
}
finally
{
unlockView();
}
+
+ if (!ObjectUtil.isEmpty(lockDeltas))
+ {
+ long timeStamp = session.getLastUpdateTime();
+ notifyLockChanges(timeStamp, lockDeltas, lockStates);
+ }
}
}
@@ -1967,6 +1892,68 @@
return session.getLockStateCache().createKey(getBranch(), id);
}
+ public final DurableLockProcessor createDurableLockProcessor()
+ {
+ return new DurableLockProcessor();
+ }
+
+ @Override
+ @Deprecated
+ public void updateLockStates(CDOLockState[] newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public String enableDurableLocking(boolean enable)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ @Deprecated
+ public CDOFeatureAnalyzer getFeatureAnalyzer()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ @Deprecated
+ public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
+ Map<CDOID, InternalCDORevision> oldRevisions, boolean async)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
+ Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public boolean isInvalidationRunnerActive()
+ {
+ throw new UnsupportedOperationException();
+ }
+
public static Object getLockTarget(CDOView view, CDOID id)
{
return ((CDOViewImpl)view).getLockTarget(id);
@@ -2889,7 +2876,7 @@
* @author Caspar De Groot
* @since 4.1
*/
- private final class ViewLocksChangedEvent extends DefaultLocksChangedEvent implements CDOViewLocksChangedEvent
+ private final class ViewLocksChangedEvent extends AbstractLocksChangedEvent implements CDOViewLocksChangedEvent
{
private static final long serialVersionUID = 1L;
@@ -2910,9 +2897,9 @@
List<EObject> objects = new ArrayList<>();
CDOView view = getSource();
- for (CDOLockState lockState : getNewLockStates())
+ for (CDOLockDelta delta : getLockDeltas())
{
- Object lockedObject = lockState.getLockedObject();
+ Object lockedObject = delta.getTarget();
CDOID id = null;
if (lockedObject instanceof CDOIDAndBranch)
@@ -2942,6 +2929,12 @@
}
@Override
+ protected InternalCDOSession getSession()
+ {
+ return getSource().getSession();
+ }
+
+ @Override
protected String formatEventName()
{
return "CDOViewLocksChangedEvent";
@@ -3104,6 +3097,54 @@
/**
* @author Eike Stepper
+ */
+ public final class DurableLockProcessor implements BiConsumer<CDOID, LockGrade>, Runnable
+ {
+ private final Map<CDOID, LockGrade> lockGrades = CDOIDUtil.createMap();
+
+ private DurableLockProcessor()
+ {
+ }
+
+ @Override
+ public void accept(CDOID id, LockGrade lockGrade)
+ {
+ lockGrades.put(id, lockGrade);
+ }
+
+ @Override
+ public void run()
+ {
+ List<CDOLockDelta> lockDeltas = new ArrayList<>();
+ List<CDOLockState> lockStates = new ArrayList<>();
+
+ for (Map.Entry<CDOID, LockGrade> entry : lockGrades.entrySet())
+ {
+ CDOID id = entry.getKey();
+ LockGrade lockGrade = entry.getValue();
+
+ Object target = getLockTarget(id);
+ InternalCDOLockState lockState = (InternalCDOLockState)CDOLockUtil.createLockState(target);
+
+ lockGrade.forEachLockType(lockType -> {
+ lockDeltas.add(CDOLockUtil.createLockDelta(target, lockType, null, lockOwner));
+ lockState.addOwner(lockOwner, lockType);
+ });
+
+ lockStates.add(lockState);
+ }
+
+ if (!lockDeltas.isEmpty())
+ {
+ CDOBranch branch = getBranch();
+ CDOLockStateCache lockStateCache = session.getLockStateCache();
+ lockStateCache.updateLockStates(branch, lockDeltas, lockStates, null);
+ }
+ }
+ }
+
+ /**
+ * @author Eike Stepper
* @since 2.0
*/
public class OptionsImpl extends Notifier implements Options
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOLockStateCache.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOLockStateCache.java
index b7d88e1..1ab629a 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOLockStateCache.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOLockStateCache.java
@@ -12,12 +12,14 @@
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import java.util.Collection;
+import java.util.List;
import java.util.function.Consumer;
/**
@@ -40,11 +42,36 @@
public void addLockStates(CDOBranch branch, Collection<? extends CDOLockState> newLockStates, Consumer<CDOLockState> consumer);
- public void removeOwner(CDOBranch branch, CDOLockOwner owner, Consumer<CDOLockState> changeConsumer);
-
- public void remapOwner(CDOBranch branch, CDOLockOwner oldOwner, CDOLockOwner newOwner);
+ public void updateLockStates(CDOBranch branch, Collection<CDOLockDelta> lockDeltas, Collection<CDOLockState> lockStates, Consumer<CDOLockState> consumer);
public void removeLockStates(CDOBranch branch, Collection<CDOID> ids, Consumer<CDOLockState> consumer);
public void removeLockStates(CDOBranch branch);
+
+ public List<CDOLockDelta> removeOwner(CDOBranch branch, CDOLockOwner owner, Consumer<CDOLockState> consumer);
+
+ public void remapOwner(CDOBranch branch, CDOLockOwner oldOwner, CDOLockOwner newOwner);
+
+ /**
+ * @author Eike Stepper
+ */
+ public static final class ObjectAlreadyLockedException extends IllegalStateException
+ {
+ private static final long serialVersionUID = 1L;
+
+ public ObjectAlreadyLockedException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public ObjectAlreadyLockedException(String message)
+ {
+ super(message);
+ }
+
+ public ObjectAlreadyLockedException(CDOID id, CDOBranch branch, Throwable cause)
+ {
+ super(id + " on " + branch.getPathName() + " branch: " + cause.getMessage(), cause);
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java
index c180bed..bb86ca8 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java
@@ -27,7 +27,9 @@
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lob.CDOLob;
import org.eclipse.emf.cdo.common.lob.CDOLobInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockDelta;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocol;
@@ -52,7 +54,6 @@
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader3;
import org.eclipse.emf.cdo.view.CDOView;
-import org.eclipse.net4j.util.CheckUtil;
import org.eclipse.net4j.util.collection.UnionSet;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
@@ -78,6 +79,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
@@ -135,9 +137,9 @@
public void openView(int viewID, boolean readOnly, CDOBranchPoint branchPoint);
/**
- * @since 4.0
+ * @since 4.15
*/
- public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID);
+ public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID, BiConsumer<CDOID, LockGrade> consumer);
/**
* @since 4.0
@@ -157,14 +159,6 @@
public boolean cancelQuery(int queryId);
/**
- * @since 4.0
- * @deprecated Not called anymore. Use {@link #lockObjects2(List, int, CDOBranch, LockType, boolean, long)} instead.
- */
- @Deprecated
- public LockObjectsResult lockObjects(List<InternalCDORevision> viewedRevisions, int viewID, CDOBranch viewedBranch, LockType lockType, long timeout)
- throws InterruptedException;
-
- /**
* @since 4.1
*/
public LockObjectsResult lockObjects2(List<CDORevisionKey> revisionKeys, int viewID, CDOBranch viewedBranch, LockType lockType, boolean recursive,
@@ -177,13 +171,6 @@
boolean recursive, long timeout) throws InterruptedException;
/**
- * @since 3.0
- * @deprecated Not called anymore. Use {@link #unlockObjects2(CDOView, Collection, LockType, boolean)} instead.
- */
- @Deprecated
- public void unlockObjects(CDOView view, Collection<CDOID> objectIDs, LockType lockType);
-
- /**
* @since 4.1
*/
public UnlockObjectsResult unlockObjects2(CDOView view, Collection<CDOID> objectIDs, LockType lockType, boolean recursive);
@@ -214,27 +201,11 @@
public void loadLob(CDOLobInfo info, Object outputStreamOrWriter) throws IOException;
/**
- * @since 4.0
- * @deprecated Not called anymore. Use {@link #commitTransaction(InternalCDOCommitContext, OMMonitor)} instead.
- */
- @Deprecated
- public CommitTransactionResult commitTransaction(int transactionID, String comment, boolean releaseLocks, CDOIDProvider idProvider, CDOCommitData commitData,
- Collection<CDOLob<?>> lobs, OMMonitor monitor);
-
- /**
* @since 4.1
*/
public CommitTransactionResult commitTransaction(InternalCDOCommitContext context, OMMonitor monitor);
/**
- * @since 4.0
- * @deprecated Not called anymore. Use {@link #commitDelegation(InternalCDOCommitContext, OMMonitor)} instead.
- */
- @Deprecated
- public CommitTransactionResult commitDelegation(CDOBranch branch, String userID, String comment, CDOCommitData commitData,
- Map<CDOID, EClass> detachedObjectTypes, Collection<CDOLob<?>> lobs, OMMonitor monitor);
-
- /**
* @since 4.1
*/
public CommitTransactionResult commitDelegation(InternalCDOCommitContext context, OMMonitor monitor);
@@ -292,30 +263,15 @@
public CDOChangeSetData[] loadChangeSets(CDOBranchPointRange... ranges);
/**
- * @since 4.0
- * @deprecated As of 4.6 use {@link #loadMergeData2(CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo, CDORevisionAvailabilityInfo)}.
- */
- @Deprecated
- public Set<CDOID> loadMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
- CDORevisionAvailabilityInfo sourceBaseInfo);
-
- /**
* @since 4.6
*/
public MergeDataResult loadMergeData2(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo);
/**
- * @since 4.1
- * @deprecated Not called anymore. Use {@link #getLockStates(int, Collection, int)} instead.
+ * @since 4.15
*/
- @Deprecated
- public CDOLockState[] getLockStates(int viewID, Collection<CDOID> ids);
-
- /**
- * @since 4.4
- */
- public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids, int depth);
+ public List<CDOLockState> getLockStates2(int branchID, Collection<CDOID> ids, int depth);
/**
* @since 4.1
@@ -336,19 +292,6 @@
* Requests that the server initiate the change-credentials protocol.
* This is an optional session protocol operation.
*
- * @since 4.3
- * @deprecated As of 4.13 use {@link #requestChangeServerPassword(AtomicReference)}.
- *
- * @throws UnsupportedOperationException if the session protocol implementation does
- * not support requesting change of credentials
- */
- @Deprecated
- public void requestChangeCredentials();
-
- /**
- * Requests that the server initiate the change-credentials protocol.
- * This is an optional session protocol operation.
- *
* @since 4.13
*
* @throws UnsupportedOperationException if the session protocol implementation does
@@ -1094,7 +1037,9 @@
private CDOReferenceAdjuster referenceAdjuster;
- private CDOLockState[] newLockStates;
+ private List<CDOLockDelta> lockDeltas;
+
+ private List<CDOLockState> lockStates;
private boolean clearResourcePathCache;
@@ -1320,20 +1265,35 @@
}
/**
- * @since 4.1
+ * @since 4.15
*/
- public CDOLockState[] getNewLockStates()
+ public List<CDOLockDelta> getLockDeltas()
{
- return newLockStates;
+ return lockDeltas;
}
/**
- * @since 4.1
+ * @since 4.15
*/
- public void setNewLockStates(CDOLockState[] newLockStates)
+ public void setLockDeltas(List<CDOLockDelta> lockDeltas)
{
- CheckUtil.checkArg(newLockStates, "newLockStates");
- this.newLockStates = newLockStates;
+ this.lockDeltas = lockDeltas;
+ }
+
+ /**
+ * @since 4.15
+ */
+ public List<CDOLockState> getLockStates()
+ {
+ return lockStates;
+ }
+
+ /**
+ * @since 4.15
+ */
+ public void setLockStates(List<CDOLockState> lockStates)
+ {
+ this.lockStates = lockStates;
}
/**
@@ -1379,6 +1339,26 @@
}
/**
+ * @since 4.1
+ * @deprecated As of 4.15 use {@link #getLockDeltas()}.
+ */
+ @Deprecated
+ public CDOLockState[] getNewLockStates()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 4.1
+ * @deprecated As of 4.15 use {@link #setLockStates(List)}.
+ */
+ @Deprecated
+ public void setNewLockStates(CDOLockState[] newLockStates)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Simon McDuff
@@ -1423,38 +1403,35 @@
*/
public static final class LockObjectsResult
{
- private boolean successful;
+ private final boolean successful;
- private boolean timedOut;
+ private final boolean timedOut;
- private boolean waitForUpdate;
+ private final boolean waitForUpdate;
- private long requiredTimestamp;
+ private final long requiredTimestamp;
- private long timestamp;
+ private final long timestamp;
- private CDORevisionKey[] staleRevisions;
+ private final CDORevisionKey[] staleRevisions;
- private CDOLockState[] newLockStates;
+ private final List<CDOLockDelta> lockDeltas;
- @Deprecated
- public LockObjectsResult(boolean successful, boolean timedOut, boolean waitForUpdate, long requiredTimestamp, CDORevisionKey[] staleRevisions)
- {
- throw new AssertionError("Deprecated");
- }
+ private final List<CDOLockState> lockStates;
/**
- * @since 4.1
+ * @since 4.15
*/
public LockObjectsResult(boolean successful, boolean timedOut, boolean waitForUpdate, long requiredTimestamp, CDORevisionKey[] staleRevisions,
- CDOLockState[] newLockStates, long timestamp)
+ List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates, long timestamp)
{
this.successful = successful;
this.timedOut = timedOut;
this.waitForUpdate = waitForUpdate;
this.requiredTimestamp = requiredTimestamp;
this.staleRevisions = staleRevisions;
- this.newLockStates = newLockStates;
+ this.lockDeltas = lockDeltas;
+ this.lockStates = lockStates;
this.timestamp = timestamp;
}
@@ -1478,19 +1455,6 @@
return requiredTimestamp;
}
- public CDORevisionKey[] getStaleRevisions()
- {
- return staleRevisions;
- }
-
- /**
- * @since 4.1
- */
- public CDOLockState[] getNewLockStates()
- {
- return newLockStates;
- }
-
/**
* @since 4.1
*/
@@ -1498,6 +1462,53 @@
{
return timestamp;
}
+
+ public CDORevisionKey[] getStaleRevisions()
+ {
+ return staleRevisions;
+ }
+
+ /**
+ * @since 4.15
+ */
+ public List<CDOLockDelta> getLockDeltas()
+ {
+ return lockDeltas;
+ }
+
+ /**
+ * @since 4.15
+ */
+ public List<CDOLockState> getLockStates()
+ {
+ return lockStates;
+ }
+
+ /**
+ * @since 4.1
+ * @deprecated As of 4.15 use {@link #getLockStates()}.
+ */
+ @Deprecated
+ public CDOLockState[] getNewLockStates()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
+ public LockObjectsResult(boolean successful, boolean timedOut, boolean waitForUpdate, long requiredTimestamp, CDORevisionKey[] staleRevisions)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 4.1
+ */
+ @Deprecated
+ public LockObjectsResult(boolean successful, boolean timedOut, boolean waitForUpdate, long requiredTimestamp, CDORevisionKey[] staleRevisions,
+ CDOLockState[] newLockStates, long timestamp)
+ {
+ throw new UnsupportedOperationException();
+ }
}
/**
@@ -1507,23 +1518,87 @@
*/
public static final class UnlockObjectsResult
{
- private CDOLockState[] newLockStates;
+ private final long timestamp;
- private long timestamp;
+ private final List<CDOLockDelta> lockDeltas;
- public UnlockObjectsResult(CDOLockState[] newLockStates, long timestamp)
+ private final List<CDOLockState> lockStates;
+
+ /**
+ * @since 4.15
+ */
+ public UnlockObjectsResult(long timestamp, List<CDOLockDelta> lockDeltas, List<CDOLockState> lockStates)
{
- this.newLockStates = newLockStates;
- }
-
- public CDOLockState[] getNewLockStates()
- {
- return newLockStates;
+ this.timestamp = timestamp;
+ this.lockDeltas = lockDeltas;
+ this.lockStates = lockStates;
}
public long getTimestamp()
{
return timestamp;
}
+
+ /**
+ * @since 4.15
+ */
+ public List<CDOLockDelta> getLockDeltas()
+ {
+ return lockDeltas;
+ }
+
+ /**
+ * @since 4.15
+ */
+ public List<CDOLockState> getLockStates()
+ {
+ return lockStates;
+ }
+
+ @Deprecated
+ public UnlockObjectsResult(CDOLockState[] newLockStates, long timestamp)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated As of 4.15 use {@link #getLockStates()}.
+ */
+ @Deprecated
+ public CDOLockState[] getNewLockStates()
+ {
+ throw new UnsupportedOperationException();
+ }
}
+
+ @Deprecated
+ public LockObjectsResult lockObjects(List<InternalCDORevision> viewedRevisions, int viewID, CDOBranch viewedBranch, LockType lockType, long timeout)
+ throws InterruptedException;
+
+ @Deprecated
+ public void unlockObjects(CDOView view, Collection<CDOID> objectIDs, LockType lockType);
+
+ @Deprecated
+ public CommitTransactionResult commitTransaction(int transactionID, String comment, boolean releaseLocks, CDOIDProvider idProvider, CDOCommitData commitData,
+ Collection<CDOLob<?>> lobs, OMMonitor monitor);
+
+ @Deprecated
+ public CommitTransactionResult commitDelegation(CDOBranch branch, String userID, String comment, CDOCommitData commitData,
+ Map<CDOID, EClass> detachedObjectTypes, Collection<CDOLob<?>> lobs, OMMonitor monitor);
+
+ @Deprecated
+ public Set<CDOID> loadMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
+ CDORevisionAvailabilityInfo sourceBaseInfo);
+
+ @Deprecated
+ public CDOLockState[] getLockStates(int viewID, Collection<CDOID> ids);
+
+ @Deprecated
+ public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids, int depth);
+
+ @Deprecated
+ public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID);
+
+ @Deprecated
+ public void requestChangeCredentials();
}
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 9451340..6d706cf 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
@@ -77,12 +77,6 @@
public void setViewSet(InternalCDOViewSet viewSet);
- @Deprecated
- public CDOFeatureAnalyzer getFeatureAnalyzer();
-
- @Deprecated
- public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer);
-
/**
* Returns an unmodifiable map of the objects managed by this view.
*
@@ -115,21 +109,6 @@
public void handleObjectStateChanged(InternalCDOObject object, CDOState oldState, CDOState newState);
/**
- * @deprecated As of 4.2. use {@link #invalidate(CDOBranch, long, List, List, Map, boolean, boolean)}
- */
- @Deprecated
- public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
- Map<CDOID, InternalCDORevision> oldRevisions, boolean async);
-
- /**
- * @since 4.2
- * @deprecated As of 4.6. use {@link #invalidate(ViewInvalidationData)}
- */
- @Deprecated
- public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
- Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache);
-
- /**
* @since 4.6
*/
public void invalidate(ViewInvalidationData invalidationData);
@@ -153,12 +132,6 @@
public CDOID getResourceNodeID(String path);
- /**
- * @deprecated No longer supported.
- */
- @Deprecated
- public void registerProxyResource(CDOResourceImpl resource);
-
public void registerObject(InternalCDOObject object);
public void deregisterObject(InternalCDOObject object);
@@ -203,18 +176,6 @@
public boolean isObjectLocked(CDOObject object, LockType lockType, boolean byOthers);
/**
- * @since 4.12
- * @deprecated As of 4.15 use {@link #updateLockStates(Collection, boolean, Consumer)}.
- */
- @Deprecated
- public void updateLockStates(CDOLockState[] newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer);
-
- /**
- * @since 4.15
- */
- public void updateLockStates(Collection<? extends CDOLockState> newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer);
-
- /**
* @since 4.15
*/
public CDOLockState[] getLockStates(Collection<CDOID> ids, boolean loadOnDemand);
@@ -254,6 +215,40 @@
*/
public void inverseClose();
+ @Deprecated
+ public CDOFeatureAnalyzer getFeatureAnalyzer();
+
+ @Deprecated
+ public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer);
+
+ /**
+ * @deprecated As of 4.2. use {@link #invalidate(CDOBranch, long, List, List, Map, boolean, boolean)}
+ */
+ @Deprecated
+ public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
+ Map<CDOID, InternalCDORevision> oldRevisions, boolean async);
+
+ /**
+ * @since 4.2
+ * @deprecated As of 4.6. use {@link #invalidate(ViewInvalidationData)}
+ */
+ @Deprecated
+ public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects,
+ Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache);
+
+ /**
+ * @deprecated No longer supported.
+ */
+ @Deprecated
+ public void registerProxyResource(CDOResourceImpl resource);
+
+ /**
+ * @since 4.12
+ * @deprecated As of 4.15 use {@link CDOLockStateCache#updateLockStates(CDOBranch, Collection, Collection, Consumer)}.
+ */
+ @Deprecated
+ public void updateLockStates(CDOLockState[] newLockStates, boolean loadObjectsOnDemand, Consumer<CDOLockState> consumer);
+
/**
* 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.
diff --git a/plugins/org.eclipse.net4j.tests/.classpath b/plugins/org.eclipse.net4j.tests/.classpath
index 3e5654f..a42a828 100644
--- a/plugins/org.eclipse.net4j.tests/.classpath
+++ b/plugins/org.eclipse.net4j.tests/.classpath
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src">
<attributes>
diff --git a/plugins/org.eclipse.net4j.tests/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.net4j.tests/.settings/org.eclipse.jdt.core.prefs
index d01a602..dbac0b5 100644
--- a/plugins/org.eclipse.net4j.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/plugins/org.eclipse.net4j.tests/.settings/org.eclipse.jdt.core.prefs
@@ -15,9 +15,9 @@
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -32,6 +32,7 @@
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
@@ -86,6 +87,7 @@
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
@@ -115,7 +117,8 @@
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH,LOW,LOW,LOW,LOW,LOW
org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,PERF,MEM,POLISH,@generated NOT,@ADDED
diff --git a/plugins/org.eclipse.net4j.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.tests/META-INF/MANIFEST.MF
index fa19b34..503b440 100644
--- a/plugins/org.eclipse.net4j.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.net4j.tests/META-INF/MANIFEST.MF
@@ -7,7 +7,7 @@
Bundle-Localization: plugin
Bundle-ActivationPolicy: lazy
Bundle-Activator: org.eclipse.net4j.tests.bundle.OM$Activator
-Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ClassPath: .
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)";visibility:=reexport,
org.eclipse.net4j.ws;bundle-version="[1.0.0,2.0.0)";visibility:=reexport,
@@ -26,9 +26,13 @@
org.eclipse.jetty.websocket.servlet;bundle-version="[10.0.0,11.0.0)",
org.eclipse.jetty.websocket.server;bundle-version="[10.0.0,11.0.0)",
org.eclipse.jetty.websocket.client;bundle-version="[10.0.0,11.0.0)",
- org.eclipse.jetty.websocket.api;bundle-version="[10.0.0,11.0.0)"
+ org.eclipse.jetty.websocket.api;bundle-version="[10.0.0,11.0.0)",
+ org.eclipse.jetty.websocket.core.client;bundle-version="[10.0.0,11.0.0)",
+ org.eclipse.jetty.websocket.core.common;bundle-version="[10.0.0,11.0.0)",
+ org.eclipse.jetty.websocket.core.server;bundle-version="[10.0.0,11.0.0)"
Import-Package: javax.servlet;version="[2.3.0,5.0.0)",
- javax.servlet.http;version="[2.3.0,5.0.0)"
+ javax.servlet.http;version="[2.3.0,5.0.0)",
+ org.slf4j;version="[1.0.0,2.0.0)"
Export-Package: org.eclipse.net4j.tests;version="4.2.6",
org.eclipse.net4j.tests.apps;version="4.2.6",
org.eclipse.net4j.tests.bugzilla;version="4.2.6",
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/AllTests.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/AllTests.java
index c552103..10379cb 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/AllTests.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/AllTests.java
@@ -22,6 +22,7 @@
import org.eclipse.net4j.util.tests.ExpectedIOTest;
import org.eclipse.net4j.util.tests.ExtendedIOTest;
import org.eclipse.net4j.util.tests.MultiMapTest;
+import org.eclipse.net4j.util.tests.RWOLockManagerTest;
import org.eclipse.net4j.util.tests.RollingLogTest;
import org.eclipse.net4j.util.tests.RoundRobinBlockingQueueTest;
import org.eclipse.net4j.util.tests.SecurityTest;
@@ -60,6 +61,7 @@
suite.addTestSuite(SecurityTest.class);
suite.addTestSuite(ExecutorWorkSerializerTest.class);
suite.addTestSuite(RoundRobinBlockingQueueTest.class);
+ suite.addTestSuite(RWOLockManagerTest.class);
suite.addTestSuite(ExpectedIOTest.class);
suite.addTestSuite(RollingLogTest.class);
suite.addTestSuite(Bugzilla_262875_Test.class);
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/RWOLockManagerTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/RWOLockManagerTest.java
new file mode 100644
index 0000000..bfbb07d
--- /dev/null
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/RWOLockManagerTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2014, 2018 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.util.tests;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.RWOLockManager;
+import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
+import org.eclipse.net4j.util.io.IOUtil;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Eike Stepper
+ */
+public class RWOLockManagerTest extends AbstractOMTest
+{
+ private static final int USERS = 10;
+
+ private static final int ALLOCATIONS = 10;
+
+ private static final int RETRIES = 5;
+
+ private static final Set<Object> EXCLUSIVE_RESOURCE = Collections.singleton(new Object()
+ {
+ @Override
+ public String toString()
+ {
+ return "EXCLUSIVE_RESOURCE";
+ }
+ });
+
+ public void testRWOLockManager() throws Exception
+ {
+ AtomicInteger resource = new AtomicInteger(-1);
+ RWOLockManager<Object, User> lockManager = new RWOLockManager<>();
+
+ User[] users = new User[USERS];
+ User[] allocators = new User[USERS * ALLOCATIONS];
+
+ CountDownLatch started = new CountDownLatch(1);
+ CountDownLatch finished = new CountDownLatch(USERS);
+
+ for (int userID = 0; userID < USERS; userID++)
+ {
+ users[userID] = new User(userID, started, finished, allocators, lockManager, resource);
+ }
+
+ for (int userID = 0; userID < USERS; userID++)
+ {
+ users[userID].start();
+ }
+
+ started.countDown();
+ await(finished);
+ IOUtil.OUT().println("FINISHED");
+
+ Exception exception = null;
+ for (int userID = 0; userID < USERS; userID++)
+ {
+ Exception ex = users[userID].getException();
+ if (ex != null)
+ {
+ exception = ex;
+ ex.printStackTrace();
+ }
+ }
+
+ if (exception != null)
+ {
+ throw exception;
+ }
+
+ IOUtil.OUT().println("SUCCESS");
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class User extends Thread
+ {
+ private final CountDownLatch started;
+
+ private final CountDownLatch finished;
+
+ private final User[] allocators;
+
+ private final RWOLockManager<Object, User> lockManager;
+
+ private final AtomicInteger resource;
+
+ private Exception exception;
+
+ public User(int userID, CountDownLatch started, CountDownLatch finished, User[] allocators, RWOLockManager<Object, User> lockManager,
+ AtomicInteger resource)
+ {
+ super("User-" + userID);
+ this.started = started;
+ this.finished = finished;
+ this.allocators = allocators;
+ this.lockManager = lockManager;
+ this.resource = resource;
+ }
+
+ public Exception getException()
+ {
+ return exception;
+ }
+
+ @Override
+ public void run()
+ {
+ await(started);
+
+ try
+ {
+ for (int allocation = 0; allocation < ALLOCATIONS; allocation++)
+ {
+ for (int retry = RETRIES; retry >= 0; --retry)
+ {
+ try
+ {
+ lockManager.lock(this, EXCLUSIVE_RESOURCE, LockType.WRITE, 1, 10000000, null, null);
+ break;
+ }
+ catch (TimeoutRuntimeException ex)
+ {
+ if (retry == 0)
+ {
+ exception = ex;
+ return;
+ }
+
+ msg("Lock timed out. Trying again...");
+ }
+ catch (InterruptedException ex)
+ {
+ exception = ex;
+ return;
+ }
+ }
+
+ try
+ {
+ int id = resource.get() + 1;
+ if (allocators[id] != null)
+ {
+ throw new IllegalStateException(id + " already allocated by " + allocators[id]);
+ }
+
+ allocators[id] = this;
+ resource.set(id);
+ msg("ALLOCATED " + id);
+ }
+ catch (Exception ex)
+ {
+ exception = ex;
+ return;
+ }
+ finally
+ {
+ lockManager.unlock(this, EXCLUSIVE_RESOURCE, LockType.WRITE, 1, null, null);
+ }
+ }
+ }
+ finally
+ {
+ finished.countDown();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return getName();
+ }
+
+ private void msg(String string)
+ {
+ IOUtil.OUT().println(getName() + ": " + string);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.net4j.util/.settings/.api_filters b/plugins/org.eclipse.net4j.util/.settings/.api_filters
index b34473e..8d9b14c 100644
--- a/plugins/org.eclipse.net4j.util/.settings/.api_filters
+++ b/plugins/org.eclipse.net4j.util/.settings/.api_filters
@@ -89,7 +89,25 @@
<filter id="336658481">
<message_arguments>
<message_argument value="org.eclipse.net4j.util.concurrent.RWOLockManager"/>
- <message_argument value="ALL_LOCK_TYPES"/>
+ <message_argument value="read"/>
+ </message_arguments>
+ </filter>
+ <filter id="336658481">
+ <message_arguments>
+ <message_argument value="org.eclipse.net4j.util.concurrent.RWOLockManager"/>
+ <message_argument value="rwAccess"/>
+ </message_arguments>
+ </filter>
+ <filter id="336658481">
+ <message_arguments>
+ <message_argument value="org.eclipse.net4j.util.concurrent.RWOLockManager"/>
+ <message_argument value="write"/>
+ </message_arguments>
+ </filter>
+ <filter id="576725006">
+ <message_arguments>
+ <message_argument value="IRWOLockManager<OBJECT, CONTEXT>"/>
+ <message_argument value="RWOLockManager<OBJECT, CONTEXT>"/>
</message_arguments>
</filter>
</resource>
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/CollectionUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/CollectionUtil.java
index b918849..b66aad3 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/CollectionUtil.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/CollectionUtil.java
@@ -74,6 +74,15 @@
/**
* @since 3.16
*/
+ public static <T> T first(Collection<? extends T> c)
+ {
+ Iterator<? extends T> it = c.iterator();
+ return it.hasNext() ? it.next() : null;
+ }
+
+ /**
+ * @since 3.16
+ */
public static <K, V> List<K> removeAll(Map<K, V> map, BiPredicate<K, V> predicate)
{
List<K> keys = new ArrayList<>();
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/Access.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/Access.java
new file mode 100644
index 0000000..1b06c6e
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/Access.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.util.concurrent;
+
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * @author Eike Stepper
+ * @since 3.16
+ */
+public final class Access implements AutoCloseable
+{
+ private final Lock lock;
+
+ public Access(Lock lock)
+ {
+ this.lock = lock;
+ }
+
+ public Lock getLock()
+ {
+ return lock;
+ }
+
+ public Condition newCondition()
+ {
+ return lock.newCondition();
+ }
+
+ public Access access()
+ {
+ lock.lock();
+ return this;
+ }
+
+ @Override
+ public void close()
+ {
+ lock.unlock();
+ }
+}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/Holder.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/Holder.java
new file mode 100644
index 0000000..0e54179
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/Holder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.util.concurrent;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * @author Eike Stepper
+ * @since 3.16
+ */
+public final class Holder<T> implements Consumer<T>, Supplier<T>
+{
+ private T element;
+
+ public Holder(T element)
+ {
+ set(element);
+ }
+
+ public Holder()
+ {
+ }
+
+ @Override
+ public T get()
+ {
+ return element;
+ }
+
+ public T set(T element)
+ {
+ T oldElement = this.element;
+ this.element = element;
+ return oldElement;
+ }
+
+ @Override
+ public void accept(T element)
+ {
+ set(element);
+ }
+}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWLockManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWLockManager.java
index c7cd4af..4e8a500 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWLockManager.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWLockManager.java
@@ -22,8 +22,10 @@
*/
public interface IRWLockManager<OBJECT, CONTEXT>
{
+ @Deprecated
public static final int WAIT = 0;
+ @Deprecated
public static final int NO_WAIT = 1;
public void lock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout) throws InterruptedException;
@@ -31,7 +33,7 @@
public void lock(LockType type, CONTEXT context, OBJECT objectToLock, long timeout) throws InterruptedException;
/**
- * Attempts to release for a given locktype, context and objects.
+ * Attempts to release for a given lock type, context and objects.
*
* @throws IllegalMonitorStateException
* Unlocking objects without lock.
@@ -57,6 +59,6 @@
/**
* @since 3.2
*/
- OPTION
+ OPTION;
}
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java
index 63ae0e8..f1bc175 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java
@@ -14,6 +14,7 @@
import java.util.Collection;
import java.util.List;
+import java.util.function.Consumer;
/**
* A {@link IRWLockManager read/write lock manager} that supports {@link IRWLockManager.LockType#OPTION write option}
@@ -21,27 +22,110 @@
*
* @author Caspar De Groot
* @since 3.2
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
*/
public interface IRWOLockManager<OBJECT, CONTEXT> extends IRWLockManager<OBJECT, CONTEXT>
{
/**
- * Adds locks of the given type, owned by the given context on the given objects.
+ * @since 3.16
*/
- public List<LockState<OBJECT, CONTEXT>> lock2(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout)
+ public static final Collection<?> ALL_OBJECTS = null;
+
+ /**
+ * @since 3.16
+ */
+ public static final LockType ALL_LOCK_TYPES = null;
+
+ /**
+ * @since 3.16
+ */
+ public static final int ALL_LOCKS = -1;
+
+ /**
+ * @since 3.16
+ */
+ public static final long NO_TIMEOUT = -1;
+
+ /**
+ * @since 3.16
+ */
+ public long getModCount();
+
+ /**
+ * Adds locks of the given lockType, owned by the given context to the given objects.
+ *
+ * @param context The lock context to add from the <code>objects</code>. Must not be <code>null</code>.
+ * @param objects The objects to lock. Must not be <code>null</code>.
+ * @param lockType The type of lock to add to the <code>objects</code>. Must not be <code>null</code>.
+ * @param count The number of locks to add to each of the <code>objects</code>.
+ * @param timeout The period in milliseconds after that a {@link TimeoutRuntimeException} is thrown if some or all of the
+ * <code>objects</code> could not be locked, or {@link #NO_TIMEOUT} to attempt forever to acquire the requested locks.
+ * @param deltaHandler A handler that is notified with each delta in a {@link LockState lock state}, or <code>null</code> if no such notification is needed.
+ * The handler is notified at most once per delta, but it can happen that the handler is notified before the lock operation finally fails
+ * with one of the specified exceptions. The notification handling should be fast because notifications occur while the calling thread is synchronized on this lock manager.
+ * @param stateHandler A handler that is notified with each new {@link LockState lock state}, or <code>null</code> if no such notification is needed..
+ * The handler is notified at most once per lock state, but it can happen that the handler is notified before the lock operation finally fails
+ * with one of the specified exceptions. The notification handling should be fast because notifications occur while the calling thread is synchronized on this lock manager.
+ * @return The new {@link #getModCount() modification count}.
+ * @throws InterruptedException If the calling thread is interrupted.
+ * @throws TimeoutRuntimeException If the timeout period has expired and some or all of the <code>objects</code> could not be locked.
+ * @since 3.16
+ */
+ public long lock(CONTEXT context, Collection<? extends OBJECT> objects, LockType lockType, int count, long timeout, //
+ LockDeltaHandler<OBJECT, CONTEXT> deltaHandler, Consumer<LockState<OBJECT, CONTEXT>> stateHandler) //
+ throws InterruptedException, TimeoutRuntimeException;
+
+ /**
+ * Removes locks of the given lockType, owned by the given context from the given objects.
+ *
+ * @param context The lock context to remove from the <code>objects</code>. Must not be <code>null</code>.
+ * @param objects The objects to unlock, or {@link #ALL_OBJECTS} to unlock all objects of the <code>context</code>.
+ * @param lockType The type of lock to remove from the <code>objects</code>, or {@link #ALL_LOCK_TYPES} to remove the locks of all types.
+ * @param count The number of locks to remove from each of the <code>objects</code>, or {@link #ALL_LOCKS} to remove all locks.
+ * @param deltaHandler A handler that is notified with each delta in a {@link LockState}, or <code>null</code> if no such notification is needed.
+ * @param stateHandler A handler that is notified with each new {@link LockState}, or <code>null</code> if no such notification is needed.
+ * @since 3.16
+ */
+ public long unlock(CONTEXT context, Collection<? extends OBJECT> objects, LockType lockType, int count, //
+ LockDeltaHandler<OBJECT, CONTEXT> deltaHandler, Consumer<LockState<OBJECT, CONTEXT>> stateHandler);
+
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> lock2(LockType lockType, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout)
throws InterruptedException;
- /**
- * Removes all locks of the given type, owned by the given context on the given objects.
- */
- public List<LockState<OBJECT, CONTEXT>> unlock2(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock);
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> unlock2(LockType lockType, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock);
- /**
- * Removes all locks owned by the given context on any objects.
- */
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context, Collection<? extends OBJECT> objectsToUnlock);
+
+ @Deprecated
public List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context);
+ @Override
+ @Deprecated
+ public void lock(LockType lockType, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout) throws InterruptedException;
+
+ @Override
+ @Deprecated
+ public void lock(LockType lockType, CONTEXT context, OBJECT objectToLock, long timeout) throws InterruptedException;
+
+ @Override
+ @Deprecated
+ public void unlock(LockType lockType, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock);
+
+ @Override
+ @Deprecated
+ public void unlock(CONTEXT context);
+
/**
- * Removes all locks owned by the given context.
+ * @author Eike Stepper
+ * @since 3.16
*/
- public List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context, Collection<? extends OBJECT> objectsToUnlock);
+ @FunctionalInterface
+ public interface LockDeltaHandler<OBJECT, CONTEXT>
+ {
+ public void handleLockDelta(CONTEXT context, OBJECT object, LockType lockType, int oldCount, int newCount);
+ }
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java
index 7c57e26..ee49e90 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java
@@ -7,15 +7,14 @@
*
* Contributors:
* Caspar De Groot - initial API and implementation
+ * Eike Stepper - major reimplementation
*/
package org.eclipse.net4j.util.concurrent;
-import org.eclipse.net4j.internal.util.bundle.OM;
import org.eclipse.net4j.util.CheckUtil;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.collection.HashBag;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
-import org.eclipse.net4j.util.om.trace.ContextTracer;
import java.util.ArrayList;
import java.util.Collection;
@@ -23,11 +22,14 @@
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.Set;
+import java.util.StringJoiner;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
/**
* Keeps track of locks on objects. Locks are owned by contexts. A particular combination of locks and their owners, for
@@ -35,17 +37,31 @@
* deciding whether or not a new lock can be granted, based on the locks already present.
*
* @author Caspar De Groot
+ * @author Eike Stepper
* @since 3.2
*/
public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWOLockManager<OBJECT, CONTEXT>
{
- private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_CONCURRENCY, RWOLockManager.class);
+ private static final LockType[][] LOCK_TYPE_ARRAYS = { { LockType.values()[0] }, { LockType.values()[1] }, { LockType.values()[2] } };
- private static final ThreadLocal<Boolean> UNLOCK_ALL = new ThreadLocal<>();
+ private static final LockType[] ALL_LOCK_TYPES_ARRAY = LockType.values();
- private static final LockType[] ALL_LOCK_TYPES = LockType.values();
+ /**
+ * @since 3.16
+ */
+ protected final ReentrantReadWriteAccess rwAccess = new ReentrantReadWriteAccess(true);
- private final List<LockState<OBJECT, CONTEXT>> emptyResult = Collections.emptyList();
+ /**
+ * @since 3.16
+ */
+ protected final Access read = rwAccess.readAccess();
+
+ /**
+ * @since 3.16
+ */
+ protected final Access write = rwAccess.writeAccess();
+
+ private final Condition unlocked = rwAccess.newCondition();
private final Map<OBJECT, LockState<OBJECT, CONTEXT>> objectToLockStateMap = createObjectToLocksMap();
@@ -58,228 +74,343 @@
*/
private final Map<CONTEXT, Set<LockState<OBJECT, CONTEXT>>> contextToLockStates = createContextToLocksMap();
- @Override
- public void lock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout) throws InterruptedException
+ private volatile long modCount;
+
+ public RWOLockManager()
{
- lock2(type, context, objectsToLock, timeout);
}
+ /**
+ * @category Read Access
+ */
@Override
- public List<LockState<OBJECT, CONTEXT>> lock2(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout)
- throws InterruptedException
+ public long getModCount()
{
- int count = objectsToLock.size();
- if (count == 0)
+ try (Access access = read.access())
{
- return emptyResult;
+ return modCount;
}
+ }
- if (TRACER.isEnabled())
+ /**
+ * @since 3.16
+ * @category Write Access
+ */
+ @Override
+ public long lock(CONTEXT context, Collection<? extends OBJECT> objects, LockType lockType, int count, long timeout, //
+ LockDeltaHandler<OBJECT, CONTEXT> deltaHandler, Consumer<LockState<OBJECT, CONTEXT>> stateHandler) //
+ throws InterruptedException, TimeoutRuntimeException
+ {
+ CheckUtil.checkArg(context, "context");
+ CheckUtil.checkArg(objects, "objects");
+ CheckUtil.checkArg(lockType, "lockType");
+ CheckUtil.checkArg(count >= 0, "count >= 0");
+
+ long deadline = timeout == NO_TIMEOUT ? Long.MAX_VALUE : currentTimeMillis() + timeout;
+
+ try (Access access = write.access())
{
- TRACER.format("Lock: {0} --> {1}", context, objectsToLock); //$NON-NLS-1$
- }
+ if (ObjectUtil.isEmpty(objects) || count == 0)
+ {
+ // Nothing to do.
+ return modCount;
+ }
- // Must come before the synchronized block!
- long startTime = timeout == WAIT ? 0L : currentTimeMillis();
+ // Populate a mutable list of objects to lock. This list will shrink while objects are successfully locked below.
+ List<OBJECT> objectsToLock = new ArrayList<>(objects);
- // Do not synchronize the entire method as it would corrupt the timeout!
- synchronized (this)
- {
+ // Remember the locked objects for the case that an exception occurs, so that their locks can be removed again.
+ List<OBJECT> lockedObjects = new ArrayList<>(objectsToLock.size());
+
for (;;)
{
- ArrayList<LockState<OBJECT, CONTEXT>> lockStates = getLockStatesForContext(type, context, objectsToLock);
- if (lockStates != null)
+ for (Iterator<OBJECT> it = objectsToLock.iterator(); it.hasNext();)
{
- for (int i = 0; i < count; i++)
+ OBJECT lockedObject = it.next();
+ LockState<OBJECT, CONTEXT> lockState = getOrCreateLockState(lockedObject);
+
+ if (lockState.canLock(lockType, context))
{
- LockState<OBJECT, CONTEXT> lockState = lockStates.get(i);
- lockState.lock(type, context);
- addContextToLockStateMapping(context, lockState);
- }
+ int oldCount = lockState.getLockCount(lockType, context);
+ int newCount = lockState.lock(lockType, context, count);
- return lockStates;
- }
-
- wait(startTime, timeout);
- }
- }
- }
-
- @Override
- public void lock(LockType type, CONTEXT context, OBJECT objectToLock, long timeout) throws InterruptedException
- {
- // Do not synchronize the entire method as it would corrupt the timeout!
- lock(type, context, Collections.singleton(objectToLock), timeout);
- }
-
- @Override
- public void unlock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
- {
- unlock2(type, context, objectsToUnlock);
- }
-
- @Override
- public List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
- {
- return unlock2(ALL_LOCK_TYPES, context, objectsToUnlock);
- }
-
- @Override
- public List<LockState<OBJECT, CONTEXT>> unlock2(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
- {
- return unlock2(new LockType[] { type }, context, objectsToUnlock);
- }
-
- private List<LockState<OBJECT, CONTEXT>> unlock2(LockType[] types, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
- {
- if (objectsToUnlock.isEmpty())
- {
- return emptyResult;
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Unlock: {0} --> {1}", context, objectsToUnlock); //$NON-NLS-1$
- }
-
- Set<LockState<OBJECT, CONTEXT>> result = new HashSet<>();
- boolean unlockAll = UNLOCK_ALL.get() == Boolean.TRUE;
-
- synchronized (this)
- {
- for (OBJECT o : objectsToUnlock)
- {
- LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(o);
- if (lockState != null)
- {
- for (LockType type : types)
- {
- while (lockState.canUnlock(type, context))
+ if (newCount != oldCount)
{
- lockState.unlock(type, context);
- result.add(lockState);
+ addContextToLockStateMapping(context, lockState);
- if (!unlockAll)
+ if (deltaHandler != null)
{
- break;
+ deltaHandler.handleLockDelta(context, lockedObject, lockType, oldCount, newCount);
}
}
+
+ if (stateHandler != null)
+ {
+ stateHandler.accept(lockState);
+ }
+
+ lockedObjects.add(lockedObject);
+ it.remove();
+ }
+ }
+
+ if (objectsToLock.isEmpty())
+ {
+ return ++modCount;
+ }
+
+ try
+ {
+ long waitTime = deadline - currentTimeMillis();
+ if (waitTime <= 0)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Could not lock objects within ");
+ builder.append(timeout);
+ builder.append(" milliseconds: ");
+
+ StringJoiner joiner = new StringJoiner(", ", "Could not lock objects within " + timeout + " milliseconds: ", "");
+ for (OBJECT objectToLock : objectsToLock)
+ {
+ LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(objectToLock);
+ if (lockState != null)
+ {
+ joiner.add(lockState.toString());
+ }
+ }
+
+ throw new TimeoutRuntimeException(builder.toString());
+ }
+
+ // Give others a chance to unlock objects.
+ unlocked.await(waitTime, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException | TimeoutRuntimeException ex)
+ {
+ unlock(context, lockedObjects, lockType, count, null, null);
+
+ --modCount; // Fix the modCount that was increased by unlock();
+ throw ex;
+ }
+ }
+ }
+ }
+
+ private LockState<OBJECT, CONTEXT> getOrCreateLockState(OBJECT object)
+ {
+ return objectToLockStateMap.computeIfAbsent(object, o -> new LockState<>(o));
+ }
+
+ private void addContextToLockStateMapping(CONTEXT context, LockState<OBJECT, CONTEXT> lockState)
+ {
+ contextToLockStates.computeIfAbsent(context, c -> new HashSet<>()).add(lockState);
+ }
+
+ /**
+ * @category Write Access
+ */
+ @Override
+ public long unlock(CONTEXT context, Collection<? extends OBJECT> objects, LockType lockType, int count, //
+ LockDeltaHandler<OBJECT, CONTEXT> deltaHandler, Consumer<LockState<OBJECT, CONTEXT>> stateHandler)
+ {
+ CheckUtil.checkArg(context, "context");
+ CheckUtil.checkArg(count >= -1, "count >= -1");
+
+ LockType[] lockTypes = lockType == null ? ALL_LOCK_TYPES_ARRAY : LOCK_TYPE_ARRAYS[lockType.ordinal()];
+ List<LockState<OBJECT, CONTEXT>> modifiedLockStates = new ArrayList<>();
+
+ try (Access access = write.access())
+ {
+ if (objects == null)
+ {
+ if (count == 0)
+ {
+ // Nothing to do.
+ return modCount;
+ }
+
+ Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.get(context);
+ if (lockStates == null)
+ {
+ // We have no locks, nothing to do.
+ return modCount;
+ }
+
+ for (LockState<OBJECT, CONTEXT> lockState : lockStates)
+ {
+ OBJECT object = lockState.getLockedObject();
+ doUnlock(context, object, lockTypes, count, deltaHandler, stateHandler, lockState, modifiedLockStates);
+ }
+ }
+ else
+ {
+ if (objects.isEmpty())
+ {
+ return modCount;
+ }
+
+ for (OBJECT object : objects)
+ {
+ LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(object);
+ if (lockState != null)
+ {
+ doUnlock(context, object, lockTypes, count, deltaHandler, stateHandler, lockState, modifiedLockStates);
}
}
}
- for (LockState<OBJECT, CONTEXT> lockState : result)
+ removeLockStates(context, modifiedLockStates);
+
+ // Wake up blocked lockers.
+ unlocked.signalAll();
+
+ return ++modCount;
+ }
+ }
+
+ private void doUnlock(CONTEXT context, OBJECT object, LockType[] lockTypes, int count, //
+ LockDeltaHandler<OBJECT, CONTEXT> deltaHandler, Consumer<LockState<OBJECT, CONTEXT>> stateHandler, //
+ LockState<OBJECT, CONTEXT> lockState, List<LockState<OBJECT, CONTEXT>> modifiedLockStates)
+ {
+ for (LockType lockType : lockTypes)
+ {
+ if (lockState.canUnlock(lockType, context))
{
- if (!lockState.hasLocks(context))
+ int oldCount = lockState.getLockCount(lockType, context);
+ int newCount = lockState.unlock(lockType, context, count);
+
+ if (newCount != oldCount)
{
- removeLockStateForContext(context, lockState);
+ modifiedLockStates.add(lockState);
+
+ if (deltaHandler != null)
+ {
+ deltaHandler.handleLockDelta(context, lockState.getLockedObject(), lockType, oldCount, newCount);
+ }
}
- if (lockState.hasNoLocks())
+ if (stateHandler != null)
{
- objectToLockStateMap.remove(lockState.getLockedObject());
+ stateHandler.accept(lockState);
}
}
-
- notifyAll();
}
-
- return new LinkedList<>(result);
}
- @Override
- public synchronized void unlock(CONTEXT context)
+ private void removeLockStates(CONTEXT context, List<LockState<OBJECT, CONTEXT>> modifiedLockStates)
{
- unlock2(context);
- }
-
- @Override
- public synchronized List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context)
- {
- Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.get(context);
- if (lockStates == null)
+ for (LockState<OBJECT, CONTEXT> lockState : modifiedLockStates)
{
- return emptyResult;
- }
-
- if (TRACER.isEnabled())
- {
- TRACER.format("Unlock: {0} --> {1}", context, lockStates); //$NON-NLS-1$
- }
-
- List<OBJECT> objectsWithoutLocks = new LinkedList<>();
-
- for (LockState<OBJECT, CONTEXT> lockState : lockStates)
- {
- for (LockType type : ALL_LOCK_TYPES)
+ if (!lockState.hasLocks(context))
{
- while (lockState.hasLock(type, context, false))
- {
- lockState.unlock(type, context);
- }
+ removeLockStateForContext(context, lockState);
}
if (lockState.hasNoLocks())
{
- OBJECT o = lockState.getLockedObject();
- objectsWithoutLocks.add(o);
+ objectToLockStateMap.remove(lockState.getLockedObject());
}
}
-
- contextToLockStates.remove(context);
-
- // This must be done outside the above iteration, in order to avoid ConcurrentModEx
- for (OBJECT o : objectsWithoutLocks)
- {
- objectToLockStateMap.remove(o);
- }
-
- notifyAll();
-
- return toList(lockStates);
}
- @Override
- public synchronized boolean hasLock(LockType type, CONTEXT context, OBJECT objectToLock)
+ /**
+ * Removes a lockState from the set of all lockStates that the given context is involved in. If the lockState being
+ * removed is the last one for the given context, then the set becomes empty, and is therefore removed from the
+ * contextToLockStates map.
+ */
+ private void removeLockStateForContext(CONTEXT context, LockState<OBJECT, CONTEXT> lockState)
{
- LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(objectToLock);
- return lockState != null && lockState.hasLock(type, context, false);
- }
-
- @Override
- public synchronized boolean hasLockByOthers(LockType type, CONTEXT context, OBJECT objectToLock)
- {
- LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(objectToLock);
- return lockState != null && lockState.hasLock(type, context, true);
- }
-
- protected synchronized void changeContext(CONTEXT oldContext, CONTEXT newContext)
- {
- for (LockState<OBJECT, CONTEXT> lockState : objectToLockStateMap.values())
- {
- lockState.replaceContext(oldContext, newContext);
- }
-
- Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.remove(oldContext);
+ Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.get(context);
if (lockStates != null)
{
- contextToLockStates.put(newContext, lockStates);
+ lockStates.remove(lockState);
+
+ if (lockStates.isEmpty())
+ {
+ contextToLockStates.remove(context);
+ }
}
}
- protected long currentTimeMillis()
+ /**
+ * @category Read Access
+ */
+ @Override
+ public boolean hasLock(LockType type, CONTEXT context, OBJECT objectToLock)
{
- return System.currentTimeMillis();
+ try (Access access = read.access())
+ {
+ LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(objectToLock);
+ return lockState != null && lockState.hasLock(type, context, false);
+ }
}
- protected Map<OBJECT, LockState<OBJECT, CONTEXT>> createObjectToLocksMap()
+ /**
+ * @category Read Access
+ */
+ @Override
+ public boolean hasLockByOthers(LockType type, CONTEXT context, OBJECT objectToLock)
{
- return new HashMap<>();
+ try (Access access = read.access())
+ {
+ LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(objectToLock);
+ return lockState != null && lockState.hasLock(type, context, true);
+ }
}
- protected Map<CONTEXT, Set<LockState<OBJECT, CONTEXT>>> createContextToLocksMap()
+ /**
+ * @category Read Access
+ */
+ public LockState<OBJECT, CONTEXT> getLockState(OBJECT key)
{
- return new HashMap<>();
+ try (Access access = read.access())
+ {
+ return objectToLockStateMap.get(key);
+ }
+ }
+
+ /**
+ * @since 3.16
+ * @category Read Access
+ */
+ public void getLockStates(Collection<OBJECT> keys, BiConsumer<OBJECT, LockState<OBJECT, CONTEXT>> consumer)
+ {
+ try (Access access = read.access())
+ {
+ keys.forEach(key -> {
+ LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(key);
+ consumer.accept(key, lockState);
+ });
+ }
+ }
+
+ /**
+ * @since 3.16
+ * @category Read Access
+ */
+ public void getLockStates(Consumer<LockState<OBJECT, CONTEXT>> consumer)
+ {
+ try (Access access = read.access())
+ {
+ objectToLockStateMap.values().forEach(consumer);
+ }
+ }
+
+ protected void changeContext(CONTEXT oldContext, CONTEXT newContext)
+ {
+ try (Access access = write.access())
+ {
+ for (LockState<OBJECT, CONTEXT> lockState : objectToLockStateMap.values())
+ {
+ lockState.replaceContext(oldContext, newContext);
+ }
+
+ Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.remove(oldContext);
+ if (lockStates != null)
+ {
+ contextToLockStates.put(newContext, lockStates);
+ }
+ }
}
/**
@@ -298,162 +429,117 @@
return contextToLockStates;
}
- public synchronized LockState<OBJECT, CONTEXT> getLockState(OBJECT key)
+ protected Map<OBJECT, LockState<OBJECT, CONTEXT>> createObjectToLocksMap()
{
- return objectToLockStateMap.get(key);
+ return new HashMap<>();
+ }
+
+ protected Map<CONTEXT, Set<LockState<OBJECT, CONTEXT>>> createContextToLocksMap()
+ {
+ return new HashMap<>();
+ }
+
+ protected long currentTimeMillis()
+ {
+ return System.currentTimeMillis();
+ }
+
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> getLockStates()
+ {
+ throw new UnsupportedOperationException();
}
/**
- * @since 3.16
+ * @category Write Access
*/
- public synchronized void getLockStates(Collection<OBJECT> keys, BiConsumer<OBJECT, LockState<OBJECT, CONTEXT>> consumer)
+ @Deprecated
+ public void setLockState(OBJECT key, LockState<OBJECT, CONTEXT> lockState)
{
- keys.forEach(key -> {
- LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(key);
- consumer.accept(key, lockState);
- });
- }
-
- /**
- * @since 3.5
- */
- public synchronized List<LockState<OBJECT, CONTEXT>> getLockStates()
- {
- return new ArrayList<>(objectToLockStateMap.values());
- }
-
- public synchronized void setLockState(OBJECT key, LockState<OBJECT, CONTEXT> lockState)
- {
- objectToLockStateMap.put(key, lockState);
-
- for (CONTEXT readLockOwner : lockState.getReadLockOwners())
+ try (Access access = write.access())
{
- addContextToLockStateMapping(readLockOwner, lockState);
- }
+ objectToLockStateMap.put(key, lockState);
- CONTEXT writeLockOwner = lockState.getWriteLockOwner();
- if (writeLockOwner != null)
- {
- addContextToLockStateMapping(writeLockOwner, lockState);
- }
-
- CONTEXT writeOptionOwner = lockState.getWriteOptionOwner();
- if (writeOptionOwner != null)
- {
- addContextToLockStateMapping(writeOptionOwner, lockState);
- }
- }
-
- private LockState<OBJECT, CONTEXT> getOrCreateLockState(OBJECT o)
- {
- LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(o);
- if (lockState == null)
- {
- lockState = new LockState<>(o);
- objectToLockStateMap.put(o, lockState);
- }
-
- return lockState;
- }
-
- private ArrayList<LockState<OBJECT, CONTEXT>> getLockStatesForContext(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock)
- {
- int count = objectsToLock.size();
- ArrayList<LockState<OBJECT, CONTEXT>> lockStates = new ArrayList<>(count);
-
- Iterator<? extends OBJECT> it = objectsToLock.iterator();
-
- for (int i = 0; i < count; i++)
- {
- OBJECT o = it.next();
- LockState<OBJECT, CONTEXT> lockState = getOrCreateLockState(o);
- if (!lockState.canLock(type, context))
+ for (CONTEXT readLockOwner : lockState.getReadLockOwners())
{
- return null;
+ addContextToLockStateMapping(readLockOwner, lockState);
}
- lockStates.add(lockState);
- }
-
- return lockStates;
- }
-
- private void addContextToLockStateMapping(CONTEXT context, LockState<OBJECT, CONTEXT> lockState)
- {
- Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.get(context);
- if (lockStates == null)
- {
- lockStates = new HashSet<>();
- contextToLockStates.put(context, lockStates);
- }
-
- lockStates.add(lockState);
- }
-
- /**
- * Removes a lockState from the set of all lockStates that the given context is involved in. If the lockState being
- * removed is the last one for the given context, then the set becomes empty, and is therefore removed from the
- * contextToLockStates map.
- */
- private void removeLockStateForContext(CONTEXT context, LockState<OBJECT, CONTEXT> lockState)
- {
- Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.get(context);
- lockStates.remove(lockState);
- if (lockStates.isEmpty())
- {
- contextToLockStates.remove(context);
- }
- }
-
- private void wait(long startTime, long timeout) throws InterruptedException
- {
- if (timeout == WAIT)
- {
- wait();
- }
- else
- {
- long elapsedTime = currentTimeMillis() - startTime;
- long waitTime = timeout - elapsedTime;
- if (waitTime < 1)
+ CONTEXT writeLockOwner = lockState.getWriteLockOwner();
+ if (writeLockOwner != null)
{
- throw new TimeoutRuntimeException("Could not lock objects within " + timeout + " milli seconds");
+ addContextToLockStateMapping(writeLockOwner, lockState);
}
- wait(waitTime);
+ CONTEXT writeOptionOwner = lockState.getWriteOptionOwner();
+ if (writeOptionOwner != null)
+ {
+ addContextToLockStateMapping(writeOptionOwner, lockState);
+ }
}
}
- @SuppressWarnings("unchecked")
- private static <OBJECT, CONTEXT> List<LockState<OBJECT, CONTEXT>> toList(Set<LockState<OBJECT, CONTEXT>> lockStates)
+ @Override
+ @Deprecated
+ public void lock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout) throws InterruptedException
{
- if (lockStates instanceof List)
- {
- return (List<LockState<OBJECT, CONTEXT>>)lockStates;
- }
-
- List<LockState<OBJECT, CONTEXT>> list = new LinkedList<>();
- for (LockState<OBJECT, CONTEXT> lockState : lockStates)
- {
- list.add(lockState);
- }
-
- return list;
+ throw new UnsupportedOperationException();
}
- /**
- * @since 3.7
- */
+ @Override
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> lock2(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout)
+ throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void lock(LockType type, CONTEXT context, OBJECT objectToLock, long timeout) throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public void unlock(CONTEXT context)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public List<LockState<OBJECT, CONTEXT>> unlock2(LockType lockType, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Deprecated
public static void setUnlockAll(boolean on)
{
- if (on)
- {
- UNLOCK_ALL.set(Boolean.TRUE);
- }
- else
- {
- UNLOCK_ALL.remove();
- }
+ throw new UnsupportedOperationException();
}
/**
@@ -477,7 +563,7 @@
{
private final OBJECT lockedObject;
- private final HashBag<CONTEXT> readLockOwners = new HashBag<>();
+ private HashBag<CONTEXT> readLockOwners;
private CONTEXT writeLockOwner;
@@ -496,38 +582,67 @@
return lockedObject;
}
- public boolean hasLock(LockType type, CONTEXT view, boolean byOthers)
+ /**
+ * @since 3.16
+ */
+ public int getLockCount(LockType type, CONTEXT context)
{
- CheckUtil.checkArg(view, "view");
+ CheckUtil.checkArg(context, "context");
switch (type)
{
case READ:
- if (byOthers)
+ return readLockOwners == null ? 0 : readLockOwners.getCounterFor(context);
+
+ case WRITE:
+ return writeLockOwner == context ? writeLockCounter : 0;
+
+ case OPTION:
+ return writeOptionOwner == context ? 1 : 0;
+
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public boolean hasLock(LockType type, CONTEXT context, boolean byOthers)
+ {
+ CheckUtil.checkArg(context, "context");
+
+ switch (type)
+ {
+ case READ:
+ if (readLockOwners == null)
{
- return readLockOwners.size() > 1 || readLockOwners.size() == 1 && !readLockOwners.contains(view);
+ return false;
}
- return readLockOwners.contains(view);
+ if (byOthers)
+ {
+ return readLockOwners.size() > 1 || readLockOwners.size() == 1 && !readLockOwners.contains(context);
+ }
+
+ return readLockOwners.contains(context);
case WRITE:
if (byOthers)
{
- return writeLockOwner != null && writeLockOwner != view;
+ return writeLockOwner != null && writeLockOwner != context;
}
- return writeLockOwner == view;
+ return writeLockOwner == context;
case OPTION:
if (byOthers)
{
- return writeOptionOwner != null && writeOptionOwner != view;
+ return writeOptionOwner != null && writeOptionOwner != context;
}
- return writeOptionOwner == view;
- }
+ return writeOptionOwner == context;
- return false;
+ default:
+ throw new AssertionError();
+ }
}
public boolean hasLock(LockType type)
@@ -535,20 +650,26 @@
switch (type)
{
case READ:
- return readLockOwners.size() > 0;
+ return readLockOwners != null && readLockOwners.size() > 0;
case WRITE:
return writeLockOwner != null;
case OPTION:
return writeOptionOwner != null;
- }
- return false;
+ default:
+ throw new AssertionError();
+ }
}
public Set<CONTEXT> getReadLockOwners()
{
+ if (readLockOwners == null)
+ {
+ return Collections.emptySet();
+ }
+
return Collections.unmodifiableSet(readLockOwners);
}
@@ -596,11 +717,11 @@
StringBuilder builder = new StringBuilder("LockState[target=");
builder.append(lockedObject);
- if (readLockOwners.size() > 0)
+ if (readLockOwners != null && readLockOwners.size() > 0)
{
builder.append(", read=");
boolean first = true;
- for (CONTEXT view : readLockOwners)
+ for (CONTEXT context : readLockOwners)
{
if (first)
{
@@ -611,7 +732,7 @@
builder.append(", ");
}
- builder.append(view);
+ builder.append(context);
}
builder.deleteCharAt(builder.length() - 1);
@@ -633,43 +754,23 @@
return builder.toString();
}
- void lock(LockType type, CONTEXT context)
- {
- CheckUtil.checkArg(context, "context");
- switch (type)
- {
- case READ:
- doReadLock(context);
- return;
-
- case WRITE:
- doWriteLock(context);
- return;
-
- case OPTION:
- doWriteOption(context);
- return;
- }
-
- throw new AssertionError("Unknown lock type " + type);
- }
-
boolean canLock(LockType type, CONTEXT context)
{
CheckUtil.checkArg(context, "context");
switch (type)
{
case READ:
- return canReadLock(context);
+ return canLockRead(context);
case WRITE:
- return canWriteLock(context);
+ return canLockWrite(context);
case OPTION:
- return canWriteOption(context);
- }
+ return canLockOption(context);
- throw new AssertionError("Unknown lock type " + type);
+ default:
+ throw new AssertionError();
+ }
}
boolean canUnlock(LockType type, CONTEXT context)
@@ -678,48 +779,69 @@
switch (type)
{
case READ:
- return canReadUnlock(context);
+ return canUnlockRead(context);
case WRITE:
- return canWriteUnlock(context);
+ return canUnlockWrite(context);
case OPTION:
- return canWriteUnoption(context);
- }
+ return canUnlockOption(context);
- throw new AssertionError("Unknown lock type " + type);
+ default:
+ throw new AssertionError();
+ }
}
- void unlock(LockType type, CONTEXT context)
+ int lock(LockType type, CONTEXT context, int count)
{
CheckUtil.checkArg(context, "context");
switch (type)
{
case READ:
- doReadUnlock(context);
- return;
+ return doLockRead(context, count);
case WRITE:
- doWriteUnlock(context);
- return;
+ return doLockWrite(context, count);
case OPTION:
- doWriteUnoption(context);
- return;
- }
+ return doLockOption(context, count);
- throw new AssertionError("Unknown lock type " + type);
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ int unlock(LockType type, CONTEXT context, int count)
+ {
+ CheckUtil.checkArg(context, "context");
+ switch (type)
+ {
+ case READ:
+ return doUnlockRead(context, count);
+
+ case WRITE:
+ return doUnlockWrite(context, count);
+
+ case OPTION:
+ return doUnlockOption(context, count);
+
+ default:
+ throw new AssertionError();
+ }
}
void replaceContext(CONTEXT oldContext, CONTEXT newContext)
{
- int readLocksOwnedByOldView = readLockOwners.getCounterFor(oldContext);
- if (readLocksOwnedByOldView > 0)
+ if (readLockOwners != null)
{
- for (int i = 0; i < readLocksOwnedByOldView; i++)
+ int readLocksOwnedByOldView = readLockOwners.getCounterFor(oldContext);
+ if (readLocksOwnedByOldView > 0)
{
- readLockOwners.remove(oldContext);
- readLockOwners.add(newContext);
+ for (int i = 0; i < readLocksOwnedByOldView; i++)
+ {
+ readLockOwners.remove(oldContext);
+ readLockOwners.add(newContext);
+ }
}
}
@@ -736,15 +858,15 @@
boolean hasNoLocks()
{
- return readLockOwners.isEmpty() && writeLockOwner == null && writeOptionOwner == null;
+ return ObjectUtil.isEmpty(readLockOwners) && writeLockOwner == null && writeOptionOwner == null;
}
boolean hasLocks(CONTEXT context)
{
- return readLockOwners.contains(context) || writeLockOwner == context || writeOptionOwner == context;
+ return readLockOwners != null && readLockOwners.contains(context) || writeLockOwner == context || writeOptionOwner == context;
}
- private boolean canReadLock(CONTEXT context)
+ private boolean canLockRead(CONTEXT context)
{
if (writeLockOwner != null && writeLockOwner != context)
{
@@ -754,12 +876,7 @@
return true;
}
- private void doReadLock(CONTEXT context)
- {
- readLockOwners.add(context);
- }
-
- private boolean canWriteLock(CONTEXT context)
+ private boolean canLockWrite(CONTEXT context)
{
// If another context owns a writeLock, we can't write-lock
if (writeLockOwner != null && writeLockOwner != context)
@@ -774,29 +891,26 @@
}
// If another context owns a readLock, we can't write-lock
- if (readLockOwners.size() > 1)
+ if (readLockOwners != null)
{
- return false;
- }
-
- if (readLockOwners.size() == 1)
- {
- if (!readLockOwners.contains(context))
+ if (readLockOwners.size() > 1)
{
return false;
}
+
+ if (readLockOwners.size() == 1)
+ {
+ if (!readLockOwners.contains(context))
+ {
+ return false;
+ }
+ }
}
return true;
}
- private void doWriteLock(CONTEXT context)
- {
- writeLockOwner = context;
- writeLockCounter++;
- }
-
- private boolean canWriteOption(CONTEXT context)
+ private boolean canLockOption(CONTEXT context)
{
if (writeOptionOwner != null && writeOptionOwner != context)
{
@@ -811,14 +925,9 @@
return true;
}
- private void doWriteOption(CONTEXT context)
+ private boolean canUnlockRead(CONTEXT context)
{
- writeOptionOwner = context;
- }
-
- private boolean canReadUnlock(CONTEXT context)
- {
- if (!readLockOwners.contains(context))
+ if (readLockOwners != null && !readLockOwners.contains(context))
{
return false;
}
@@ -826,12 +935,7 @@
return true;
}
- private void doReadUnlock(CONTEXT context)
- {
- readLockOwners.remove(context);
- }
-
- private boolean canWriteUnlock(CONTEXT context)
+ private boolean canUnlockWrite(CONTEXT context)
{
if (writeLockOwner != context)
{
@@ -841,16 +945,7 @@
return true;
}
- private void doWriteUnlock(CONTEXT context)
- {
- writeLockCounter--;
- if (writeLockCounter == 0)
- {
- writeLockOwner = null;
- }
- }
-
- private boolean canWriteUnoption(CONTEXT context)
+ private boolean canUnlockOption(CONTEXT context)
{
if (writeOptionOwner != context)
{
@@ -860,9 +955,77 @@
return true;
}
- private void doWriteUnoption(CONTEXT context)
+ private int doLockRead(CONTEXT context, int count)
+ {
+ if (readLockOwners == null)
+ {
+ readLockOwners = new HashBag<>();
+ }
+
+ return readLockOwners.addAndGet(context, count);
+ }
+
+ private int doLockWrite(CONTEXT context, int count)
+ {
+ writeLockOwner = context;
+ return writeLockCounter += count;
+ }
+
+ private int doLockOption(CONTEXT context, int count)
+ {
+ writeOptionOwner = context;
+ return 1;
+ }
+
+ private int doUnlockRead(CONTEXT context, int count)
+ {
+ if (readLockOwners == null)
+ {
+ return 0;
+ }
+
+ if (count == ALL_LOCKS)
+ {
+ readLockOwners.removeCounterFor(context);
+ if (readLockOwners.isEmpty())
+ {
+ readLockOwners = null;
+ }
+
+ return 0;
+ }
+
+ int newCount = readLockOwners.removeAndGet(context, count);
+ if (readLockOwners.isEmpty())
+ {
+ readLockOwners = null;
+ }
+
+ return newCount;
+ }
+
+ private int doUnlockWrite(CONTEXT context, int count)
+ {
+ if (count == ALL_LOCKS)
+ {
+ writeLockOwner = null;
+ writeLockCounter = 0;
+ return 0;
+ }
+
+ writeLockCounter -= count;
+ if (writeLockCounter == 0)
+ {
+ writeLockOwner = null;
+ }
+
+ return writeLockCounter;
+ }
+
+ private int doUnlockOption(CONTEXT context, int count)
{
writeOptionOwner = null;
+ return 0;
}
}
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/ReentrantReadWriteAccess.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/ReentrantReadWriteAccess.java
new file mode 100644
index 0000000..b2e002a
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/ReentrantReadWriteAccess.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.util.concurrent;
+
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * @author Eike Stepper
+ * @since 3.16
+ */
+public final class ReentrantReadWriteAccess
+{
+ private final ReentrantReadWriteLock lock;
+
+ private final Access readAccess;
+
+ private final Access writeAccess;
+
+ public ReentrantReadWriteAccess(boolean fair)
+ {
+ lock = new ReentrantReadWriteLock(fair);
+ readAccess = new Access(lock.readLock());
+ writeAccess = new Access(lock.writeLock());
+ }
+
+ public ReentrantReadWriteAccess()
+ {
+ this(false);
+ }
+
+ public ReentrantReadWriteLock getLock()
+ {
+ return lock;
+ }
+
+ public Access readAccess()
+ {
+ return readAccess;
+ }
+
+ public Access writeAccess()
+ {
+ return writeAccess;
+ }
+
+ public Condition newCondition()
+ {
+ return writeAccess.newCondition();
+ }
+}