From b90d0af5da43dfd67bd50393c4064a1313459c83 Mon Sep 17 00:00:00 2001 From: Martin Taal Date: Sat, 24 Nov 2012 14:36:11 +0100 Subject: Combine hibernate and CDO versioning, use optimistic locking in hibernate --- .../server/hibernate/teneo/CDOEntityMapper.java | 2 +- .../mappings/resource.hbm.xml | 4 +- .../server/internal/hibernate/CDOAuditHandler.java | 21 ++ .../internal/hibernate/HibernateAuditHandler.java | 75 +++-- .../internal/hibernate/HibernateStoreAccessor.java | 69 +++- .../hibernate/tuplizer/CDORevisionTuplizer.java | 11 + .../emf/cdo/tests/hibernate/AllTestsHibernate.java | 20 +- .../cdo/tests/hibernate/CDOObjectHistoryTest.java | 351 +++++++++++++++++++++ 8 files changed, 517 insertions(+), 36 deletions(-) create mode 100644 plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/CDOObjectHistoryTest.java diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java b/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java index a44be5b6ba..0b86786304 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate.teneo/src/org/eclipse/emf/cdo/server/hibernate/teneo/CDOEntityMapper.java @@ -74,7 +74,7 @@ public class CDOEntityMapper extends EntityMapper final Element columnElement = containerElement.addElement("column").addAttribute("name", //$NON-NLS-1$ //$NON-NLS-2$ CDOHibernateConstants.CONTAINER_PROPERTY_COLUMN); - final Element versionElement = entityElement.addElement("property"); //$NON-NLS-1$ + final Element versionElement = entityElement.addElement("version"); //$NON-NLS-1$ // add cdo_teneo prefix to prop name prevent name clashes with // efeatures which are accidentally called version // https://bugs.eclipse.org/bugs/show_bug.cgi?id=378050 diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml b/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml index 87748e0c18..d92d57c1ed 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/mappings/resource.hbm.xml @@ -24,9 +24,9 @@ - + true - + diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/CDOAuditHandler.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/CDOAuditHandler.java index c61c639de6..7a74641c6b 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/CDOAuditHandler.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/CDOAuditHandler.java @@ -12,6 +12,7 @@ package org.eclipse.emf.cdo.server.internal.hibernate; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.model.CDOClassifierRef; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionData; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; @@ -67,6 +68,26 @@ public class CDOAuditHandler extends AuditHandler return auditEClass != null; } + public boolean isAudited(CDOID id) + { + if (!getDataStore().isAuditing()) + { + return false; + } + if (!(id instanceof CDOClassifierRef.Provider)) + { + return false; + } + CDOClassifierRef cdoClassifierRef = ((CDOClassifierRef.Provider)id).getClassifierRef(); + final EClass eClass = HibernateUtil.getInstance().getEClass(cdoClassifierRef); + if (eClass == null) + { + return false; + } + final EClass auditEClass = getAuditingModelElement(eClass); + return auditEClass != null; + } + @Override public EClass getEClass(Object o) { diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateAuditHandler.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateAuditHandler.java index ea29dedb5f..93439fa1d1 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateAuditHandler.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateAuditHandler.java @@ -11,6 +11,7 @@ */ package org.eclipse.emf.cdo.server.internal.hibernate; +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.model.CDOClassifierRef; @@ -18,6 +19,7 @@ import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; import org.eclipse.emf.cdo.eresource.EresourcePackage; import org.eclipse.emf.cdo.spi.common.id.AbstractCDOIDLong; +import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.common.util.Enumerator; @@ -34,7 +36,6 @@ import org.eclipse.emf.teneo.hibernate.auditing.model.teneoauditing.TeneoAuditKi import org.hibernate.Query; import org.hibernate.Session; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -50,9 +51,23 @@ public class HibernateAuditHandler private HbDataStore cdoDataStore; - public AuditHandler getAuditHandler() + public CDOAuditHandler getCDOAuditHandler() { - return cdoDataStore.getAuditHandler(); + return (CDOAuditHandler)cdoDataStore.getAuditHandler(); + } + + public InternalCDORevision readRevisionByVersion(Session session, CDOID id, int version) + { + final CDOClassifierRef classifierRef = CDOIDUtil.getClassifierRef(id); + if (classifierRef == null) + { + throw new IllegalArgumentException("This CDOID type of " + id + " is not supported by this store."); //$NON-NLS-1$ //$NON-NLS-2$ + } + final EClass eClass = HibernateUtil.getInstance().getEClass(classifierRef); + AuditVersionProvider auditVersionProvider = cdoDataStore.getAuditVersionProvider(); + auditVersionProvider.setSession(session); + final TeneoAuditEntry auditEntry = auditVersionProvider.getAuditEntryForVersion(eClass, id, version); + return (InternalCDORevision)getCDORevision(session, auditEntry); } public InternalCDORevision readRevision(Session session, CDOID id, long timeStamp) @@ -72,10 +87,6 @@ public class HibernateAuditHandler AuditVersionProvider auditVersionProvider = cdoDataStore.getAuditVersionProvider(); auditVersionProvider.setSession(session); final TeneoAuditEntry auditEntry = auditVersionProvider.getAuditEntry(eClass, id, timeStamp); - if (auditEntry.getTeneo_audit_kind() == TeneoAuditKind.DELETE) - { - return null; - } return getCDORevision(session, auditEntry); } @@ -87,17 +98,37 @@ public class HibernateAuditHandler protected CDORevision convertAuditEntryToCDORevision(TeneoAuditEntry teneoAuditEntry) { + if (teneoAuditEntry == null) + { + return null; + } final HibernateStoreAccessor storeAccessor = HibernateThreadContext.getCurrentStoreAccessor(); - final EClass domainEClass = getAuditHandler().getModelElement(teneoAuditEntry.eClass()); + final EClass domainEClass = getCDOAuditHandler().getModelElement(teneoAuditEntry.eClass()); final CDOID cdoID = HibernateUtil.getInstance().convertStringToCDOID(teneoAuditEntry.getTeneo_object_id()); - final InternalCDORevision revision = hibernateStore.createRevision(domainEClass, cdoID); - revision.setBranchPoint(storeAccessor.getStore().getMainBranchHead().getBranch() - .getPoint(teneoAuditEntry.getTeneo_start())); - if (teneoAuditEntry.getTeneo_end() > 0) + final InternalCDORevision revision; + if (teneoAuditEntry.getTeneo_audit_kind() == TeneoAuditKind.DELETE) { - revision.setRevised(teneoAuditEntry.getTeneo_end()); + revision = new DetachedCDORevision(domainEClass, cdoID, hibernateStore.getRepository().getBranchManager() + .getMainBranch(), new Long(teneoAuditEntry.getTeneo_object_version()).intValue(), + teneoAuditEntry.getTeneo_start(), CDOBranchPoint.UNSPECIFIED_DATE); + revision.setRevised(CDOBranchPoint.UNSPECIFIED_DATE); + } + else + { + revision = hibernateStore.createRevision(domainEClass, cdoID); + revision.setVersion(new Long(teneoAuditEntry.getTeneo_object_version()).intValue()); + revision.setBranchPoint(storeAccessor.getStore().getMainBranchHead().getBranch() + .getPoint(teneoAuditEntry.getTeneo_start())); + if (teneoAuditEntry.getTeneo_end() > 0) + { + revision.setRevised(teneoAuditEntry.getTeneo_end()); + } + else + { + revision.setRevised(CDOBranchPoint.UNSPECIFIED_DATE); + } + convertContent(teneoAuditEntry, revision); } - convertContent(teneoAuditEntry, revision); return revision; } @@ -161,7 +192,7 @@ public class HibernateAuditHandler public List getCDOResources(Session session, CDOID folderId, long timeStamp) { - final AuditHandler auditHandler = getAuditHandler(); + final AuditHandler auditHandler = getCDOAuditHandler(); final EClass auditEClass = auditHandler.getAuditingModelElement(EresourcePackage.eINSTANCE.getCDOResourceNode()); final String entityName = cdoDataStore.toEntityName(auditEClass); return getCDOResources(session, folderId, timeStamp, entityName); @@ -169,7 +200,7 @@ public class HibernateAuditHandler public List getCDOResources(Session session, CDOID folderId, long timeStamp, String entityName) { - final AuditHandler auditHandler = getAuditHandler(); + final AuditHandler auditHandler = getCDOAuditHandler(); String idStr = null; if (folderId != null) { @@ -190,19 +221,19 @@ public class HibernateAuditHandler return qry.list(); } - public List handleRevisionsByEClass(Session session, EClass eClass, CDORevisionHandler handler, - long timeStamp) + public void handleRevisionsByEClass(Session session, EClass eClass, CDORevisionHandler handler, long timeStamp) { AuditVersionProvider auditVersionProvider = cdoDataStore.getAuditVersionProvider(); auditVersionProvider.setSession(session); - final List teneoAuditEntries = auditVersionProvider.getAllAuditEntries(eClass, timeStamp); - final List revisions = new ArrayList(); + final List teneoAuditEntries = auditVersionProvider.getSpecificAuditEntries(eClass, timeStamp); for (TeneoAuditEntry teneoAuditEntry : teneoAuditEntries) { final CDORevision cdoRevision = getCDORevision(session, teneoAuditEntry); - handler.handleRevision(cdoRevision); + if (!handler.handleRevision(cdoRevision)) + { + return; + } } - return revisions; } public HbDataStore getCdoDataStore() diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java index 3210809625..b84818c373 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateStoreAccessor.java @@ -367,14 +367,15 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS return null; } - if (getStore().isAuditing() && branchPoint.getTimeStamp() != 0) + if (getStore().getHibernateAuditHandler().getCDOAuditHandler().isAudited(id) && getStore().isAuditing() + && branchPoint.getTimeStamp() != 0) { InternalCDORevision revision = getStore().getHibernateAuditHandler().readRevision(getHibernateSession(), id, branchPoint.getTimeStamp()); // found one, use it - if (revision != null) + if (revision != null && !(revision instanceof DetachedCDORevision)) { - revision.setBranchPoint(getStore().getMainBranchHead()); + revision.setBranchPoint(branchPoint); return revision; } } @@ -529,7 +530,10 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS final Query query = session.createQuery("select e from " + getStore().getEntityName(eClass) + " e"); for (Object o : query.list()) { - handler.handleRevision((CDORevision)o); + if (!handler.handleRevision((CDORevision)o)) + { + return; + } } } finally @@ -539,15 +543,28 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS } /** - * Not supported by the Hibernate Store, auditing is not supported. Currently ignores the branchVersion and calls the - * {@readRevision(CDOID, CDOBranchPoint, int, CDORevisionCacheAdder)} . + * @see #readRevision(CDOID, CDOBranchPoint, int, CDORevisionCacheAdder) */ public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk, CDORevisionCacheAdder cache) { - InternalCDORevision revision = readRevision(id, branchVersion.getBranch().getPoint(System.currentTimeMillis()), - listChunk, cache); - if (revision != null) + InternalCDORevision revision = null; + if (getStore().getHibernateAuditHandler().getCDOAuditHandler().isAudited(id)) + { + revision = getStore().getHibernateAuditHandler().readRevisionByVersion(getHibernateSession(), id, + branchVersion.getVersion()); + } + else + { + revision = readRevision(id, branchVersion.getBranch().getPoint(System.currentTimeMillis()), listChunk, cache); + if (revision != null) + { + // otherwise CDO gets confused and we get wrong version numbers later + revision.setVersion(branchVersion.getVersion()); + } + } + + if (revision != null && !(revision instanceof DetachedCDORevision)) { revision.freeze(); } @@ -760,6 +777,9 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS final Session session = getNewHibernateSession(false); session.setDefaultReadOnly(false); + // decrement version, hibernate will increment it + decrementVersions(context); + // order is 1) insert, 2) update and then delete // this order is the most stable! Do not change it without testing @@ -790,12 +810,18 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS { final String entityName = HibernateUtil.getInstance().getEntityName(revision.getID()); session.merge(entityName, revision); + if (TRACER.isEnabled()) { TRACER.trace("Updated Object " + revision.getEClass().getName() + " id: " + revision.getID()); //$NON-NLS-1$ //$NON-NLS-2$ } } + // and increment the versions again so that the objects are cached correctly + // note that this is needed because above a merge is done and not a + // saveupdate, so hibernate does not update the version back in the revision + incrementVersions(context); + session.flush(); // delete all objects @@ -869,6 +895,31 @@ public class HibernateStoreAccessor extends StoreAccessor implements IHibernateS monitor.done(); } + // set the version one back, hibernate will update it + private void decrementVersions(CommitContext context) + { + for (InternalCDORevision revision : context.getNewObjects()) + { + revision.setVersion(revision.getVersion() - 1); + } + for (InternalCDORevision revision : context.getDirtyObjects()) + { + revision.setVersion(revision.getVersion() - 1); + } + } + + private void incrementVersions(CommitContext context) + { + for (InternalCDORevision revision : context.getNewObjects()) + { + revision.setVersion(1); + } + for (InternalCDORevision revision : context.getDirtyObjects()) + { + revision.setVersion(revision.getVersion() + 1); + } + } + private void repairContainerIDs(List repairContainerIDs, Session session) { for (InternalCDORevision revision : repairContainerIDs) diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java index 0299f00555..b291702eaf 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/tuplizer/CDORevisionTuplizer.java @@ -12,6 +12,7 @@ package org.eclipse.emf.cdo.server.internal.hibernate.tuplizer; import org.eclipse.emf.cdo.common.model.EMFUtil; +import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.eresource.EresourcePackage; import org.eclipse.emf.cdo.server.internal.hibernate.CDOHibernateConstants; import org.eclipse.emf.cdo.server.internal.hibernate.HibernateStore; @@ -378,4 +379,14 @@ public class CDORevisionTuplizer extends AbstractEntityTuplizer { return null; } + + @Override + public Object getVersion(Object entity) throws HibernateException + { + if (entity instanceof CDORevision) + { + return ((CDORevision)entity).getVersion(); + } + return super.getVersion(entity); + } } diff --git a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AllTestsHibernate.java b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AllTestsHibernate.java index 27e7683562..8f7d4f46c2 100644 --- a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AllTestsHibernate.java +++ b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/AllTestsHibernate.java @@ -36,6 +36,7 @@ import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_279982_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_303466_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_306998_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_322804_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_329254_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_334995_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_347964_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_351393_Test; @@ -75,8 +76,8 @@ public class AllTestsHibernate extends AllConfigs @Override protected void initTestClasses(List> testClasses, IScenario scenario) { - testClasses.clear(); - // testClasses.add(Bugzilla_306998_Test.class); + // testClasses.clear(); + // testClasses.add(RevisionDeltaTest.class); // if (true) // { // return; @@ -109,6 +110,8 @@ public class AllTestsHibernate extends AllConfigs if (scenario.getCapabilities().contains(IRepositoryConfig.CAPABILITY_AUDITING)) { + testClasses.add(CDOObjectHistoryTest.class); + // the security model inherits from the ecore model // not so well supported for now testClasses.remove(SecurityManagerTest.class); @@ -122,6 +125,8 @@ public class AllTestsHibernate extends AllConfigs } else { + testClasses.remove(Bugzilla_329254_Test.class); + testClasses.remove(Hibernate_Bugzilla_329254_Test.class); testClasses.remove(CommitInfoTest.class); } @@ -306,4 +311,15 @@ public class AllTestsHibernate extends AllConfigs } } + + public static class Hibernate_Bugzilla_329254_Test extends Bugzilla_329254_Test + { + + // does not work for non audited cases + @Override + public void testCommitTimeStampUpdateOnError() throws Exception + { + } + + } } diff --git a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/CDOObjectHistoryTest.java b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/CDOObjectHistoryTest.java new file mode 100644 index 0000000000..0071f8fc8d --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/CDOObjectHistoryTest.java @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2004 - 2012 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.hibernate; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.CDOObjectHistory; +import org.eclipse.emf.cdo.common.commit.CDOCommitHistory; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; +import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.eresource.EresourcePackage; +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.Requires; +import org.eclipse.emf.cdo.tests.legacy.model1.Model1Package; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.view.CDOView; + +import org.eclipse.net4j.util.concurrent.ConcurrencyUtil; +import org.eclipse.net4j.util.lifecycle.LifecycleUtil; + +import java.util.List; + +/** + * @author Martin Taal + * @author Eike Stepper + */ +@Requires(IRepositoryConfig.CAPABILITY_AUDITING) +public class CDOObjectHistoryTest extends AbstractCDOTest +{ + protected CDOSession session1; + + private boolean finishedLoadingHistory = false; + + @Override + protected void doTearDown() throws Exception + { + LifecycleUtil.deactivate(session1); + session1 = null; + super.doTearDown(); + } + + protected CDOSession openSession1() + { + session1 = openSession(); + return session1; + } + + protected void closeSession1() + { + session1.close(); + } + + protected CDOSession openSession2() + { + return openSession(); + } + + public void testChangedAudit() throws Exception + { + CDOSession session = openSession1(); + CDOTransaction transaction = session.openTransaction(); + CDOResource resource = transaction.createResource(getResourcePath("/res1")); + + Company company = getModel1Factory().createCompany(); + company.setName("ESC"); + resource.getContents().add(company); + long commitTime1 = transaction.commit().getTimeStamp(); + assertEquals(true, session.getRepositoryInfo().getCreationTime() < commitTime1); + assertEquals("ESC", company.getName()); + + company.setName("Sympedia"); + long commitTime2 = transaction.commit().getTimeStamp(); + assertEquals(true, commitTime1 < commitTime2); + assertEquals(true, session.getRepositoryInfo().getCreationTime() < commitTime2); + assertEquals("Sympedia", company.getName()); + + company.setName("Eclipse"); + long commitTime3 = transaction.commit().getTimeStamp(); + assertEquals(true, commitTime2 < commitTime3); + assertEquals(true, session.getRepositoryInfo().getCreationTime() < commitTime2); + assertEquals("Eclipse", company.getName()); + + resource.getContents().remove(company); + long commitTime4 = transaction.commit().getTimeStamp(); + + closeSession1(); + session = openSession2(); + + CDOView audit = session.openView(commitTime1); + { + CDOResource auditResource = audit.getResource(getResourcePath("/res1")); + Company auditCompany = (Company)auditResource.getContents().get(0); + assertEquals("ESC", auditCompany.getName()); + + final CDOObjectHistory cdoObjectHistory = getCDOObjectHistory(audit, auditCompany); + assertEquals(1, cdoObjectHistory.getElements().length); + for (CDOCommitInfo cdoCommitInfo : cdoObjectHistory.getElements()) + { + if (cdoCommitInfo.getTimeStamp() == commitTime1) + { + checkCommitInfo1(cdoCommitInfo); + } + else + { + fail(); + } + } + audit.close(); + } + + audit = session.openView(commitTime2); + { + CDOResource auditResource = audit.getResource(getResourcePath("/res1")); + Company auditCompany = (Company)auditResource.getContents().get(0); + assertEquals("Sympedia", auditCompany.getName()); + + final CDOObjectHistory cdoObjectHistory = getCDOObjectHistory(audit, auditCompany); + assertEquals(2, cdoObjectHistory.getElements().length); + for (CDOCommitInfo cdoCommitInfo : cdoObjectHistory.getElements()) + { + if (cdoCommitInfo.getTimeStamp() == commitTime1) + { + checkCommitInfo1(cdoCommitInfo); + } + else if (cdoCommitInfo.getTimeStamp() == commitTime2) + { + checkCommitInfo2(cdoCommitInfo); + } + else + { + fail(); + } + } + audit.close(); + } + + audit = session.openView(commitTime3); + { + CDOResource auditResource = audit.getResource(getResourcePath("/res1")); + Company auditCompany = (Company)auditResource.getContents().get(0); + assertEquals("Eclipse", auditCompany.getName()); + + final CDOObjectHistory cdoObjectHistory = getCDOObjectHistory(audit, auditCompany); + assertEquals(3, cdoObjectHistory.getElements().length); + for (CDOCommitInfo cdoCommitInfo : cdoObjectHistory.getElements()) + { + if (cdoCommitInfo.getTimeStamp() == commitTime1) + { + checkCommitInfo1(cdoCommitInfo); + } + else if (cdoCommitInfo.getTimeStamp() == commitTime2) + { + checkCommitInfo2(cdoCommitInfo); + } + else if (cdoCommitInfo.getTimeStamp() == commitTime3) + { + checkCommitInfo3(cdoCommitInfo); + } + else + { + fail(); + } + } + audit.close(); + } + + audit = session.openView(commitTime4); + { + final CDOCommitHistory cdoCommitHistory = getCDOCommitHistory(audit); + assertEquals(5, cdoCommitHistory.getElements().length); + for (CDOCommitInfo cdoCommitInfo : cdoCommitHistory.getElements()) + { + if (cdoCommitInfo.getTimeStamp() == commitTime1) + { + checkCommitInfo1(cdoCommitInfo); + } + else if (cdoCommitInfo.getTimeStamp() == commitTime2) + { + checkCommitInfo2(cdoCommitInfo); + } + else if (cdoCommitInfo.getTimeStamp() == commitTime3) + { + checkCommitInfo3(cdoCommitInfo); + } + else if (cdoCommitInfo.getTimeStamp() == commitTime4) + { + checkCommitInfo4(cdoCommitInfo); + } + else if (cdoCommitInfo.getComment() != null && cdoCommitInfo.getComment().equals("")) + { + // as expected + } + else + { + fail(); + } + } + audit.close(); + } + + session.close(); + } + + private void checkCommitInfo1(CDOCommitInfo cdoCommitInfo) + { + final List newObjects = cdoCommitInfo.getNewObjects(); + final List changedObjects = cdoCommitInfo.getChangedObjects(); + final List detachedObjects = cdoCommitInfo.getDetachedObjects(); + assertEquals(0, detachedObjects.size()); + assertEquals(3, newObjects.size()); + assertEquals(1, changedObjects.size()); + for (Object o : changedObjects) + { + final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o; + final CDOFeatureDelta cdoFeatureDelta = cdoRevisionDelta.getFeatureDelta(EresourcePackage.eINSTANCE + .getCDOResource_Contents()); + assertNotNull(cdoFeatureDelta); + assertEquals(CDOFeatureDelta.Type.LIST, cdoFeatureDelta.getType()); + } + int resourceCnt = 0; + int resourceFolderCnt = 0; + int companyCnt = 0; + for (Object o : newObjects) + { + final CDORevision cdoRevision = (CDORevision)o; + if (cdoRevision.getEClass().getName().equals(Model1Package.eINSTANCE.getCompany().getName())) + { + companyCnt++; + } + if (cdoRevision.getEClass() == EresourcePackage.eINSTANCE.getCDOResource()) + { + resourceCnt++; + } + if (cdoRevision.getEClass() == EresourcePackage.eINSTANCE.getCDOResourceFolder()) + { + resourceFolderCnt++; + } + } + assertEquals(1, companyCnt); + assertEquals(1, resourceCnt); + assertEquals(1, resourceFolderCnt); + } + + private void checkCommitInfo2(CDOCommitInfo cdoCommitInfo) + { + final List newObjects = cdoCommitInfo.getNewObjects(); + final List changedObjects = cdoCommitInfo.getChangedObjects(); + final List detachedObjects = cdoCommitInfo.getDetachedObjects(); + assertEquals(0, detachedObjects.size()); + assertEquals(0, newObjects.size()); + assertEquals(1, changedObjects.size()); + for (Object o : changedObjects) + { + final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o; + final CDOSetFeatureDelta cdoFeatureDelta = (CDOSetFeatureDelta)cdoRevisionDelta.getFeatureDelta(cdoRevisionDelta + .getEClass().getEStructuralFeature("name")); + assertNotNull(cdoFeatureDelta); + assertEquals("Sympedia", cdoFeatureDelta.getValue()); + } + } + + private void checkCommitInfo3(CDOCommitInfo cdoCommitInfo) + { + final List newObjects = cdoCommitInfo.getNewObjects(); + final List changedObjects = cdoCommitInfo.getChangedObjects(); + final List detachedObjects = cdoCommitInfo.getDetachedObjects(); + assertEquals(0, detachedObjects.size()); + assertEquals(0, newObjects.size()); + assertEquals(1, changedObjects.size()); + for (Object o : changedObjects) + { + final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o; + final CDOSetFeatureDelta cdoFeatureDelta = (CDOSetFeatureDelta)cdoRevisionDelta.getFeatureDelta(cdoRevisionDelta + .getEClass().getEStructuralFeature("name")); + assertNotNull(cdoFeatureDelta); + assertEquals("Eclipse", cdoFeatureDelta.getValue()); + } + } + + private void checkCommitInfo4(CDOCommitInfo cdoCommitInfo) + { + final List newObjects = cdoCommitInfo.getNewObjects(); + final List changedObjects = cdoCommitInfo.getChangedObjects(); + final List detachedObjects = cdoCommitInfo.getDetachedObjects(); + assertEquals(1, detachedObjects.size()); + assertEquals(0, newObjects.size()); + assertEquals(1, changedObjects.size()); + for (Object o : changedObjects) + { + final CDORevisionDelta cdoRevisionDelta = (CDORevisionDelta)o; + final CDOFeatureDelta cdoFeatureDelta = cdoRevisionDelta.getFeatureDelta(EresourcePackage.eINSTANCE + .getCDOResource_Contents()); + assertNotNull(cdoFeatureDelta); + assertEquals(CDOFeatureDelta.Type.LIST, cdoFeatureDelta.getType()); + } + } + + private synchronized CDOObjectHistory getCDOObjectHistory(CDOView audit, Object object) + { + CDOObjectHistory cdoObjectHistory = audit.getHistory((CDOObject)object); + + cdoObjectHistory.triggerLoad(); + long startTime = System.currentTimeMillis(); + while (cdoObjectHistory.isLoading()) + { + ConcurrencyUtil.sleep(10); + + // waited too long + if (System.currentTimeMillis() - startTime > 5000) + { + throw new IllegalStateException("commit info could not be loaded"); + } + } + return cdoObjectHistory; + } + + private synchronized CDOCommitHistory getCDOCommitHistory(CDOView audit) + { + CDOCommitHistory cdoCommitHistory = audit.getHistory(); + + cdoCommitHistory.triggerLoad(); + long startTime = System.currentTimeMillis(); + while (cdoCommitHistory.isLoading()) + { + ConcurrencyUtil.sleep(10); + + // waited too long + if (System.currentTimeMillis() - startTime > 5000) + { + throw new IllegalStateException("commit info could not be loaded"); + } + } + return cdoCommitHistory; + } +} -- cgit v1.2.3