diff options
6 files changed, 149 insertions, 36 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java index 4837553cf7..c37266a66a 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java @@ -10,6 +10,7 @@ */ package org.eclipse.emf.cdo.server.db; +import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.server.IStoreAccessor; import java.sql.Connection; @@ -27,4 +28,9 @@ public interface IDBStoreAccessor extends IStoreAccessor * @since 2.0 */ public IPreparedStatementCache getStatementCache(); + + /** + * @since 3.0 + */ + public boolean isNewObject(CDOID id); } diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingBranchingSupport.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingBranchingSupport.java index 80f5b298d0..3c5d15e24d 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingBranchingSupport.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingBranchingSupport.java @@ -14,6 +14,7 @@ package org.eclipse.emf.cdo.server.db.mapping; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.server.db.IDBStoreAccessor; import org.eclipse.net4j.util.om.monitor.OMMonitor; @@ -47,4 +48,20 @@ public interface IClassMappingBranchingSupport extends IClassMappingAuditSupport * the monitor to indicate progress. */ public void detachObject(IDBStoreAccessor dbStoreAccessor, CDOID id, long revised, CDOBranch branch, OMMonitor monitor); + + /** + * Write a special placeholder revision which is used to indicate that a revision is detached in a branch. + * + * @param accessor + * the accessor to use. + * @param revision + * the old revision about to be detached + * @param revised + * the timeStamp when this object became detached. + * @param monitor + * the monitor to indicate progress. + * @since 3.0 + */ + public void detachFirstVersion(IDBStoreAccessor accessor, CDORevision revision, long revised, OMMonitor monitor); + } 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 559ef13fbe..08ee03f185 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 @@ -19,6 +19,7 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.model.CDOClassifierRef; import org.eclipse.emf.cdo.common.model.CDOPackageRegistry; +import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCacheAdder; import org.eclipse.emf.cdo.server.IQueryHandler; import org.eclipse.emf.cdo.server.IRepository; @@ -36,18 +37,16 @@ import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport; import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy; import org.eclipse.emf.cdo.server.internal.db.bundle.OM; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; +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.InternalCDORevisionDelta; import org.eclipse.emf.cdo.spi.server.LongIDStoreAccessor; import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.DBUtil; -import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; import org.eclipse.net4j.util.collection.CloseableIterator; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.eclipse.net4j.util.om.monitor.OMMonitor; -import org.eclipse.net4j.util.om.monitor.ProgressDistributable; -import org.eclipse.net4j.util.om.monitor.ProgressDistributor; import org.eclipse.net4j.util.om.monitor.OMMonitor.Async; import org.eclipse.net4j.util.om.trace.ContextTracer; @@ -62,7 +61,9 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -79,25 +80,7 @@ public class DBStoreAccessor extends LongIDStoreAccessor implements IDBStoreAcce private Timer connectionKeepAliveTimer = null; - @ExcludeFromDump - @SuppressWarnings("unchecked") - private final ProgressDistributable<CommitContext>[] ops = ProgressDistributor.array( // - new ProgressDistributable.Default<CommitContext>() - { - public void runLoop(int index, CommitContext commitContext, OMMonitor monitor) throws Exception - { - DBStoreAccessor.super.write(commitContext, monitor.fork()); - } - }, // - - new ProgressDistributable.Default<CommitContext>() - { - public void runLoop(int index, CommitContext commitContext, OMMonitor monitor) throws Exception - { - // TODO - reenable when reimplementing stmt caching - // flush(monitor.fork()); - } - }); + private Set<CDOID> newObjects = new HashSet<CDOID>(); public DBStoreAccessor(DBStore store, ISession session) throws DBException { @@ -189,6 +172,10 @@ public class DBStoreAccessor extends LongIDStoreAccessor implements IDBStoreAcce IClassMapping mapping = mappingStrategy.getClassMapping(eClass); if (mapping.readRevision(this, revision, listChunk)) { + if (revision.getVersion() == -1) + { + return new DetachedCDORevision(id, branchPoint.getBranch(), 1, branchPoint.getTimeStamp()); + } return revision; } @@ -277,8 +264,14 @@ public class DBStoreAccessor extends LongIDStoreAccessor implements IDBStoreAcce @Override public void write(CommitContext context, OMMonitor monitor) { - ProgressDistributor distributor = getStore().getAccessorWriteDistributor(); - distributor.run(ops, context, monitor); + // remember CDOIDs of new objects + newObjects.clear(); + for (InternalCDORevision revision : context.getNewObjects()) + { + newObjects.add(revision.getID()); + } + + super.write(context, monitor); } @Override @@ -403,11 +396,23 @@ public class DBStoreAccessor extends LongIDStoreAccessor implements IDBStoreAcce TRACER.format("Detaching object: {0} in branch {1}", id, branch); //$NON-NLS-1$ } - EClass eClass = getObjectType(id); + InternalCDORevision oldRevision = (InternalCDORevision)getStore().getRepository().getRevisionManager().getRevision( + id, branch.getPoint(revised), 0, CDORevision.DEPTH_NONE, true); + EClass eClass = oldRevision.getEClass(); + IMappingStrategy mappingStrategy = getStore().getMappingStrategy(); IClassMappingBranchingSupport mapping = (IClassMappingBranchingSupport)mappingStrategy.getClassMapping(eClass); - mapping.detachObject(this, id, revised, branch, monitor); + if (oldRevision.getVersion() == 1) + { + // version 1 in branch gets deleted -> write placebo revision. + mapping.detachFirstVersion(this, oldRevision, revised, monitor); + } + else + { + // default detach behavior + mapping.detachObject(this, id, revised, branch, monitor); + } } public Connection getConnection() @@ -657,4 +662,9 @@ public class DBStoreAccessor extends LongIDStoreAccessor implements IDBStoreAcce } } } + + public boolean isNewObject(CDOID id) + { + return newObjects.contains(id); + } } diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java index fa88fc1312..b6d420f395 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java @@ -92,7 +92,7 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping IDBField idField = table.addField(CDODBSchema.ATTRIBUTES_ID, DBType.BIGINT, true); IDBField versionField = table.addField(CDODBSchema.ATTRIBUTES_VERSION, DBType.INTEGER, true); - addBranchingField(table); + IDBField branchField = addBranchingField(table); table.addField(CDODBSchema.ATTRIBUTES_CLASS, DBType.BIGINT, true); table.addField(CDODBSchema.ATTRIBUTES_CREATED, DBType.BIGINT, true); @@ -101,12 +101,21 @@ public abstract class AbstractHorizontalClassMapping implements IClassMapping table.addField(CDODBSchema.ATTRIBUTES_CONTAINER, DBType.BIGINT, true); table.addField(CDODBSchema.ATTRIBUTES_FEATURE, DBType.INTEGER, true); - table.addIndex(IDBIndex.Type.UNIQUE, idField, versionField); + if (branchField != null) + { + table.addIndex(IDBIndex.Type.UNIQUE, idField, versionField, branchField); + } + else + { + table.addIndex(IDBIndex.Type.UNIQUE, idField, versionField); + } + table.addIndex(IDBIndex.Type.NON_UNIQUE, idField, revisedField); } - protected void addBranchingField(IDBTable table) + protected IDBField addBranchingField(IDBTable table) { + return null; } private void initFeatures() 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 749d0ea042..22d721ca47 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 @@ -34,7 +34,6 @@ import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.DBType; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBTable; -import org.eclipse.net4j.db.ddl.IDBIndex.Type; import org.eclipse.net4j.util.ImplementationError; import org.eclipse.net4j.util.om.monitor.OMMonitor; import org.eclipse.net4j.util.om.monitor.OMMonitor.Async; @@ -77,10 +76,9 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp } @Override - protected void addBranchingField(IDBTable table) + protected IDBField addBranchingField(IDBTable table) { - IDBField branch = table.addField(CDODBSchema.ATTRIBUTES_BRANCH, DBType.INTEGER, true); - table.addIndex(Type.NON_UNIQUE, branch); + return table.addField(CDODBSchema.ATTRIBUTES_BRANCH, DBType.INTEGER, true); } private void initSqlStrings() @@ -485,6 +483,69 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp } } + public void detachFirstVersion(IDBStoreAccessor accessor, CDORevision rev, long revised, OMMonitor monitor) + { + PreparedStatement stmt = null; + + InternalCDORevision revision = (InternalCDORevision)rev; + + try + { + stmt = accessor.getStatementCache().getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH); + + int col = 1; + + stmt.setLong(col++, CDOIDUtil.getLong(revision.getID())); + stmt.setInt(col++, -1); // cdo_version + stmt.setInt(col++, revision.getBranch().getID()); + stmt.setLong(col++, accessor.getStore().getMetaDataManager().getMetaID(revision.getEClass())); + stmt.setLong(col++, revised); // cdo_created + stmt.setLong(col++, 0); // cdo_revised + stmt.setLong(col++, CDODBUtil.convertCDOIDToLong(getExternalReferenceManager(), accessor, revision + .getResourceID())); + stmt.setLong(col++, CDODBUtil.convertCDOIDToLong(getExternalReferenceManager(), accessor, (CDOID)revision + .getContainerID())); + stmt.setInt(col++, revision.getContainingFeatureID()); + + // XXX Eike: what to do with attributes? + // the following is currently a copy of writeValues ... + + int isSetCol = col + getValueMappings().size(); + + for (ITypeMapping mapping : getValueMappings()) + { + EStructuralFeature feature = mapping.getFeature(); + if (feature.isUnsettable()) + { + if (revision.getValue(feature) == null) + { + stmt.setBoolean(isSetCol++, false); + + // also set value column to default value + mapping.setDefaultValue(stmt, col++); + + continue; + } + else + { + stmt.setBoolean(isSetCol++, true); + } + } + mapping.setValueFromRevision(stmt, col++, revision); + } + + CDODBUtil.sqlUpdate(stmt, true); + } + catch (SQLException e) + { + throw new DBException(e); + } + finally + { + accessor.getStatementCache().releasePreparedStatement(stmt); + } + } + protected void reviseObject(IDBStoreAccessor accessor, CDOID id, int branchId, long revised) { PreparedStatement stmt = null; @@ -525,13 +586,15 @@ public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapp async = monitor.forkAsync(); CDOID id = revision.getID(); - if (revision.getVersion() == CDORevision.FIRST_VERSION) + + if (accessor.isNewObject(id)) { - // XXX Assumption no longer valid with branches! + // put new objects into objectTypeCache ((HorizontalBranchingMappingStrategy)getMappingStrategy()).putObjectType(accessor, id, getEClass()); } - else + else if (revision.getVersion() > 1) { + // if revision is not the first one, revise the old revision long revised = revision.getTimeStamp() - 1; reviseObject(accessor, id, revision.getBranch().getID(), revised); for (IListMapping mapping : getListMappings()) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java index 01b6568737..6f7350246c 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java @@ -67,14 +67,22 @@ public interface InternalCDOView extends CDOView, CDOIDProvider, ILifecycle /** * Returns the conflicting objects. + * + * @since 3.0 */ public Set<CDOObject> handleInvalidation(long timeStamp, Set<CDOIDAndVersion> dirtyOIDs, Collection<CDOID> detachedOIDs, boolean async); + /** + * @since 3.0 + */ public Set<CDOObject> handleInvalidationWithoutNotification(Set<CDOIDAndVersion> dirtyOIDs, Collection<CDOID> detachedOIDs, Set<InternalCDOObject> dirtyObjects, Set<InternalCDOObject> detachedObjects, boolean async); + /** + * @since 3.0 + */ public void handleChangeSubscription(Collection<CDORevisionDelta> deltas, Collection<CDOID> detachedObjects, boolean async); |