diff options
10 files changed, 217 insertions, 22 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DetachedCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DetachedCDORevision.java index 2b43da8b67..8de399b017 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DetachedCDORevision.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DetachedCDORevision.java @@ -27,11 +27,22 @@ public class DetachedCDORevision extends SyntheticCDORevision private long timeStamp; + private long revised; + public DetachedCDORevision(EClass eClass, CDOID id, CDOBranch branch, int version, long timeStamp) { + this(eClass, id, branch, version, timeStamp, UNSPECIFIED_DATE); + } + + /** + * @since 3.0 + */ + public DetachedCDORevision(EClass eClass, CDOID id, CDOBranch branch, int version, long timeStamp, long revised) + { super(eClass, id, branch); this.version = version; this.timeStamp = timeStamp; + this.revised = revised; } @Override @@ -49,7 +60,7 @@ public class DetachedCDORevision extends SyntheticCDORevision @Override public long getRevised() { - return UNSPECIFIED_DATE; + return revised; } @Override @@ -57,4 +68,10 @@ public class DetachedCDORevision extends SyntheticCDORevision { return MessageFormat.format("DetachedCDORevision[{0}:{1}v{2}]", getID(), getBranch().getID(), version); } + + @Override + public void setRevised(long revised) + { + this.revised = revised; + } } 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 567f9decf8..e9a66cb565 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 @@ -10,6 +10,7 @@ */ package org.eclipse.emf.cdo.spi.common.revision; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; @@ -136,13 +137,13 @@ public abstract class RevisionInfo public void writeResult(CDODataOutput out, int referenceChunk) throws IOException { writeRevision(out, referenceChunk); - doWriteResult(out, synthetic, referenceChunk); + writeResult(out, referenceChunk, synthetic); } public void readResult(CDODataInput in) throws IOException { readRevision(in); - synthetic = (SyntheticCDORevision)doReadResult(in); + synthetic = (SyntheticCDORevision)readResult(in, getID(), requestedBranchPoint.getBranch()); } public void processResult(InternalCDORevisionManager revisionManager, List<CDORevision> results, @@ -192,7 +193,11 @@ public abstract class RevisionInfo result = (InternalCDORevision)in.readCDORevision(); } - protected void doWriteResult(CDODataOutput out, InternalCDORevision revision, int referenceChunk) throws IOException + /** + * @since 3.0 + */ + public static void writeResult(CDODataOutput out, int referenceChunk, InternalCDORevision revision) + throws IOException { if (revision == null) { @@ -208,7 +213,7 @@ public abstract class RevisionInfo CDOBranchVersion target = pointer.getTarget(); if (target instanceof InternalCDORevision) { - doWriteResult(out, (InternalCDORevision)target, referenceChunk); + writeResult(out, referenceChunk, (InternalCDORevision)target); } else { @@ -221,6 +226,7 @@ public abstract class RevisionInfo out.writeByte(DETACHED_RESULT); out.writeCDOClassifierRef(detached.getEClass()); out.writeLong(detached.getTimeStamp()); + out.writeLong(detached.getRevised()); out.writeInt(detached.getVersion()); } else @@ -230,7 +236,10 @@ public abstract class RevisionInfo } } - protected InternalCDORevision doReadResult(CDODataInput in) throws IOException + /** + * @since 3.0 + */ + public static InternalCDORevision readResult(CDODataInput in, CDOID id, CDOBranch branch) throws IOException { byte type = in.readByte(); switch (type) @@ -242,16 +251,17 @@ public abstract class RevisionInfo { EClassifier classifier = in.readCDOClassifierRefAndResolve(); long revised = in.readLong(); - InternalCDORevision target = doReadResult(in); - return new PointerCDORevision((EClass)classifier, id, requestedBranchPoint.getBranch(), revised, target); + InternalCDORevision target = readResult(in, id, branch); + return new PointerCDORevision((EClass)classifier, id, branch, revised, target); } case DETACHED_RESULT: { EClassifier classifier = in.readCDOClassifierRefAndResolve(); long timeStamp = in.readLong(); + long revised = in.readLong(); int version = in.readInt(); - return new DetachedCDORevision((EClass)classifier, id, requestedBranchPoint.getBranch(), version, timeStamp); + return new DetachedCDORevision((EClass)classifier, id, branch, version, timeStamp, revised); } case NORMAL_RESULT: @@ -262,6 +272,16 @@ public abstract class RevisionInfo } } + protected void doWriteResult(CDODataOutput out, InternalCDORevision revision, int referenceChunk) throws IOException + { + writeResult(out, referenceChunk, revision); + } + + protected InternalCDORevision doReadResult(CDODataInput in) throws IOException + { + return readResult(in, id, requestedBranchPoint.getBranch()); + } + /** * @author Eike Stepper * @since 3.0 diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionByVersionRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionByVersionRequest.java index 1f2cf108ac..8d07aed863 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionByVersionRequest.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/LoadRevisionByVersionRequest.java @@ -17,6 +17,7 @@ import org.eclipse.emf.cdo.common.protocol.CDODataOutput; import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.internal.net4j.bundle.OM; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; import org.eclipse.net4j.util.om.trace.ContextTracer; @@ -71,7 +72,7 @@ public class LoadRevisionByVersionRequest extends CDOClientRequest<InternalCDORe @Override protected InternalCDORevision confirming(CDODataInput in) throws IOException { - return (InternalCDORevision)in.readCDORevision(); + return RevisionInfo.readResult(in, id, branchVersion.getBranch()); } @Override diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBRevisionHandler.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBRevisionHandler.java index cf418358f9..ba805d01c6 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBRevisionHandler.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBRevisionHandler.java @@ -21,8 +21,8 @@ public class DBRevisionHandler implements CDORevisionHandler { if (revision.getVersion() < CDOBranchVersion.FIRST_VERSION - 1) { - revision = new DetachedCDORevision(revision.getEClass(), revision.getID(), revision.getBranch(), -revision - .getVersion(), revision.getTimeStamp()); + revision = new DetachedCDORevision(revision.getEClass(), revision.getID(), revision.getBranch(), + -revision.getVersion(), revision.getTimeStamp(), revision.getRevised()); } delegate.handleRevision(revision); diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java index 8ce9430b3b..93947944cf 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java @@ -206,7 +206,8 @@ public class DBStoreAccessor extends LongIDStoreAccessor implements IDBStoreAcce int version = revision.getVersion(); if (version < CDOBranchVersion.FIRST_VERSION - 1) { - return new DetachedCDORevision(eClass, id, revision.getBranch(), -version, revision.getTimeStamp()); + return new DetachedCDORevision(eClass, id, revision.getBranch(), -version, revision.getTimeStamp(), + revision.getRevised()); } return revision; @@ -238,12 +239,19 @@ public class DBStoreAccessor extends LongIDStoreAccessor implements IDBStoreAcce TRACER.format("Selecting revision {0} from {1}", id, branchVersion); //$NON-NLS-1$ } - // if audit support is present, just use the audit method + // If audit support is present, just use the audit method success = ((IClassMappingAuditSupport)mapping).readRevisionByVersion(this, revision, listChunk); + if (success && revision.getVersion() < CDOBranchVersion.FIRST_VERSION - 1) + { + // It is detached revision + revision = new DetachedCDORevision(eClass, id, revision.getBranch(), -revision.getVersion(), + revision.getTimeStamp(), revision.getRevised()); + + } } else { - // if audit support is not present, we still have to provide a method + // If audit support is not present, we still have to provide a method // to readRevisionByVersion because TransactionCommitContext.computeDirtyObject // needs to lookup the base revision for a change. Hence we emulate this // behavior by getting the current revision and asserting that the version diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java index 1928c8f287..e9edd2407e 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java @@ -15,6 +15,7 @@ package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.revision.CDORevision; @@ -153,8 +154,9 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping builder = new StringBuilder(sqlSelectAttributesPrefix); + builder.append("ABS("); builder.append(CDODBSchema.ATTRIBUTES_VERSION); - builder.append("=?)"); //$NON-NLS-1$ + builder.append(")=?)"); //$NON-NLS-1$ sqlSelectAttributesByVersion = builder.toString(); @@ -293,7 +295,7 @@ public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping boolean success = readValuesFromStatement(pstmt, revision, accessor); // Read multival tables only if revision exists - if (success) + if (success && revision.getVersion() >= CDOBranchVersion.FIRST_VERSION) { readLists(accessor, revision, listChunk); } diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java index ad226ef59f..3f48cf260c 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java @@ -294,7 +294,7 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp boolean success = readValuesFromStatement(pstmt, revision, accessor); // Read multival tables only if revision exists - if (success) + if (success && revision.getVersion() >= CDOBranchVersion.FIRST_VERSION) { readLists(accessor, revision, listChunk); } diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionByVersionIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionByVersionIndication.java index 815aced75d..f4f2d18c70 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionByVersionIndication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/LoadRevisionByVersionIndication.java @@ -15,8 +15,10 @@ import org.eclipse.emf.cdo.common.id.CDOID; 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.CDORevision; 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.net4j.util.om.trace.ContextTracer; @@ -66,8 +68,8 @@ public class LoadRevisionByVersionIndication extends CDOReadIndication @Override protected void responding(CDODataOutput out) throws IOException { - CDORevision revision = getRepository().getRevisionManager().getRevisionByVersion(id, branchVersion, referenceChunk, - true); - out.writeCDORevision(revision, referenceChunk); + InternalCDORevisionManager revisionManager = getRepository().getRevisionManager(); + InternalCDORevision revision = revisionManager.getRevisionByVersion(id, branchVersion, referenceChunk, true); + RevisionInfo.writeResult(out, referenceChunk, revision); } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java index 1f404f2b6b..1280d3b831 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java @@ -75,6 +75,7 @@ import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_306998_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_308895_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_310574_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_314264_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_315043_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_316145_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_316434_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_318844_Test; @@ -220,6 +221,7 @@ public abstract class AllConfigs extends ConfigTestSuite testClasses.add(Bugzilla_310574_Test.class); // testClasses.add(Bugzilla_313326_Test.class); testClasses.add(Bugzilla_314264_Test.class); + testClasses.add(Bugzilla_315043_Test.class); testClasses.add(Bugzilla_316145_Test.class); testClasses.add(Bugzilla_316434_Test.class); testClasses.add(Bugzilla_318844_Test.class); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_315043_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_315043_Test.java new file mode 100644 index 0000000000..e09de007a2 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_315043_Test.java @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2004 - 2010 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: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionManager; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.net4j.CDOSession; +import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision; +import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.config.IRepositoryConfig; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOUtil; + +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import junit.framework.Assert; + +/** + * @author Eike Stepper + */ +public class Bugzilla_315043_Test extends AbstractCDOTest +{ + public void testReloadingRevisions() throws Exception + { + skipUnlessAuditing(); + + final String RESOURCE_NAME = "resource"; + + Set<CDOID> cdoid; + long timeStampOfHoleCommit; + + CDOSession initialSession = (CDOSession)openSession(); + { + // create model history + CDOTransaction openTransaction = initialSession.openTransaction(); + CDOResource resource = openTransaction.getOrCreateResource(RESOURCE_NAME); + + // creating initial commit + Company createdCompany = getModel1Factory().createCompany(); + createdCompany.setName("CompanyTesting"); + createdCompany.setCity("City"); + createdCompany.setStreet("Street"); + + resource.getContents().add(createdCompany); + + openTransaction.commit(); + + // collect id's + cdoid = new HashSet<CDOID>(); + for (TreeIterator<EObject> allContents = resource.getAllContents(); allContents.hasNext();) + { + CDOObject next = CDOUtil.getCDOObject(allContents.next()); + cdoid.add(next.cdoID()); + } + + // making holes - detaching + List<EObject> contents = new ArrayList<EObject>(resource.getContents()); + for (int i = 0; i < contents.size(); i++) + { + EcoreUtil.delete(contents.get(i), true); + } + + timeStampOfHoleCommit = openTransaction.commit().getTimeStamp(); + } + + // check when locally cached elements are availabe + checkRevisionsOnGivenSession(cdoid, timeStampOfHoleCommit, 2, initialSession); + // turn of revision download by timestamp + checkRevisionsOnGivenSession(cdoid, -1, 2, initialSession); + initialSession.close(); + + checkRevisions(cdoid, timeStampOfHoleCommit, 2); + // turn of revision download by timestamp + checkRevisions(cdoid, -1, 2); + + // clear caches + + clearServerRevisionCache(); + checkRevisions(cdoid, timeStampOfHoleCommit, 2); + // turn of revision download by timestamp + clearServerRevisionCache(); + checkRevisions(cdoid, -1, 2); + } + + private void checkRevisions(Set<CDOID> cdoid, long timeStampOfHoleCommit, int version) + { + org.eclipse.emf.cdo.session.CDOSession openSession = openSession(); + checkRevisionsOnGivenSession(cdoid, timeStampOfHoleCommit, version, openSession); + openSession.close(); + } + + private void checkRevisionsOnGivenSession(Set<CDOID> cdoid, long timeStampOfHoleCommit, int version, + org.eclipse.emf.cdo.session.CDOSession openSession) + { + CDORevisionManager revisionManager = openSession.getRevisionManager(); + for (Iterator<CDOID> it = cdoid.iterator(); it.hasNext();) + { + + CDOID next = it.next(); + if (timeStampOfHoleCommit != -1) + { + CDORevision revisionByTimestamp = revisionManager.getRevision(next, openSession.getBranchManager() + .getMainBranch().getPoint(timeStampOfHoleCommit), CDORevision.DEPTH_NONE, 0, true); + + Assert.assertNull(revisionByTimestamp); + } + + CDORevision revisionByVersion = revisionManager.getRevisionByVersion(next, openSession.getBranchManager() + .getMainBranch().getVersion(version), CDORevision.DEPTH_NONE, true); + + assertEquals("Revisions is detached", true, revisionByVersion instanceof DetachedCDORevision); + + } + } + + private void clearServerRevisionCache() + { + InternalRepository repository = getScenario().getRepositoryConfig() + .getRepository(IRepositoryConfig.REPOSITORY_NAME); + clearCache(repository.getRevisionManager()); + } +}
\ No newline at end of file |