From 6bfe9d00fd54fcc24b9ac238f6fc63d15cf58537 Mon Sep 17 00:00:00 2001 From: Esteban Dugueperoux Date: Fri, 30 May 2014 17:03:29 +0200 Subject: [436246] CDOObject.cdoPrefetch() useless on CDOBranch Have prefetch returning RevisionInfo, instead of referenced CDORevision, to have PointCDORevision put in cache. Fix the case of a PointerCDORevision without target by putting result as target in RevisionInfo.readResult(). Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=436246 Change-Id: I49744c824b732da12fdbc7818d305d7f5d11ea00 Signed-off-by: Esteban Dugueperoux --- .../cdo/common/protocol/CDOProtocolConstants.java | 6 +- .../common/revision/CDORevisionCacheAuditing.java | 6 +- .../common/revision/CDORevisionManagerImpl.java | 13 +- .../revision/InternalCDORevisionManager.java | 2 +- .../emf/cdo/spi/common/revision/RevisionInfo.java | 22 +- .../internal/net4j/protocol/CDOClientProtocol.java | 6 +- .../net4j/protocol/LoadRevisionsRequest.java | 18 +- .../net4j/protocol/LoadRevisionsIndication.java | 72 +++-- .../emf/cdo/internal/server/Repository.java | 2 +- .../embedded/EmbeddedClientSessionProtocol.java | 2 +- .../cdo/tests/bugzilla/Bugzilla_436246_Test.java | 333 +++++++++++++++++++++ .../cdo/session/DelegatingSessionProtocol.java | 2 +- 12 files changed, 428 insertions(+), 56 deletions(-) create mode 100644 plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_436246_Test.java (limited to 'plugins') 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 778a3871d2..69831ef281 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 @@ -29,9 +29,11 @@ public interface CDOProtocolConstants /** * @since 4.2 */ - public static final int PROTOCOL_VERSION = 21; // Update how CDOChangeSetData's detachedObject is encoded, see - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=449171 + public static final int PROTOCOL_VERSION = 21; // Have prefetch returns RevisionInfo instead of CDORevision to have + // PointerCDORevision + // public static final int PROTOCOL_VERSION = 21; // Update how CDOChangeSetData's detachedObject is encoded, see + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=449171 // public static final int PROTOCOL_VERSION = 20; // Have OMMOnitor optional in // RequestWithMonitoring/IndicationWithMonitoring // public static final int PROTOCOL_VERSION = 19; // Branch renaming diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java index cb050558d2..408ed210c4 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionCacheAuditing.java @@ -187,8 +187,10 @@ public class CDORevisionCacheAuditing extends AbstractCDORevisionCache revisionLists.put(key, list); } - list.addRevision((InternalCDORevision)revision, createReference(revision)); - typeRefIncrease(id, revision.getEClass()); + if (list.addRevision((InternalCDORevision)revision, createReference(revision))) + { + typeRefIncrease(id, revision.getEClass()); + } } } 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 c4be7fc240..f149dffc1d 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 @@ -390,14 +390,17 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi try { - List additionalRevisions = // - revisionLoader.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth); + List additionalRevisions = null; + List additionalRevisionInfos = // + revisionLoader.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth); - if (additionalRevisions != null) + if (additionalRevisionInfos != null) { - for (InternalCDORevision revision : additionalRevisions) + additionalRevisions = new ArrayList(additionalRevisionInfos.size()); + for (RevisionInfo info : additionalRevisionInfos) { - addRevision(revision); + info.processResult(this, new ArrayList(), null, 0); + additionalRevisions.add(info.getResult()); } } 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 7a4d4d09b9..67d1ef0a30 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 @@ -97,7 +97,7 @@ public interface InternalCDORevisionManager extends CDORevisionManager, CDORevis */ public interface RevisionLoader { - public List loadRevisions(List infos, CDOBranchPoint branchPoint, + public List loadRevisions(List infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth); public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/RevisionInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/RevisionInfo.java index d41443ab6d..6297734fe0 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/RevisionInfo.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/RevisionInfo.java @@ -163,7 +163,7 @@ public abstract class RevisionInfo public void readResult(CDODataInput in) throws IOException { readRevision(in); - synthetic = (SyntheticCDORevision)readResult(in, getID(), requestedBranchPoint.getBranch()); + synthetic = (SyntheticCDORevision)readResult(in, getID(), requestedBranchPoint.getBranch(), result); } public void processResult(InternalCDORevisionManager revisionManager, List results, @@ -280,10 +280,8 @@ public abstract class RevisionInfo } } - /** - * @since 4.0 - */ - public static InternalCDORevision readResult(CDODataInput in, CDOID id, CDOBranch branch) throws IOException + private static InternalCDORevision readResult(CDODataInput in, CDOID id, CDOBranch branch, InternalCDORevision result) + throws IOException { byte type = in.readByte(); switch (type) @@ -296,6 +294,12 @@ public abstract class RevisionInfo EClassifier classifier = in.readCDOClassifierRefAndResolve(); long revised = in.readLong(); InternalCDORevision target = readResult(in, id, branch); + // If target is null and where are in a Available RevisionInfo it mean that we can use + // availableBranchVersion/result as target + if (target == null && result != null) + { + target = result; + } return new PointerCDORevision((EClass)classifier, id, branch, revised, target); } @@ -316,6 +320,14 @@ public abstract class RevisionInfo } } + /** + * @since 4.0 + */ + public static InternalCDORevision readResult(CDODataInput in, CDOID id, CDOBranch branch) throws IOException + { + return readResult(in, id, branch, null); + } + /** * @deprecated Not called anymore by the framework */ 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 e9f6acf529..92e84e7585 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 @@ -183,7 +183,7 @@ public class CDOClientProtocol extends AuthenticatingSignalProtocol loadRevisions(List infos, CDOBranchPoint branchPoint, + public List loadRevisions(List infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth) { return send(new LoadRevisionsRequest(this, infos, branchPoint, referenceChunk, prefetchDepth)); @@ -547,12 +547,12 @@ public class CDOClientProtocol extends AuthenticatingSignalProtocol send(LoadRevisionsRequest request) + private List send(LoadRevisionsRequest request) { try { REVISION_LOADING.start(request); - return send((RequestWithConfirmation>)request); + return send((RequestWithConfirmation>)request); } finally { 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 92bee45a03..34d8d584ff 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 @@ -19,7 +19,6 @@ import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.util.CDOFetchRule; import org.eclipse.emf.cdo.internal.net4j.bundle.OM; import org.eclipse.emf.cdo.session.CDOCollectionLoadingPolicy; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; import org.eclipse.emf.cdo.view.CDOFetchRuleManager; @@ -34,7 +33,7 @@ import java.util.List; /** * @author Eike Stepper */ -public class LoadRevisionsRequest extends CDOClientRequest> +public class LoadRevisionsRequest extends CDOClientRequest> { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, LoadRevisionsRequest.class); @@ -130,7 +129,7 @@ public class LoadRevisionsRequest extends CDOClientRequest confirming(CDODataInput in) throws IOException + protected List confirming(CDODataInput in) throws IOException { int size = infos.size(); if (TRACER.isEnabled()) @@ -143,24 +142,25 @@ public class LoadRevisionsRequest extends CDOClientRequest additionalRevisions = null; + List additionalRevisionInfos = null; int additionalSize = in.readInt(); if (additionalSize != 0) { if (TRACER.isEnabled()) { - TRACER.format("Reading {0} additional revisions", additionalSize); //$NON-NLS-1$ + TRACER.format("Reading {0} additional revision infos", additionalSize); //$NON-NLS-1$ } - additionalRevisions = new ArrayList(additionalSize); + additionalRevisionInfos = new ArrayList(additionalSize); for (int i = 0; i < additionalSize; i++) { - InternalCDORevision revision = (InternalCDORevision)in.readCDORevision(); - additionalRevisions.add(revision); + RevisionInfo info = RevisionInfo.read(in, branchPoint); + info.readResult(in); + additionalRevisionInfos.add(info); } } - return additionalRevisions; + return additionalRevisionInfos; } @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 2e373736e0..2a01ece004 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 @@ -23,6 +23,7 @@ import org.eclipse.emf.cdo.server.internal.net4j.bundle.OM; 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.RevisionInfo; +import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo.Type; import org.eclipse.net4j.util.collection.MoveableList; import org.eclipse.net4j.util.om.trace.ContextTracer; @@ -136,6 +137,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication protected void responding(CDODataOutput out) throws IOException { List additionalRevisions = new ArrayList(); + List additionalRevisionInfos = new ArrayList(); Set revisionIDs = new HashSet(); int size = infos.length; if (TRACER.isEnabled()) @@ -157,8 +159,9 @@ public class LoadRevisionsIndication extends CDOServerReadIndication TRACER.format("Collecting more revisions based on rules"); //$NON-NLS-1$ } - InternalCDORevision revisionContext = getRevision(contextID); - collectRevisions(revisionContext, revisionIDs, additionalRevisions, visitedFetchRules); + RevisionInfo info = getRevisionInfo(contextID); + InternalCDORevision revisionContext = info.getResult(); + collectRevisions(revisionContext, revisionIDs, additionalRevisionInfos, additionalRevisions, visitedFetchRules); } InternalCDORevisionManager revisionManager = getRepository().getRevisionManager(); @@ -170,13 +173,14 @@ public class LoadRevisionsIndication extends CDOServerReadIndication revisions[i] = info.getResult(); if (loadRevisionCollectionChunkSize > 0) { - collectRevisions(revisions[i], revisionIDs, additionalRevisions, visitedFetchRules); + collectRevisions(revisions[i], revisionIDs, additionalRevisionInfos, additionalRevisions, visitedFetchRules); } } if (prefetchDepth != 0) { - prefetchRevisions(prefetchDepth > 0 ? prefetchDepth : Integer.MAX_VALUE, revisions, additionalRevisions); + prefetchRevisions(prefetchDepth > 0 ? prefetchDepth : Integer.MAX_VALUE, revisions, additionalRevisionInfos, + additionalRevisions); } getRepository().notifyReadAccessHandlers(getSession(), revisions, additionalRevisions); @@ -188,27 +192,34 @@ public class LoadRevisionsIndication extends CDOServerReadIndication info.writeResult(out, referenceChunk, branchPoint); // Exposes revision to client side } - int additionalSize = additionalRevisions.size(); + int additionalSize = additionalRevisionInfos.size(); if (TRACER.isEnabled()) { - TRACER.format("Writing {0} additional revisions", additionalSize); //$NON-NLS-1$ + TRACER.format("Writing {0} additional revision infos", additionalSize); //$NON-NLS-1$ } out.writeInt(additionalSize); - for (CDORevision revision : additionalRevisions) + for (int i = 0; i < additionalSize; i++) { - out.writeCDORevision(revision, referenceChunk, branchPoint); // Exposes revision to client side + InternalCDORevision revision = (InternalCDORevision)additionalRevisions.get(i); + RevisionInfo info = additionalRevisionInfos.get(i); + info.setResult(revision); + out.write(Type.MISSING.ordinal()); + out.writeCDOID(info.getID()); + info.writeResult(out, referenceChunk, branchPoint); } } - private InternalCDORevision getRevision(CDOID id) + private RevisionInfo getRevisionInfo(CDOID id) { - return getRepository().getRevisionManager().getRevision(id, branchPoint, referenceChunk, CDORevision.DEPTH_NONE, - true); + RevisionInfo info = new RevisionInfo.Missing(id, branchPoint); + info.execute(getRepository().getRevisionManager(), referenceChunk); + return info; } private void collectRevisions(InternalCDORevision revision, Set revisions, - List additionalRevisions, Set visitedFetchRules) + List additionalRevisionInfos, List additionalRevisions, + Set visitedFetchRules) { if (revision == null) { @@ -239,12 +250,15 @@ public class LoadRevisionsIndication extends CDOServerReadIndication CDOID id = (CDOID)value; if (!CDOIDUtil.isNull(id) && !revisions.contains(id)) { - InternalCDORevision containedRevision = getRevision(id); + RevisionInfo info = getRevisionInfo(id); + InternalCDORevision containedRevision = info.getResult(); if (containedRevision != null) { + additionalRevisionInfos.add(info); revisions.add(containedRevision.getID()); additionalRevisions.add(containedRevision); - collectRevisions(containedRevision, revisions, additionalRevisions, visitedFetchRules); + collectRevisions(containedRevision, revisions, additionalRevisionInfos, additionalRevisions, + visitedFetchRules); } } } @@ -258,12 +272,14 @@ public class LoadRevisionsIndication extends CDOServerReadIndication CDOID id = (CDOID)value; if (!id.isNull() && !revisions.contains(id)) { - InternalCDORevision containedRevision = getRevision(id); + RevisionInfo info = getRevisionInfo(id); + InternalCDORevision containedRevision = info.getResult(); if (containedRevision != null) { revisions.add(containedRevision.getID()); additionalRevisions.add(containedRevision); - collectRevisions(containedRevision, revisions, additionalRevisions, visitedFetchRules); + collectRevisions(containedRevision, revisions, additionalRevisionInfos, additionalRevisions, + visitedFetchRules); } } } @@ -273,7 +289,8 @@ public class LoadRevisionsIndication extends CDOServerReadIndication visitedFetchRules.remove(fetchRule); } - private void prefetchRevisions(int depth, CDORevision[] revisions, List additionalRevisions) + private void prefetchRevisions(int depth, CDORevision[] revisions, List additionalRevisionInfos, + List additionalRevisions) { Map map = CDOIDUtil.createMap(); for (CDORevision revision : revisions) @@ -288,12 +305,12 @@ public class LoadRevisionsIndication extends CDOServerReadIndication for (CDORevision revision : revisions) { - prefetchRevision(depth, (InternalCDORevision)revision, additionalRevisions, map); + prefetchRevision(depth, (InternalCDORevision)revision, additionalRevisionInfos, additionalRevisions, map); } } - private void prefetchRevision(int depth, InternalCDORevision revision, List additionalRevisions, - Map map) + private void prefetchRevision(int depth, InternalCDORevision revision, List additionalRevisionInfos, + List additionalRevisions, Map map) { CDOClassInfo classInfo = revision.getClassInfo(); for (EStructuralFeature feature : classInfo.getAllPersistentFeatures()) @@ -307,7 +324,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication if (value instanceof CDOID) { CDOID id = (CDOID)value; - prefetchRevisionChild(depth, id, additionalRevisions, map); + prefetchRevisionChild(depth, id, additionalRevisionInfos, additionalRevisions, map); } else if (value instanceof Collection) { @@ -320,7 +337,7 @@ public class LoadRevisionsIndication extends CDOServerReadIndication if (e instanceof CDOID) { CDOID id = (CDOID)e; - prefetchRevisionChild(depth, id, additionalRevisions, map); + prefetchRevisionChild(depth, id, additionalRevisionInfos, additionalRevisions, map); } } } @@ -329,8 +346,8 @@ public class LoadRevisionsIndication extends CDOServerReadIndication } } - private void prefetchRevisionChild(int depth, CDOID id, List additionalRevisions, - Map map) + private void prefetchRevisionChild(int depth, CDOID id, List additionalRevisionInfos, + List additionalRevisions, Map map) { if (CDOIDUtil.isNull(id)) { @@ -340,17 +357,20 @@ public class LoadRevisionsIndication extends CDOServerReadIndication CDORevision child = map.get(id); if (child == null) { - child = getRevision(id); + RevisionInfo info = getRevisionInfo(id); + child = info.getResult(); if (child != null) { map.put(id, child); additionalRevisions.add(child); + additionalRevisionInfos.add(info); } } if (child != null && depth > 0) { - prefetchRevision(depth - 1, (InternalCDORevision)child, additionalRevisions, map); + prefetchRevision(depth - 1, (InternalCDORevision)child, additionalRevisionInfos, additionalRevisions, map); } } + } 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 8c059fa02e..3c22add177 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 @@ -480,7 +480,7 @@ public class Repository extends Container implements InternalRepository return accessor.loadCommitData(timeStamp); } - public List loadRevisions(List infos, CDOBranchPoint branchPoint, + public List loadRevisions(List infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth) { for (RevisionInfo info : infos) diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java index 03ff06f428..6dd8e30c1c 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java @@ -219,7 +219,7 @@ public class EmbeddedClientSessionProtocol extends Lifecycle implements CDOSessi } } - public List loadRevisions(List infos, CDOBranchPoint branchPoint, + public List loadRevisions(List infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth) { try diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_436246_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_436246_Test.java new file mode 100644 index 0000000000..afcc8e19e2 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_436246_Test.java @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2014 Eike Stepper (Berlin, 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: + * Esteban Dugueperoux - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +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.protocol.CDOProtocolConstants; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.util.CDOFetchRule; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.internal.net4j.protocol.CDOClientProtocol; +import org.eclipse.emf.cdo.internal.net4j.protocol.LoadRevisionsRequest; +import org.eclipse.emf.cdo.session.CDOCollectionLoadingPolicy; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.config.IRepositoryConfig; +import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.CleanRepositoriesBefore; +import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Requires; +import org.eclipse.emf.cdo.tests.model1.Category; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOURIUtil; +import org.eclipse.emf.cdo.util.CDOUtil; +import org.eclipse.emf.cdo.view.CDOFetchRuleManager; +import org.eclipse.emf.cdo.view.CDOView; + +import org.eclipse.net4j.signal.Signal; +import org.eclipse.net4j.signal.SignalScheduledEvent; +import org.eclipse.net4j.util.event.IEvent; +import org.eclipse.net4j.util.event.IListener; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EContentAdapter; +import org.eclipse.emf.spi.cdo.InternalCDOSession; + +import org.junit.Assert; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Test {@link CDOObject#cdoPrefetch(int)} with branch. + * + * @author Esteban Dugueperoux + */ +@Requires(IRepositoryConfig.CAPABILITY_BRANCHING) +@CleanRepositoriesBefore(reason = "to not be disturb by branches created by others tests") +public class Bugzilla_436246_Test extends AbstractCDOTest +{ + private static final String RESOURCE_NAME = "test1.model1"; + + private static final String B1_BRANCH_NAME = "b1"; + + private static final String B11_BRANCH_NAME = "b11"; + + private static final int NB_CATEGORY = 10; + + @Override + public void setUp() throws Exception + { + super.setUp(); + CDOSession session = openSession(); + CDOTransaction transaction = session.openTransaction(); + CDOResource resource = transaction.createResource(getResourcePath(RESOURCE_NAME)); + Company company = getModel1Factory().createCompany(); + for (int i = 0; i < NB_CATEGORY; i++) + { + Category category = getModel1Factory().createCategory(); + company.getCategories().add(category); + } + resource.getContents().add(company); + transaction.commit(); + transaction.close(); + session.close(); + } + + /** + * Test prefetch on different branches with each having changes. + */ + public void testCDORevisionPrefetchOnOtherBranchWithChanges() throws Exception + { + // Setup + CDOID companyCDOID = setUpChangesOnBranches(); + + // Test + CDOSession session = openSession(); + InternalCDOSession internalCDOSession = (InternalCDOSession)session; + CDOClientProtocol cdoClientProtocol = (CDOClientProtocol)internalCDOSession.getSessionProtocol(); + LoadRevisionsRequestCounter loadRevisionsRequestCounter = new LoadRevisionsRequestCounter(); + cdoClientProtocol.addListener(loadRevisionsRequestCounter); + + CDOBranch currentBranch = session.getBranchManager().getMainBranch(); + testCDORevisionFetchWithChangesOnAllBranches(session, currentBranch, loadRevisionsRequestCounter, companyCDOID, + NB_CATEGORY, true); + + currentBranch = currentBranch.getBranch(B1_BRANCH_NAME); + testCDORevisionFetchWithChangesOnAllBranches(session, currentBranch, loadRevisionsRequestCounter, companyCDOID, + 2 * NB_CATEGORY, true); + + currentBranch = currentBranch.getBranch(B11_BRANCH_NAME); + testCDORevisionFetchWithChangesOnAllBranches(session, currentBranch, loadRevisionsRequestCounter, companyCDOID, + 3 * NB_CATEGORY, true); + + } + + /** + * Test {@link CDOCollectionLoadingPolicy} on different branches with each having changes. + */ + public void testCDORevisionCDOFetchRuleOnOtherBranchWithChanges() throws Exception + { + // Setup + CDOID companyCDOID = setUpChangesOnBranches(); + + // Test + CDOSession session = openSession(); + InternalCDOSession internalCDOSession = (InternalCDOSession)session; + CDOFetchRuleManager fetchRuleManager = new CustomCDOFetchRuleManager(companyCDOID); + internalCDOSession.setFetchRuleManager(fetchRuleManager); + CDOClientProtocol cdoClientProtocol = (CDOClientProtocol)internalCDOSession.getSessionProtocol(); + LoadRevisionsRequestCounter loadRevisionsRequestCounter = new LoadRevisionsRequestCounter(); + cdoClientProtocol.addListener(loadRevisionsRequestCounter); + + CDOBranch currentBranch = session.getBranchManager().getMainBranch(); + testCDORevisionFetchWithChangesOnAllBranches(session, currentBranch, loadRevisionsRequestCounter, companyCDOID, + NB_CATEGORY, false); + + currentBranch = currentBranch.getBranch(B1_BRANCH_NAME); + testCDORevisionFetchWithChangesOnAllBranches(session, currentBranch, loadRevisionsRequestCounter, companyCDOID, + 2 * NB_CATEGORY, false); + + currentBranch = currentBranch.getBranch(B11_BRANCH_NAME); + testCDORevisionFetchWithChangesOnAllBranches(session, currentBranch, loadRevisionsRequestCounter, companyCDOID, + 3 * NB_CATEGORY, false); + + } + + private void testCDORevisionFetchWithChangesOnAllBranches(CDOSession session, CDOBranch currentBranch, + LoadRevisionsRequestCounter loadRevisionsRequestCounter, CDOID companyCDOID, int expectedNbCategories, + boolean prefetch) + { + CDOView view = session.openView(currentBranch); + + assertEquals(0, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + String resourcePath = getResourcePath(RESOURCE_NAME); + List pathSegments = CDOURIUtil.analyzePath(resourcePath); + CDOResource resource = view.getResource(resourcePath); + assertEquals(pathSegments.size(), loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + if (prefetch) + { + resource.cdoPrefetch(CDORevision.DEPTH_INFINITE); + } + assertEquals(RESOURCE_NAME, resource.getName()); + EObject eObject = resource.getContents().get(0); + Assert.assertTrue(eObject instanceof Company); + Company company = (Company)eObject; + assertEquals(pathSegments.size() + 1, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + Assert.assertEquals(expectedNbCategories, company.getCategories().size()); + + view.getRevision(companyCDOID); + + assertEquals(pathSegments.size() + 1, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + view.getResourceSet().eAdapters().add(new EContentAdapter()); + + assertEquals(pathSegments.size() + 1, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + view.close(); + loadRevisionsRequestCounter.reset(); + } + + private CDOID setUpChangesOnBranches() throws Exception + { + CDOSession session = openSession(); + CDOBranch b1Branch = session.getBranchManager().getMainBranch().createBranch(B1_BRANCH_NAME); + + CDOTransaction transaction = session.openTransaction(b1Branch); + CDOResource resource = transaction.getResource(getResourcePath(RESOURCE_NAME)); + Company company = (Company)resource.getContents().get(0); + for (int i = 0; i < NB_CATEGORY; i++) + { + company.getCategories().add(getModel1Factory().createCategory()); + } + transaction.commit(); + transaction.close(); + + CDOBranch b2Branch = b1Branch.createBranch(B11_BRANCH_NAME); + + transaction = session.openTransaction(b2Branch); + resource = transaction.getResource(getResourcePath(RESOURCE_NAME)); + company = (Company)resource.getContents().get(0); + for (int i = 0; i < NB_CATEGORY; i++) + { + company.getCategories().add(getModel1Factory().createCategory()); + } + transaction.commit(); + transaction.close(); + session.close(); + + return CDOUtil.getCDOObject(company).cdoID(); + } + + /** + * Test that after a prefetch of infinite depth of CDORevision on a CDOResource, no more LoadRevisionRequest are sent on the main branch. + */ + public void testCDORevisionPrefetchOnMainBranch() throws Exception + { + CDOSession session = openSession(); + CDOBranch mainBranch = session.getBranchManager().getMainBranch(); + testCDORevisionPrefetchOnBranch(session, mainBranch); + } + + /** + * Test that after a prefetch of infinite depth of CDORevision on a CDOResource, no more LoadRevisionRequest are sent on the branch "B1". + */ + public void testCDORevisionPrefetchOnOtherBranch() throws Exception + { + CDOSession session = openSession(); + String newBranchName = "B1"; + CDOBranch newBranch = session.getBranchManager().getMainBranch().createBranch(newBranchName); + testCDORevisionPrefetchOnBranch(session, newBranch); + } + + private void testCDORevisionPrefetchOnBranch(CDOSession session, CDOBranch cdoBranch) throws Exception + { + CDOTransaction view = session.openTransaction(cdoBranch); + InternalCDOSession internalCDOSession = (InternalCDOSession)session; + CDOClientProtocol cdoClientProtocol = (CDOClientProtocol)internalCDOSession.getSessionProtocol(); + LoadRevisionsRequestCounter loadRevisionsRequestCounter = new LoadRevisionsRequestCounter(); + cdoClientProtocol.addListener(loadRevisionsRequestCounter); + + assertEquals(0, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + String resourcePath = getResourcePath(RESOURCE_NAME); + List pathSegments = CDOURIUtil.analyzePath(resourcePath); + CDOResource resource = view.getResource(resourcePath); + assertEquals(pathSegments.size(), loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + resource.cdoPrefetch(CDORevision.DEPTH_INFINITE); + + assertEquals(pathSegments.size() + 1, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + Company company = (Company)resource.getContents().get(0); + CDOID companyCDOID = CDOUtil.getCDOObject(company).cdoID(); + + assertEquals(pathSegments.size() + 1, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + view.getRevision(companyCDOID); + + assertEquals(pathSegments.size() + 1, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + view.getResourceSet().eAdapters().add(new EContentAdapter()); + + assertEquals(pathSegments.size() + 1, loadRevisionsRequestCounter.getNbLoadRevisionsRequestCalls()); + + } + + private static class LoadRevisionsRequestCounter implements IListener + { + + private int nbLoadRevisionsRequestCalls = 0; + + public void notifyEvent(IEvent event) + { + if (event instanceof SignalScheduledEvent) + { + @SuppressWarnings("unchecked") + SignalScheduledEvent signalScheduledEvent = (SignalScheduledEvent)event; + Signal signal = signalScheduledEvent.getSignal(); + if (signal.getID() == CDOProtocolConstants.SIGNAL_LOAD_REVISIONS && signal instanceof LoadRevisionsRequest) + { + nbLoadRevisionsRequestCalls++; + } + } + } + + public int getNbLoadRevisionsRequestCalls() + { + return nbLoadRevisionsRequestCalls; + } + + public void reset() + { + nbLoadRevisionsRequestCalls = 0; + } + + } + + private class CustomCDOFetchRuleManager implements CDOFetchRuleManager + { + + private CDOID companyCDOID; + + public CustomCDOFetchRuleManager(CDOID companyCDOID) + { + this.companyCDOID = companyCDOID; + } + + public CDOID getContext() + { + return companyCDOID; + } + + public List getFetchRules(Collection ids) + { + List fetchRules = null; + if (ids.contains(companyCDOID)) + { + CDOFetchRule fetchRule = new CDOFetchRule(getModel1Package().getCompany()); + fetchRule.addFeature(getModel1Package().getCompany_Categories()); + fetchRules = Collections.singletonList(fetchRule); + } + return fetchRules; + } + + public CDOCollectionLoadingPolicy getCollectionLoadingPolicy() + { + return CDOUtil.createCollectionLoadingPolicy(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + } + +} 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 6e18026a84..3142856e1d 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 @@ -622,7 +622,7 @@ public class DelegatingSessionProtocol extends Lifecycle implements CDOSessionPr } } - public List loadRevisions(List infos, CDOBranchPoint branchPoint, + public List loadRevisions(List infos, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth) { int attempt = 0; -- cgit v1.2.3