diff options
author | Eike Stepper | 2021-11-18 08:16:56 +0000 |
---|---|---|
committer | Eike Stepper | 2021-11-18 08:16:56 +0000 |
commit | 5eec84ecb3019f20bf2776b78cba98c98d51a7a8 (patch) | |
tree | 93ea08105166ff007da03b6c29a0bbf094830fab | |
parent | 52aae9b138a63f643cf814405f70fe3403eaf3e6 (diff) | |
download | cdo-5eec84ecb3019f20bf2776b78cba98c98d51a7a8.tar.gz cdo-5eec84ecb3019f20bf2776b78cba98c98d51a7a8.tar.xz cdo-5eec84ecb3019f20bf2776b78cba98c98d51a7a8.zip |
[577319] Implement lock state prefetching as integral part of revision loading
https://bugs.eclipse.org/bugs/show_bug.cgi?id=577319
25 files changed, 490 insertions, 102 deletions
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 1a48acad6f..83903e19d2 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 @@ -334,17 +334,6 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi return (InternalCDORevision)results.get(0); } - // @Override - // public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, - // boolean loadOnDemand, - // List<CDORevision> additionalRevisions) - // { - // List<CDOID> ids = Collections.singletonList(id); - // List<CDORevision> results = getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, - // synthetics); - // return (InternalCDORevision)results.get(0); - // } - @Override public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand) { @@ -355,18 +344,25 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand, SyntheticCDORevision[] synthetics) { - return getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, synthetics, null, null); + return getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, false, loadOnDemand, synthetics, null, null); + } + + @Override + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean prefetchLockStates, + boolean loadOnDemand, SyntheticCDORevision[] synthetics) + { + return getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates, loadOnDemand, synthetics, null, null); } @Override public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand, List<CDORevision> additionalRevisions) { - return getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, null, additionalRevisions, null); + return getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, false, loadOnDemand, null, additionalRevisions, null); } - private List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand, - SyntheticCDORevision[] synthetics, List<CDORevision> additionalRevisions, Consumer<CDORevision> consumer) + private List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean prefetchLockStates, + boolean loadOnDemand, SyntheticCDORevision[] synthetics, List<CDORevision> additionalRevisions, Consumer<CDORevision> consumer) { RevisionInfo[] allInfos = new RevisionInfo[ids.size()]; @@ -380,7 +376,7 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi if (infosToLoad != null) { // Load the requested revision infos, then process the additional revisions. - loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth, additionalRevisions, consumer); + loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates, additionalRevisions, consumer); } List<CDORevision> primaryRevisions = processResults(allInfos, synthetics, consumer); @@ -406,10 +402,10 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi * @since 4.15 */ @Override - public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, Consumer<CDORevision> consumer) + public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, boolean prefetchLockStates, Consumer<CDORevision> consumer) { List<CDOID> ids = Collections.singletonList(id); - getRevisions(ids, branchPoint, CDORevision.UNCHUNKED, prefetchDepth, true, null, null, consumer); + getRevisions(ids, branchPoint, CDORevision.UNCHUNKED, prefetchDepth, prefetchLockStates, true, null, null, consumer); } @Override @@ -505,14 +501,18 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi /** * Loads the requested revision infos, then processes and returns additional revisions. */ - protected void loadRevisions(List<RevisionInfo> infosToLoad, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + protected void loadRevisions(List<RevisionInfo> infosToLoad, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean prefetchLockStates, List<CDORevision> additionalRevisions, Consumer<CDORevision> consumer) { acquireAtomicRequestLock(loadAndAddLock); try { - List<RevisionInfo> additionalRevisionInfos = revisionLoader.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth); + @SuppressWarnings("deprecation") + List<RevisionInfo> additionalRevisionInfos = revisionLoader instanceof RevisionLoader3 + ? ((RevisionLoader3)revisionLoader).loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates) + : revisionLoader.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth); + if (additionalRevisionInfos != null) { for (RevisionInfo info : additionalRevisionInfos) 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 1c9daeb4d2..4dd4d6c30d 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 @@ -386,14 +386,23 @@ public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating impl public CDOLockState readCDOLockState() throws IOException { Object target; - boolean sendingBranchWithID = readBoolean(); - if (!sendingBranchWithID) + + byte type = readByte(); + switch (type) { + case 0: + return null; + + case 1: target = readCDOID(); - } - else - { + break; + + case 2: target = readCDOIDAndBranch(); + break; + + default: + throw new IOException("Invalid type: " + type); } InternalCDOLockState lockState = new CDOLockStateImpl(target); 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 edb746ce0d..eaa5ee9276 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 @@ -369,15 +369,21 @@ public class CDODataOutputImpl extends ExtendedDataOutput.Delegating implements @Override public void writeCDOLockState(CDOLockState lockState) throws IOException { + if (lockState == null) + { + writeByte(0); + return; + } + Object o = lockState.getLockedObject(); if (o instanceof CDOID) { - writeBoolean(false); + writeByte(1); writeCDOID((CDOID)o); } else if (o instanceof CDOIDAndBranch) { - writeBoolean(true); + writeByte(2); writeCDOIDAndBranch((CDOIDAndBranch)o); } else diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevisionManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevisionManager.java index 2597a26755..25c600aefa 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevisionManager.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevisionManager.java @@ -205,6 +205,13 @@ public abstract class DelegatingCDORevisionManager extends Lifecycle implements return getDelegate().getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, synthetics); } + @Override + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean prefetchLockStates, + boolean loadOnDemand, SyntheticCDORevision[] synthetics) + { + return getDelegate().getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates, loadOnDemand, synthetics); + } + /** * @since 4.15 */ @@ -216,9 +223,9 @@ public abstract class DelegatingCDORevisionManager extends Lifecycle implements } @Override - public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, Consumer<CDORevision> consumer) + public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, boolean prefetchLockStates, Consumer<CDORevision> consumer) { - getDelegate().prefetchRevisions(id, branchPoint, prefetchDepth, consumer); + getDelegate().prefetchRevisions(id, branchPoint, prefetchDepth, prefetchLockStates, consumer); } @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 fdeaad403f..5646f16276 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 @@ -83,11 +83,17 @@ public interface InternalCDORevisionManager extends CDORevisionManager, CDORevis /** * @since 4.15 */ - public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, Consumer<CDORevision> consumer); + public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, boolean prefetchLockStates, Consumer<CDORevision> consumer); public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand, SyntheticCDORevision[] synthetics); + /** + * @since 4.15 + */ + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean prefetchLockStates, + boolean loadOnDemand, SyntheticCDORevision[] synthetics); + public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand, SyntheticCDORevision[] synthetics); @@ -119,6 +125,10 @@ public interface InternalCDORevisionManager extends CDORevisionManager, CDORevis */ 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); @@ -146,6 +156,20 @@ public interface InternalCDORevisionManager extends CDORevisionManager, CDORevis * If the meaning of this type isn't clear, there really should be more of a description here... * * @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 RevisionLoader3 extends RevisionLoader2 + { + public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean prefetchLockStates); + } + + /** + * If the meaning of this type isn't clear, there really should be more of a description here... + * + * @author Eike Stepper * @since 3.0 */ public interface RevisionLocker diff --git a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutImpl.java b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutImpl.java index 2ad40d0f47..94ca561044 100644 --- a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutImpl.java +++ b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutImpl.java @@ -91,6 +91,8 @@ public abstract class CDOCheckoutImpl extends AbstractElement implements CDOChec public static final String PROP_PREFETCH = "prefetch"; + public static final String PROP_PREFETCH_LOCK_STATES = "prefetchLockStates"; + public static final String PROP_REPOSITORY = "repository"; public static final String EDITOR_PROPERTIES = "editor.properties"; @@ -459,6 +461,23 @@ public abstract class CDOCheckoutImpl extends AbstractElement implements CDOChec } } + public final boolean isPrefetchLockStates() + { + Object checkoutProperty = getProperties().get(PROP_PREFETCH_LOCK_STATES); + if (checkoutProperty instanceof String) + { + return Boolean.parseBoolean((String)checkoutProperty); + } + + String systemProperty = OMPlatform.INSTANCE.getProperty("org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout.DISABLE_PREFETCH_LOCK_STATES"); + if (checkoutProperty != null) + { + return !Boolean.parseBoolean(systemProperty); + } + + return view.options().isLockNotificationEnabled(); + } + @Override public boolean waitUntilPrefetched() { @@ -472,8 +491,10 @@ public abstract class CDOCheckoutImpl extends AbstractElement implements CDOChec private void startPrefetcherManager() { + boolean prefetchLockStates = isPrefetchLockStates(); + ResourceSet resourceSet = view.getResourceSet(); - prefetcherManager = new CDOPrefetcherManager(resourceSet); + prefetcherManager = new CDOPrefetcherManager(resourceSet, prefetchLockStates); prefetcherManager.activate(); prefetcherManager.waitUntilPrefetched(); 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 da4292c116..1d993af3c2 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 @@ -246,10 +246,18 @@ public class CDOClientProtocol extends AuthenticatingSignalProtocol<CDOSessionIm 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) { - return send(new LoadRevisionsRequest(this, infos, branchPoint, referenceChunk, prefetchDepth)); + throw new UnsupportedOperationException(); + } + + @Override + public List<RevisionInfo> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean prefetchLockStates) + { + return send(new LoadRevisionsRequest(this, infos, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates)); } @Override 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 e2b77f1465..5ec6b24926 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 @@ -13,9 +13,13 @@ package org.eclipse.emf.cdo.internal.net4j.protocol; 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.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.common.lock.CDOLockUtil; 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.common.revision.CDOIDAndBranch; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; @@ -27,6 +31,8 @@ import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; import org.eclipse.emf.cdo.view.CDOFetchRuleManager; +import org.eclipse.emf.internal.cdo.session.CDOLockStateCache; + import org.eclipse.net4j.util.io.IORuntimeException; import org.eclipse.emf.spi.cdo.InternalCDOSession; @@ -44,26 +50,30 @@ import java.util.Map; */ public class LoadRevisionsRequest extends CDOClientRequest<List<RevisionInfo>> { - private List<RevisionInfo> infos; + private final List<RevisionInfo> infos; + + private final CDOBranchPoint branchPoint; - private CDOBranchPoint branchPoint; + private final int referenceChunk; - private int referenceChunk; + private final int prefetchDepth; - private int prefetchDepth; + private final boolean prefetchLockStates; /** * Remembers strong references to valid revisions to prevent garbage collection. */ private Map<CDORevisionKey, CDORevision> rememberedRevisions; - public LoadRevisionsRequest(CDOClientProtocol protocol, List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth) + public LoadRevisionsRequest(CDOClientProtocol protocol, List<RevisionInfo> infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean prefetchLockStates) { super(protocol, CDOProtocolConstants.SIGNAL_LOAD_REVISIONS); this.infos = infos; this.branchPoint = branchPoint; this.referenceChunk = referenceChunk; this.prefetchDepth = prefetchDepth; + this.prefetchLockStates = prefetchLockStates; } @Override @@ -71,6 +81,7 @@ public class LoadRevisionsRequest extends CDOClientRequest<List<RevisionInfo>> { out.writeCDOBranchPoint(branchPoint); out.writeXInt(referenceChunk); + out.writeBoolean(prefetchLockStates); InternalCDOSession session = getSession(); int size = infos.size(); @@ -200,6 +211,52 @@ public class LoadRevisionsRequest extends CDOClientRequest<List<RevisionInfo>> } } + if (in.readBoolean()) + { + List<CDOLockState> lockStates = new ArrayList<>(); + + for (;;) + { + CDOLockState lockState = in.readCDOLockState(); + if (lockState == null) + { + break; + } + + lockStates.add(lockState); + } + + int noLockStateKeys = in.readXInt(); + if (noLockStateKeys != 0) + { + if (getSession().getRevisionManager().isSupportingBranches()) + { + for (int i = 0; i < noLockStateKeys; i++) + { + CDOID id = in.readCDOID(); + CDOIDAndBranch lockTarget = CDOIDUtil.createIDAndBranch(id, requestedBranch); + CDOLockState lockState = CDOLockUtil.createLockState(lockTarget); + lockStates.add(lockState); + } + } + else + { + for (int i = 0; i < noLockStateKeys; i++) + { + CDOID id = in.readCDOID(); + CDOLockState lockState = CDOLockUtil.createLockState(id); + lockStates.add(lockState); + } + } + } + + if (!lockStates.isEmpty()) + { + CDOLockStateCache lockStateCache = getSession().getLockStateCache(); + lockStateCache.addLockStates(requestedBranch, lockStates, null); + } + } + if (rememberedRevisions != null) { rememberedRevisions.clear(); // Help the garbage collector. @@ -211,7 +268,8 @@ public class LoadRevisionsRequest extends CDOClientRequest<List<RevisionInfo>> @Override protected String getAdditionalInfo() { - return MessageFormat.format("infos={0}, branchPoint={1}, referenceChunk={2}, prefetchDepth={3}", infos, branchPoint, referenceChunk, prefetchDepth); + return MessageFormat.format("infos={0}, branchPoint={1}, referenceChunk={2}, prefetchDepth={3}, prefetchLockStates={4}", // + infos, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates); } /** diff --git a/plugins/org.eclipse.emf.cdo.server.embedded/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.server.embedded/.settings/.api_filters index eb8bc080dc..8bd60e942d 100644 --- a/plugins/org.eclipse.emf.cdo.server.embedded/.settings/.api_filters +++ b/plugins/org.eclipse.emf.cdo.server.embedded/.settings/.api_filters @@ -29,5 +29,11 @@ <message_argument value="ServerRevisionLoader"/> </message_arguments> </filter> + <filter id="574619656"> + <message_arguments> + <message_argument value="RevisionLoader3"/> + <message_argument value="ServerRevisionLoader"/> + </message_arguments> + </filter> </resource> </component> diff --git a/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ClientRevisionManager.java b/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ClientRevisionManager.java index d4fbc0c33d..f8c7d21bf7 100644 --- a/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ClientRevisionManager.java +++ b/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ClientRevisionManager.java @@ -232,6 +232,21 @@ public final class ClientRevisionManager extends AbstractClientManager<InternalC } @Override + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean prefetchLockStates, + boolean loadOnDemand, SyntheticCDORevision[] synthetics) + { + try + { + ServerSession.set(serverSession); + return delegate.getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates, loadOnDemand, synthetics); + } + finally + { + ServerSession.unset(); + } + } + + @Override public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand) { try @@ -289,12 +304,12 @@ public final class ClientRevisionManager extends AbstractClientManager<InternalC } @Override - public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, Consumer<CDORevision> consumer) + public void prefetchRevisions(CDOID id, CDOBranchPoint branchPoint, int prefetchDepth, boolean prefetchLockStates, Consumer<CDORevision> consumer) { try { ServerSession.set(serverSession); - delegate.prefetchRevisions(id, branchPoint, prefetchDepth, consumer); + delegate.prefetchRevisions(id, branchPoint, prefetchDepth, prefetchLockStates, consumer); } finally { diff --git a/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ServerRevisionLoader.java b/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ServerRevisionLoader.java index 3aa2d3566d..6625262096 100644 --- a/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ServerRevisionLoader.java +++ b/plugins/org.eclipse.emf.cdo.server.embedded/src/org/eclipse/emf/cdo/server/internal/embedded/ServerRevisionLoader.java @@ -18,7 +18,7 @@ import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; import org.eclipse.emf.cdo.server.StoreThreadLocal; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader2; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader3; import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; import org.eclipse.emf.cdo.spi.server.InternalSession; @@ -29,30 +29,38 @@ import java.util.List; /** * @author Eike Stepper */ -public final class ServerRevisionLoader implements RevisionLoader2 +public final class ServerRevisionLoader implements RevisionLoader3 { - private final RevisionLoader2 delegate; + private final RevisionLoader3 delegate; - public ServerRevisionLoader(RevisionLoader2 delegate) + public ServerRevisionLoader(RevisionLoader3 delegate) { this.delegate = delegate; } - public RevisionLoader2 getDelegate() + public RevisionLoader3 getDelegate() { return delegate; } @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) + { InternalSession serverSession = ServerSession.get(); if (serverSession != null) { try { StoreThreadLocal.setSession(serverSession); - return delegate.loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth); + return delegate.loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates); } finally { @@ -60,7 +68,7 @@ public final class ServerRevisionLoader implements RevisionLoader2 } } - return delegate.loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth); + return delegate.loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates); } @Override diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionsIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionsIndication.java index ef299348b6..aa4d72ca19 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionsIndication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionsIndication.java @@ -14,22 +14,29 @@ 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.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.common.lock.CDOLockUtil; import org.eclipse.emf.cdo.common.model.CDOClassInfo; 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.common.revision.CDOIDAndBranch; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; import org.eclipse.emf.cdo.common.util.CDOFetchRule; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; +import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo.Type; +import org.eclipse.emf.cdo.spi.server.InternalLockManager; import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.emf.cdo.spi.server.InternalSession; +import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.collection.MoveableList; import org.eclipse.net4j.util.om.monitor.OMMonitor; @@ -54,10 +61,14 @@ public class LoadRevisionsIndication extends CDOServerReadIndication private CDOBranchPoint branchPoint; + private CDOBranch requestedBranch; + private int referenceChunk; private int prefetchDepth; + private boolean prefetchLockStates; + private Map<EClass, CDOFetchRule> fetchRules = new HashMap<>(); private CDOID contextID = CDOID.NULL; @@ -66,6 +77,12 @@ public class LoadRevisionsIndication extends CDOServerReadIndication private Set<CDORevisionKey> validKeys; + private InternalCDORevisionManager revisionManager; + + private InternalLockManager lockingManager; + + private Set<Object> lockStateKeys; + public LoadRevisionsIndication(CDOServerProtocol protocol) { super(protocol, CDOProtocolConstants.SIGNAL_LOAD_REVISIONS); @@ -74,9 +91,24 @@ public class LoadRevisionsIndication extends CDOServerReadIndication @Override protected void indicating(CDODataInput in) throws IOException { + InternalRepository repository = getRepository(); + revisionManager = repository.getRevisionManager(); + branchPoint = in.readCDOBranchPoint(); + requestedBranch = branchPoint.getBranch(); + referenceChunk = in.readXInt(); + prefetchLockStates = in.readBoolean(); + if (prefetchLockStates) + { + if (branchPoint.getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE) + { + lockingManager = repository.getLockingManager(); + lockStateKeys = new HashSet<>(); + } + } + int size = in.readXInt(); if (size < 0) { @@ -117,7 +149,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication contextID = in.readCDOID(); - InternalCDOPackageRegistry packageRegistry = getRepository().getPackageRegistry(); + InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(); for (int i = 0; i < fetchRulesCount; i++) { @@ -140,29 +172,26 @@ public class LoadRevisionsIndication extends CDOServerReadIndication revisionIDs.add(info.getID()); } - InternalRepository repository = getRepository(); - InternalCDORevisionManager revisionManager = repository.getRevisionManager(); - // Need to fetch the rule first. Set<CDOFetchRule> visitedFetchRules = new HashSet<>(); if (!CDOIDUtil.isNull(contextID) && fetchRules.size() > 0) { - RevisionInfo info = createRevisionInfo(revisionManager, contextID); + RevisionInfo info = createRevisionInfo(contextID); InternalCDORevision revisionContext = info.getResult(); - collectRevisions(revisionManager, revisionContext, revisionIDs, additionalInfos, additionalRevisions, visitedFetchRules); + collectRevisions(revisionContext, revisionIDs, additionalInfos, additionalRevisions, visitedFetchRules); } InternalCDORevision[] revisions = new InternalCDORevision[size]; for (int i = 0; i < size; i++) { RevisionInfo info = infos[i]; - info.execute(revisionManager, referenceChunk); + executeRevisionInfo(info); revisions[i] = info.getResult(); if (loadRevisionCollectionChunkSize > 0) { - collectRevisions(revisionManager, revisions[i], revisionIDs, additionalInfos, additionalRevisions, visitedFetchRules); + collectRevisions(revisions[i], revisionIDs, additionalInfos, additionalRevisions, visitedFetchRules); } } @@ -172,7 +201,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication try { - prefetchRevisions(revisionManager, prefetchDepth > 0 ? prefetchDepth : Integer.MAX_VALUE, revisions, additionalInfos, additionalRevisions, monitor); + prefetchRevisions(prefetchDepth > 0 ? prefetchDepth : Integer.MAX_VALUE, revisions, additionalInfos, additionalRevisions, monitor); } finally { @@ -182,7 +211,9 @@ public class LoadRevisionsIndication extends CDOServerReadIndication // Read access handlers may modify/replace the revisions and additionalRevisions, // which must be reflected in the infos and additionalInfos below! - repository.notifyReadAccessHandlers(getSession(), revisions, additionalRevisions); + InternalRepository repository = getRepository(); + InternalSession session = getSession(); + repository.notifyReadAccessHandlers(session, revisions, additionalRevisions); for (int i = 0; i < size; i++) { @@ -193,7 +224,6 @@ public class LoadRevisionsIndication extends CDOServerReadIndication // Write keys of additional revisions that are already cached on the client. int additionalSize = additionalRevisions.size(); - CDOBranch requestedBranch = branchPoint.getBranch(); List<RevisionInfo> infosToWrite = new ArrayList<>(); for (int i = 0; i < additionalSize; i++) @@ -230,17 +260,99 @@ public class LoadRevisionsIndication extends CDOServerReadIndication out.writeCDOID(info.getID()); info.writeResult(out, referenceChunk, branchPoint); } + + if (lockingManager != null) + { + out.writeBoolean(true); + + Set<Object> noLockStateKeys = new HashSet<>(); + + try + { + lockingManager.getLockStates(lockStateKeys, (key, lockState) -> { + if (lockState != null) + { + CDOLockState cdoLockState = CDOLockUtil.convertLockState(lockState); + + try + { + out.writeCDOLockState(cdoLockState); + } + catch (IOException ex) + { + throw WrappedException.wrap(ex); + } + } + else + { + noLockStateKeys.add(key); + } + }); + } + catch (WrappedException ex) + { + Exception exception = ex.exception(); + if (exception instanceof IOException) + { + throw (IOException)exception; + } + + throw ex; + } + + out.writeCDOLockState(null); + out.writeXInt(noLockStateKeys.size()); + + if (revisionManager.isSupportingBranches()) + { + for (Object key : noLockStateKeys) + { + out.writeCDOID(((CDOIDAndBranch)key).getID()); + } + } + else + { + for (Object key : noLockStateKeys) + { + out.writeCDOID((CDOID)key); + } + } + } + else + { + out.writeBoolean(false); + } } - private RevisionInfo createRevisionInfo(InternalCDORevisionManager revisionManager, CDOID id) + private RevisionInfo createRevisionInfo(CDOID id) { RevisionInfo info = new RevisionInfo.Missing(id, branchPoint); - info.execute(revisionManager, referenceChunk); + executeRevisionInfo(info); return info; } - private void collectRevisions(InternalCDORevisionManager revisionManager, InternalCDORevision revision, Set<CDOID> revisions, - List<RevisionInfo> additionalInfos, List<CDORevision> additionalRevisions, Set<CDOFetchRule> visitedFetchRules) + private void executeRevisionInfo(RevisionInfo info) + { + info.execute(revisionManager, referenceChunk); + + if (lockingManager != null) + { + CDORevision revision = info.getSynthetic(); + if (revision == null) + { + revision = info.getResult(); + } + + if (revision != null && !(revision instanceof DetachedCDORevision)) + { + Object key = lockingManager.getLockKey(revision.getID(), requestedBranch); + lockStateKeys.add(key); + } + } + } + + private void collectRevisions(InternalCDORevision revision, Set<CDOID> revisions, List<RevisionInfo> additionalInfos, List<CDORevision> additionalRevisions, + Set<CDOFetchRule> visitedFetchRules) { if (revision == null) { @@ -271,14 +383,14 @@ public class LoadRevisionsIndication extends CDOServerReadIndication CDOID id = (CDOID)value; if (!CDOIDUtil.isNull(id) && !revisions.contains(id)) { - RevisionInfo info = createRevisionInfo(revisionManager, id); + RevisionInfo info = createRevisionInfo(id); InternalCDORevision containedRevision = info.getResult(); if (containedRevision != null) { additionalInfos.add(info); revisions.add(containedRevision.getID()); additionalRevisions.add(containedRevision); - collectRevisions(revisionManager, containedRevision, revisions, additionalInfos, additionalRevisions, visitedFetchRules); + collectRevisions(containedRevision, revisions, additionalInfos, additionalRevisions, visitedFetchRules); } } } @@ -293,13 +405,13 @@ public class LoadRevisionsIndication extends CDOServerReadIndication CDOID id = (CDOID)value; if (!id.isNull() && !revisions.contains(id)) { - RevisionInfo info = createRevisionInfo(revisionManager, id); + RevisionInfo info = createRevisionInfo(id); InternalCDORevision containedRevision = info.getResult(); if (containedRevision != null) { revisions.add(containedRevision.getID()); additionalRevisions.add(containedRevision); - collectRevisions(revisionManager, containedRevision, revisions, additionalInfos, additionalRevisions, visitedFetchRules); + collectRevisions(containedRevision, revisions, additionalInfos, additionalRevisions, visitedFetchRules); } } } @@ -309,8 +421,8 @@ public class LoadRevisionsIndication extends CDOServerReadIndication visitedFetchRules.remove(fetchRule); } - private void prefetchRevisions(InternalCDORevisionManager revisionManager, int depth, CDORevision[] revisions, List<RevisionInfo> additionalInfos, - List<CDORevision> additionalRevisions, OMMonitor monitor) + private void prefetchRevisions(int depth, CDORevision[] revisions, List<RevisionInfo> additionalInfos, List<CDORevision> additionalRevisions, + OMMonitor monitor) { Map<CDOID, CDORevision> map = CDOIDUtil.createMap(); for (CDORevision revision : revisions) @@ -327,12 +439,12 @@ public class LoadRevisionsIndication extends CDOServerReadIndication for (CDORevision revision : revisions) { - prefetchRevision(revisionManager, depth, (InternalCDORevision)revision, additionalInfos, additionalRevisions, map, monitor.fork()); + prefetchRevision(depth, (InternalCDORevision)revision, additionalInfos, additionalRevisions, map, monitor.fork()); } } - private void prefetchRevision(InternalCDORevisionManager revisionManager, int depth, InternalCDORevision revision, List<RevisionInfo> additionalInfos, - List<CDORevision> additionalRevisions, Map<CDOID, CDORevision> map, OMMonitor monitor) + private void prefetchRevision(int depth, InternalCDORevision revision, List<RevisionInfo> additionalInfos, List<CDORevision> additionalRevisions, + Map<CDOID, CDORevision> map, OMMonitor monitor) { CDOClassInfo classInfo = revision.getClassInfo(); EStructuralFeature[] containments = classInfo.getAllPersistentContainments(); @@ -344,7 +456,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication if (value instanceof CDOID) { CDOID id = (CDOID)value; - prefetchRevisionChild(revisionManager, depth, id, additionalInfos, additionalRevisions, map, monitor.fork()); + prefetchRevisionChild(depth, id, additionalInfos, additionalRevisions, map, monitor.fork()); } else if (value instanceof Collection<?>) { @@ -360,7 +472,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication if (e instanceof CDOID) { CDOID id = (CDOID)e; - prefetchRevisionChild(revisionManager, depth, id, additionalInfos, additionalRevisions, map, subMonitor.fork()); + prefetchRevisionChild(depth, id, additionalInfos, additionalRevisions, map, subMonitor.fork()); } else { @@ -379,8 +491,8 @@ public class LoadRevisionsIndication extends CDOServerReadIndication monitor.done(); } - private void prefetchRevisionChild(InternalCDORevisionManager revisionManager, int depth, CDOID id, List<RevisionInfo> additionalInfos, - List<CDORevision> additionalRevisions, Map<CDOID, CDORevision> map, OMMonitor monitor) + private void prefetchRevisionChild(int depth, CDOID id, List<RevisionInfo> additionalInfos, List<CDORevision> additionalRevisions, + Map<CDOID, CDORevision> map, OMMonitor monitor) { if (CDOIDUtil.isNull(id)) { @@ -390,7 +502,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication CDORevision child = map.get(id); if (child == null) { - RevisionInfo info = createRevisionInfo(revisionManager, id); + RevisionInfo info = createRevisionInfo(id); child = info.getResult(); if (child != null) { @@ -402,7 +514,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication if (child != null && depth > 0) { - prefetchRevision(revisionManager, depth - 1, (InternalCDORevision)child, additionalInfos, additionalRevisions, map, monitor); + prefetchRevision(depth - 1, (InternalCDORevision)child, additionalInfos, additionalRevisions, map, monitor); } } } diff --git a/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters index a33c0c1fb5..2d7a2c5eae 100644 --- a/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters +++ b/plugins/org.eclipse.emf.cdo.server/.settings/.api_filters @@ -471,6 +471,12 @@ <message_argument value="InternalRepository"/> </message_arguments> </filter> + <filter id="574619656"> + <message_arguments> + <message_argument value="RevisionLoader3"/> + <message_argument value="InternalRepository"/> + </message_arguments> + </filter> <filter id="574668824"> <message_arguments> <message_argument value="IRepository"/> 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 f28278d5a1..256987fcec 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 @@ -902,7 +902,7 @@ public class LockingManager extends RWOLockManager<Object, IView> implements Int } @Override - public LockGrade getLockGrade(Object key) + public synchronized LockGrade getLockGrade(Object key) { LockState<Object, IView> lockState = getObjectToLocksMap().get(key); LockGrade grade = LockGrade.NONE; 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 5aa71298dd..2dcb2d33ac 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 @@ -763,8 +763,16 @@ public class Repository extends Container<Object> implements InternalRepository } @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) + { for (RevisionInfo info : infos) { CDOID id = info.getID(); 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 86d6e9c366..80589ebc83 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 @@ -23,6 +23,7 @@ import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; /** * The type of the to-be-locked objects is either {@link CDOIDAndBranch} or {@link CDOID}, depending on whether @@ -72,7 +73,7 @@ public interface InternalLockManager extends IRWOLockManager<Object, IView>, ILo long timeout) throws InterruptedException; /** - * Attempts to release for a given locktype, view and objects. + * Attempts to release for a given lock type, view and objects. * * @throws IllegalMonitorStateException * Unlocking objects without lock. @@ -131,6 +132,11 @@ public interface InternalLockManager extends IRWOLockManager<Object, IView>, ILo public LockState<Object, IView> getLockState(Object key); /** + * @since 4.15 + */ + public void getLockStates(Collection<Object> keys, BiConsumer<Object, LockState<Object, IView>> consumer); + + /** * @since 4.4 */ public List<LockState<Object, IView>> getLockStates(); 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 691db41627..9c17dab4ff 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 @@ -41,7 +41,7 @@ import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; import org.eclipse.emf.cdo.spi.common.revision.CDORevisionUnchunker; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader2; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader3; import org.eclipse.net4j.util.concurrent.IExecutorServiceProvider; import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; @@ -77,7 +77,7 @@ public interface InternalRepository extends IRepository, // PackageProcessor, // PackageLoader, // BranchLoader5, // - RevisionLoader2, // + RevisionLoader3, // CommitInfoLoader, // CDORevisionUnchunker, // OperationAuthorizer<ISession>, // diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_576893_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_576893_Test.java index 81a209d788..7c93816cff 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_576893_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_576893_Test.java @@ -10,6 +10,7 @@ */ package org.eclipse.emf.cdo.tests.bugzilla; +import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.CDOCommonSession.Options.PassiveUpdateMode; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.id.CDOID; @@ -17,6 +18,8 @@ import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionCache; import org.eclipse.emf.cdo.common.util.CDOCommonUtil; import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.internal.net4j.protocol.LockStateRequest; +import org.eclipse.emf.cdo.net4j.CDONet4jSession; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; @@ -30,8 +33,12 @@ import org.eclipse.emf.cdo.view.CDOPrefetcherManager; import org.eclipse.emf.cdo.view.CDOPrefetcherManager.Prefetcher; import org.eclipse.emf.cdo.view.CDOView; +import org.eclipse.net4j.signal.ISignalProtocol; +import org.eclipse.net4j.signal.SignalCounter; import org.eclipse.net4j.util.io.IOUtil; +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.ResourceSet; import java.util.ArrayList; @@ -63,7 +70,7 @@ public class Bugzilla_576893_Test extends AbstractCDOTest CDOSession session2 = openSession(); CDOView view = session2.openView(); - TestPrefetcherManager prefetcherManager = new TestPrefetcherManager(view.getResourceSet(), rootID); + TestPrefetcherManager prefetcherManager = new TestPrefetcherManager(view.getResourceSet(), rootID, false); prefetcherManager.activate(); waitUntilPrefetched(prefetcherManager); @@ -175,6 +182,44 @@ public class Bugzilla_576893_Test extends AbstractCDOTest prefetcherManager.deactivate(); } + @Requires(IRepositoryConfig.CAPABILITY_BRANCHING) + public void testLockStatePrefetching() throws Exception + { + Category root = getModel1Factory().createCategory(); + createModel(root, 2, 3, 2); + + CDOSession session1 = openSession(); + CDOTransaction transaction = session1.openTransaction(); + CDOResource resource = transaction.createResource(getResourcePath("res1")); + resource.getContents().add(root); + + transaction.commit(); + CDOID rootID = CDOUtil.getCDOObject(root).cdoID(); + + // ======================================================================================= + IOUtil.OUT().println("Testing open view..."); + CDOSession session2 = openSession(); + + ISignalProtocol<?> protocol = ((CDONet4jSession)session2).options().getNet4jProtocol(); + SignalCounter signalCounter = new SignalCounter(protocol); + + CDOView view = session2.openView(); + TestPrefetcherManager prefetcherManager = new TestPrefetcherManager(view.getResourceSet(), rootID, true); + prefetcherManager.activate(); + waitUntilPrefetched(prefetcherManager); + + CDOObject object = view.getObject(rootID); + object.cdoLockState(); + + for (TreeIterator<EObject> it = object.eAllContents(); it.hasNext();) + { + EObject child = it.next(); + CDOUtil.getCDOObject(child).cdoLockState(); + } + + assertEquals(0, signalCounter.getCountFor(LockStateRequest.class)); + } + private static void waitUntilPrefetched(TestPrefetcherManager prefetcherManager) { assertTrue(prefetcherManager.waitUntilPrefetched(DEFAULT_TIMEOUT)); @@ -247,9 +292,9 @@ public class Bugzilla_576893_Test extends AbstractCDOTest private final CDOID rootID; - public TestPrefetcherManager(ResourceSet resourceSet, CDOID rootID) + public TestPrefetcherManager(ResourceSet resourceSet, CDOID rootID, boolean prefetchLockStates) { - super(resourceSet); + super(resourceSet, prefetchLockStates); this.rootID = rootID; } @@ -262,7 +307,7 @@ public class Bugzilla_576893_Test extends AbstractCDOTest @Override protected Prefetcher createPrefetcher(CDOView view) { - return new Prefetcher(view, rootID) + return new Prefetcher(view, rootID, isPrefetchLockStates()) { @Override protected void prefetch() diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java index eb1c17278e..fabff6d028 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestRevisionManager.java @@ -103,10 +103,10 @@ public class TestRevisionManager extends CDORevisionManagerImpl } @Override - protected void loadRevisions(List<RevisionInfo> infosToLoad, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + protected void loadRevisions(List<RevisionInfo> infosToLoad, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean prefetchLockStates, List<CDORevision> additionalRevisions, Consumer<CDORevision> consumer) { - super.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth, additionalRevisions, consumer); + super.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates, additionalRevisions, consumer); synchronized (lock) { diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java index 5680470da8..e7e6975495 100644 --- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java +++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/CDOContentProvider.java @@ -15,12 +15,13 @@ import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDOList; import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.CDORevisionManager; import org.eclipse.emf.cdo.common.security.NoPermissionException; import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.internal.ui.bundle.OM; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; +import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.view.CDOView; @@ -339,9 +340,19 @@ public abstract class CDOContentProvider<CONTEXT> implements ITreeContentProvide { CDOObject cdoObject = getCDOObject((EObject)finalObject); view = cdoObject.cdoView(); - CDORevisionManager revisionManager = view.getSession().getRevisionManager(); - List<CDORevision> revisions = revisionManager.getRevisions(missingIDs, view, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true); + InternalCDORevisionManager revisionManager = (InternalCDORevisionManager)view.getSession().getRevisionManager(); + boolean prefetchLockStates = view.options().isLockNotificationEnabled(); + + List<CDORevision> revisions = revisionManager.getRevisions( // + missingIDs, // + view, // + CDORevision.UNCHUNKED, // + CDORevision.DEPTH_NONE, // + prefetchLockStates, // + true, // + (SyntheticCDORevision[])null); + loadedRevisions.addAll(revisions); } diff --git a/plugins/org.eclipse.emf.cdo/.settings/.api_filters b/plugins/org.eclipse.emf.cdo/.settings/.api_filters index 58f74f67e1..91b7e4a31f 100644 --- a/plugins/org.eclipse.emf.cdo/.settings/.api_filters +++ b/plugins/org.eclipse.emf.cdo/.settings/.api_filters @@ -981,6 +981,12 @@ <message_argument value="CDOSessionProtocol"/> </message_arguments> </filter> + <filter id="571473929"> + <message_arguments> + <message_argument value="RevisionLoader3"/> + <message_argument value="CDOSessionProtocol"/> + </message_arguments> + </filter> </resource> <resource path="src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java" type="org.eclipse.emf.spi.cdo.CDOSessionProtocol$CommitTransactionResult"> <filter id="574619656"> diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOPrefetcherManager.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOPrefetcherManager.java index 430cc6c1be..d0304fdeb2 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOPrefetcherManager.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOPrefetcherManager.java @@ -53,6 +53,8 @@ public class CDOPrefetcherManager extends CDOViewSetHandler private final ExecutorService executorService; + private final boolean prefetchLockStates; + private final Map<CDOView, Prefetcher> prefetchers = Collections.synchronizedMap(new HashMap<>()); @ExcludeFromDump @@ -60,12 +62,18 @@ public class CDOPrefetcherManager extends CDOViewSetHandler private int runnables; - public CDOPrefetcherManager(ResourceSet resourceSet) + public CDOPrefetcherManager(ResourceSet resourceSet, boolean prefetchLockStates) { super(resourceSet); + this.prefetchLockStates = prefetchLockStates; executorService = ConcurrencyUtil.getExecutorService(getViewSet()); } + public boolean isPrefetchLockStates() + { + return prefetchLockStates; + } + public final Prefetcher[] getPrefetchers() { // Don't use prefetchers.size() because that wouldn't be thread-safe anymore. @@ -169,7 +177,7 @@ public class CDOPrefetcherManager extends CDOViewSetHandler protected Prefetcher createPrefetcher(CDOView view) { - return new Prefetcher(view); + return new Prefetcher(view, prefetchLockStates); } protected void schedule(Runnable runnable) @@ -222,6 +230,8 @@ public class CDOPrefetcherManager extends CDOViewSetHandler private final InternalCDORevisionManager revisionManager; + private final boolean prefetchLockStates; + private final IListener cacheListener = new IListener() { @Override @@ -256,11 +266,13 @@ public class CDOPrefetcherManager extends CDOViewSetHandler private volatile boolean cancelCleanup; - public Prefetcher(CDOView view, CDOID rootID) + public Prefetcher(CDOView view, CDOID rootID, boolean prefetchLockStates) { this.view = view; + CDOSession session = view.getSession(); this.rootID = rootID != null ? rootID : session.getRepositoryInfo().getRootResourceID(); + this.prefetchLockStates = prefetchLockStates; revisionManager = (InternalCDORevisionManager)session.getRevisionManager(); revisionManager.getCache().addListener(cacheListener); @@ -268,9 +280,9 @@ public class CDOPrefetcherManager extends CDOViewSetHandler branchPoint = CDOBranchUtil.copyBranchPoint(view); } - public Prefetcher(CDOView view) + public Prefetcher(CDOView view, boolean prefetchLockStates) { - this(view, null); + this(view, null, prefetchLockStates); } public final CDOView getView() @@ -440,7 +452,7 @@ public class CDOPrefetcherManager extends CDOViewSetHandler try { - revisionManager.prefetchRevisions(rootID, branchPoint, CDORevision.DEPTH_INFINITE, r -> handleValidRevision(r)); + revisionManager.prefetchRevisions(rootID, branchPoint, CDORevision.DEPTH_INFINITE, prefetchLockStates, r -> handleValidRevision(r)); } finally { 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 7496890d65..0492efa243 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 @@ -474,7 +474,7 @@ public class DelegatingSessionProtocol extends Lifecycle implements CDOSessionPr @Deprecated public CDOLockState[] getLockStates(int branchID, Collection<CDOID> ids) { - return getLockStates(branchID, ids, CDOLockState.DEPTH_NONE); + throw new UnsupportedOperationException(); } @Override @@ -768,14 +768,22 @@ public class DelegatingSessionProtocol extends Lifecycle implements CDOSessionPr } @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) + { int attempt = 0; for (;;) { try { - return delegate.loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth); + return delegate.loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth, prefetchLockStates); } catch (Exception ex) { @@ -1165,7 +1173,7 @@ public class DelegatingSessionProtocol extends Lifecycle implements CDOSessionPr @Deprecated public void requestChangeCredentials() { - requestChangeServerPassword(null); + throw new UnsupportedOperationException(); } @Override 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 3bad71f8bf..c180bed6b7 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 @@ -49,7 +49,7 @@ import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; import org.eclipse.emf.cdo.spi.common.revision.CDOIDMapper; import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader2; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader3; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.net4j.util.CheckUtil; @@ -87,7 +87,7 @@ import java.util.concurrent.atomic.AtomicReference; * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. */ -public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLoader5, RevisionLoader2, CommitInfoLoader +public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLoader5, RevisionLoader3, CommitInfoLoader { public RepositoryTimeResult getRepositoryTime(); 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 6659e0dca5..95667be118 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 @@ -27,6 +27,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiConsumer; /** * Keeps track of locks on objects. Locks are owned by contexts. A particular combination of locks and their owners, for @@ -297,12 +298,23 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWOLo return contextToLockStates; } - public LockState<OBJECT, CONTEXT> getLockState(OBJECT key) + public synchronized LockState<OBJECT, CONTEXT> getLockState(OBJECT key) { return objectToLockStateMap.get(key); } /** + * @since 3.16 + */ + public synchronized void getLockStates(Collection<OBJECT> keys, BiConsumer<OBJECT, LockState<OBJECT, CONTEXT>> consumer) + { + keys.forEach(key -> { + LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(key); + consumer.accept(key, lockState); + }); + } + + /** * @since 3.5 */ public synchronized List<LockState<OBJECT, CONTEXT>> getLockStates() |