diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java')
-rw-r--r-- | plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java | 1016 |
1 files changed, 508 insertions, 508 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java index f934bbd9ac..fbb00881bd 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java @@ -1,508 +1,508 @@ -/*
- * 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
- * Simon McDuff - bug 201266
- * Simon McDuff - bug 213402
- */
-package org.eclipse.emf.cdo.spi.server;
-
-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.commit.CDOCommitData;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDTemp;
-import org.eclipse.emf.cdo.common.id.CDOIDUtil;
-import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
-import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
-import org.eclipse.emf.cdo.common.revision.CDOList;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
-import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
-import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
-import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
-import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
-import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
-import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
-import org.eclipse.emf.cdo.internal.server.bundle.OM;
-import org.eclipse.emf.cdo.server.ISession;
-import org.eclipse.emf.cdo.server.IStoreAccessor;
-import org.eclipse.emf.cdo.server.ITransaction;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
-import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
-import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl;
-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.common.revision.InternalCDORevisionManager;
-
-import org.eclipse.net4j.util.lifecycle.Lifecycle;
-import org.eclipse.net4j.util.om.monitor.OMMonitor;
-import org.eclipse.net4j.util.om.trace.ContextTracer;
-
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @author Eike Stepper
- * @since 4.0
- */
-public abstract class StoreAccessorBase extends Lifecycle implements IStoreAccessor
-{
- private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, StoreAccessorBase.class);
-
- private Store store;
-
- private Object context;
-
- private boolean reader;
-
- private List<CommitContext> commitContexts = new ArrayList<CommitContext>();
-
- private StoreAccessorBase(Store store, Object context, boolean reader)
- {
- this.store = store;
- this.context = context;
- this.reader = reader;
- }
-
- protected StoreAccessorBase(Store store, ISession session)
- {
- this(store, session, true);
- }
-
- protected StoreAccessorBase(Store store, ITransaction transaction)
- {
- this(store, transaction, false);
- }
-
- void setContext(Object context)
- {
- this.context = context;
- }
-
- public Store getStore()
- {
- return store;
- }
-
- public boolean isReader()
- {
- return reader;
- }
-
- /**
- * @since 3.0
- */
- public InternalSession getSession()
- {
- if (context instanceof ITransaction)
- {
- return (InternalSession)((ITransaction)context).getSession();
- }
-
- return (InternalSession)context;
- }
-
- public ITransaction getTransaction()
- {
- if (context instanceof ITransaction)
- {
- return (ITransaction)context;
- }
-
- return null;
- }
-
- public void release()
- {
- store.releaseAccessor(this);
- commitContexts.clear();
- }
-
- /**
- * @since 3.0
- */
- public final void write(InternalCommitContext context, OMMonitor monitor)
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Writing transaction: {0}", getTransaction()); //$NON-NLS-1$
- }
-
- commitContexts.add(context);
- doWrite(context, monitor);
- }
-
- protected abstract void doWrite(InternalCommitContext context, OMMonitor monitor);
-
- /**
- * @since 3.0
- */
- public final void commit(OMMonitor monitor)
- {
- doCommit(monitor);
-
- long latest = CDORevision.UNSPECIFIED_DATE;
- long latestNonLocal = CDORevision.UNSPECIFIED_DATE;
- for (CommitContext commitContext : commitContexts)
- {
- CDOBranchPoint branchPoint = commitContext.getBranchPoint();
- long timeStamp = branchPoint.getTimeStamp();
- if (timeStamp > latest)
- {
- latest = timeStamp;
- }
-
- CDOBranch branch = branchPoint.getBranch();
- if (!branch.isLocal())
- {
- if (timeStamp > latestNonLocal)
- {
- latestNonLocal = timeStamp;
- }
- }
- }
-
- getStore().setLastCommitTime(latest);
- getStore().setLastNonLocalCommitTime(latestNonLocal);
- }
-
- /**
- * @since 3.0
- */
- protected abstract void doCommit(OMMonitor monitor);
-
- public final void rollback()
- {
- if (TRACER.isEnabled())
- {
- TRACER.format("Rolling back transaction: {0}", getTransaction()); //$NON-NLS-1$
- }
-
- for (CommitContext commitContext : commitContexts)
- {
- doRollback(commitContext);
- }
- }
-
- protected abstract void doRollback(CommitContext commitContext);
-
- /**
- * @since 3.0
- */
- public CDOID readResourceID(CDOID folderID, String name, CDOBranchPoint branchPoint)
- {
- QueryResourcesContext.ExactMatch context = Store.createExactMatchContext(folderID, name, branchPoint);
- queryResources(context);
- return context.getResourceID();
- }
-
- /**
- * @since 3.0
- */
- public CDOCommitData loadCommitData(long timeStamp)
- {
- CommitDataRevisionHandler handler = new CommitDataRevisionHandler(this, timeStamp);
- return handler.getCommitData();
- }
-
- /**
- * Add ID mappings for all new objects of a transaction to the commit context. The implementor must, for each new
- * object of the commit context, determine a permanent CDOID and make it known to the context by calling
- * {@link InternalCommitContext#addIDMapping(CDOID, CDOID)}.
- *
- * @since 3.0
- */
- public void addIDMappings(InternalCommitContext commitContext, OMMonitor monitor)
- {
- try
- {
- CDORevision[] newObjects = commitContext.getNewObjects();
- monitor.begin(newObjects.length);
- for (CDORevision revision : newObjects)
- {
- CDOID id = revision.getID();
- if (id instanceof CDOIDTemp)
- {
- CDOIDTemp oldID = (CDOIDTemp)id;
- CDOID newID = getNextCDOID(revision);
- if (CDOIDUtil.isNull(newID) || newID.isTemporary())
- {
- throw new IllegalStateException("newID=" + newID); //$NON-NLS-1$
- }
-
- commitContext.addIDMapping(oldID, newID);
- }
-
- monitor.worked();
- }
- }
- finally
- {
- monitor.done();
- }
- }
-
- protected abstract CDOID getNextCDOID(CDORevision revision);
-
- protected void doPassivate() throws Exception
- {
- }
-
- protected void doUnpassivate() throws Exception
- {
- }
-
- /**
- * @author Eike Stepper
- * @since 3.0
- */
- public static class CommitDataRevisionHandler implements CDORevisionHandler
- {
- private IStoreAccessor storeAccessor;
-
- private long timeStamp;
-
- private InternalCDORevisionManager revisionManager;
-
- private List<CDOPackageUnit> newPackageUnits = new ArrayList<CDOPackageUnit>();
-
- private List<CDOIDAndVersion> newObjects = new ArrayList<CDOIDAndVersion>();
-
- private List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>();
-
- private DetachCounter detachCounter = new DetachCounter();
-
- public CommitDataRevisionHandler(IStoreAccessor storeAccessor, long timeStamp)
- {
- this.storeAccessor = storeAccessor;
- this.timeStamp = timeStamp;
-
- InternalStore store = (InternalStore)storeAccessor.getStore();
- InternalRepository repository = store.getRepository();
- revisionManager = repository.getRevisionManager();
-
- InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
- InternalCDOPackageUnit[] packageUnits = packageRegistry.getPackageUnits(timeStamp, timeStamp);
- for (InternalCDOPackageUnit packageUnit : packageUnits)
- {
- if (!packageUnit.isSystem())
- {
- newPackageUnits.add(packageUnit);
- }
- }
- }
-
- public CDOCommitData getCommitData()
- {
- storeAccessor.handleRevisions(null, null, timeStamp, true, new CDORevisionHandler.Filtered.Undetached(this));
-
- List<CDOIDAndVersion> detachedObjects = detachCounter.getDetachedObjects();
- return new CDOCommitDataImpl(newPackageUnits, newObjects, changedObjects, detachedObjects);
- }
-
- /**
- * @since 4.0
- */
- public boolean handleRevision(CDORevision rev)
- {
- if (rev.getTimeStamp() != timeStamp)
- {
- throw new IllegalArgumentException("Invalid revision time stamp: "
- + CDOCommonUtil.formatTimeStamp(rev.getTimeStamp()));
- }
-
- if (rev instanceof DetachedCDORevision)
- {
- // Do nothing. Detached objects are handled by detachCounter.
- }
- else
- {
- InternalCDORevision revision = (InternalCDORevision)rev;
- CDOID id = revision.getID();
- CDOBranch branch = revision.getBranch();
- int version = revision.getVersion();
- if (version > CDOBranchVersion.FIRST_VERSION)
- {
- CDOBranchVersion oldVersion = branch.getVersion(version - 1);
- InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, oldVersion, CDORevision.UNCHUNKED,
- true);
- InternalCDORevisionDelta delta = revision.compare(oldRevision);
- changedObjects.add(delta);
-
- detachCounter.update(oldRevision, delta);
- }
- else
- {
- InternalCDORevision oldRevision = getRevisionFromBase(id, branch);
- if (oldRevision != null)
- {
- InternalCDORevisionDelta delta = revision.compare(oldRevision);
- changedObjects.add(delta);
- }
- else
- {
- InternalCDORevision newRevision = revision.copy();
- newRevision.setRevised(CDOBranchPoint.UNSPECIFIED_DATE);
- newObjects.add(newRevision);
- }
- }
- }
-
- return true;
- }
-
- private InternalCDORevision getRevisionFromBase(CDOID id, CDOBranch branch)
- {
- if (branch.isMainBranch())
- {
- return null;
- }
-
- CDOBranchPoint base = branch.getBase();
- InternalCDORevision revision = revisionManager.getRevision(id, base, CDORevision.UNCHUNKED,
- CDORevision.DEPTH_NONE, true);
- if (revision == null)
- {
- revision = getRevisionFromBase(id, base.getBranch());
- }
-
- return revision;
- }
-
- /**
- * @author Eike Stepper
- */
- private static final class DetachCounter extends CDOFeatureDeltaVisitorImpl
- {
- private Map<CDOID, AtomicInteger> counters = new HashMap<CDOID, AtomicInteger>();
-
- private InternalCDORevision oldRevision;
-
- public DetachCounter()
- {
- }
-
- public void update(InternalCDORevision oldRevision, InternalCDORevisionDelta delta)
- {
- try
- {
- this.oldRevision = oldRevision;
- delta.accept(this);
- }
- finally
- {
- this.oldRevision = null;
- }
- }
-
- public List<CDOIDAndVersion> getDetachedObjects()
- {
- List<CDOIDAndVersion> result = new ArrayList<CDOIDAndVersion>();
- for (Entry<CDOID, AtomicInteger> entry : counters.entrySet())
- {
- int value = entry.getValue().get();
- if (value == -1)
- {
- CDOID id = entry.getKey();
- result.add(CDOIDUtil.createIDAndVersion(id, CDOBranchVersion.UNSPECIFIED_VERSION));
- }
- }
-
- return result;
- }
-
- @Override
- public void visit(CDOAddFeatureDelta delta)
- {
- if (isContainment(delta.getFeature()))
- {
- handleContainment(delta.getValue(), 1);
- }
- }
-
- @Override
- public void visit(CDORemoveFeatureDelta delta)
- {
- if (isContainment(delta.getFeature()))
- {
- handleContainment(delta.getValue(), -1);
- }
- }
-
- @Override
- public void visit(CDOSetFeatureDelta delta)
- {
- if (isContainment(delta.getFeature()))
- {
- handleContainment(delta.getValue(), 1);
- }
- }
-
- @Override
- public void visit(CDOUnsetFeatureDelta delta)
- {
- EStructuralFeature feature = delta.getFeature();
- if (isContainment(feature))
- {
- Object value = oldRevision.getValue(feature);
- handleContainment(value, -1);
- }
- }
-
- @Override
- public void visit(CDOClearFeatureDelta delta)
- {
- EStructuralFeature feature = delta.getFeature();
- if (isContainment(feature))
- {
- CDOList list = oldRevision.getList(feature);
- for (Object value : list)
- {
- handleContainment(value, -1);
- }
- }
- }
-
- private void handleContainment(Object value, int delta)
- {
- CDOID id = (CDOID)value;
- AtomicInteger counter = counters.get(id);
- if (counter == null)
- {
- counter = new AtomicInteger();
- counters.put(id, counter);
- }
-
- counter.addAndGet(delta);
- }
-
- private static boolean isContainment(EStructuralFeature feature)
- {
- if (feature instanceof EReference)
- {
- EReference reference = (EReference)feature;
- return reference.isContainment();
- }
-
- return false;
- }
- }
- }
-}
+/* + * 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 + * Simon McDuff - bug 201266 + * Simon McDuff - bug 213402 + */ +package org.eclipse.emf.cdo.spi.server; + +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.commit.CDOCommitData; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDTemp; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.model.CDOPackageUnit; +import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; +import org.eclipse.emf.cdo.common.revision.CDOList; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; +import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta; +import org.eclipse.emf.cdo.common.util.CDOCommonUtil; +import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl; +import org.eclipse.emf.cdo.internal.server.bundle.OM; +import org.eclipse.emf.cdo.server.ISession; +import org.eclipse.emf.cdo.server.IStoreAccessor; +import org.eclipse.emf.cdo.server.ITransaction; +import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; +import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; +import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl; +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.common.revision.InternalCDORevisionManager; + +import org.eclipse.net4j.util.lifecycle.Lifecycle; +import org.eclipse.net4j.util.om.monitor.OMMonitor; +import org.eclipse.net4j.util.om.trace.ContextTracer; + +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public abstract class StoreAccessorBase extends Lifecycle implements IStoreAccessor +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, StoreAccessorBase.class); + + private Store store; + + private Object context; + + private boolean reader; + + private List<CommitContext> commitContexts = new ArrayList<CommitContext>(); + + private StoreAccessorBase(Store store, Object context, boolean reader) + { + this.store = store; + this.context = context; + this.reader = reader; + } + + protected StoreAccessorBase(Store store, ISession session) + { + this(store, session, true); + } + + protected StoreAccessorBase(Store store, ITransaction transaction) + { + this(store, transaction, false); + } + + void setContext(Object context) + { + this.context = context; + } + + public Store getStore() + { + return store; + } + + public boolean isReader() + { + return reader; + } + + /** + * @since 3.0 + */ + public InternalSession getSession() + { + if (context instanceof ITransaction) + { + return (InternalSession)((ITransaction)context).getSession(); + } + + return (InternalSession)context; + } + + public ITransaction getTransaction() + { + if (context instanceof ITransaction) + { + return (ITransaction)context; + } + + return null; + } + + public void release() + { + store.releaseAccessor(this); + commitContexts.clear(); + } + + /** + * @since 3.0 + */ + public final void write(InternalCommitContext context, OMMonitor monitor) + { + if (TRACER.isEnabled()) + { + TRACER.format("Writing transaction: {0}", getTransaction()); //$NON-NLS-1$ + } + + commitContexts.add(context); + doWrite(context, monitor); + } + + protected abstract void doWrite(InternalCommitContext context, OMMonitor monitor); + + /** + * @since 3.0 + */ + public final void commit(OMMonitor monitor) + { + doCommit(monitor); + + long latest = CDORevision.UNSPECIFIED_DATE; + long latestNonLocal = CDORevision.UNSPECIFIED_DATE; + for (CommitContext commitContext : commitContexts) + { + CDOBranchPoint branchPoint = commitContext.getBranchPoint(); + long timeStamp = branchPoint.getTimeStamp(); + if (timeStamp > latest) + { + latest = timeStamp; + } + + CDOBranch branch = branchPoint.getBranch(); + if (!branch.isLocal()) + { + if (timeStamp > latestNonLocal) + { + latestNonLocal = timeStamp; + } + } + } + + getStore().setLastCommitTime(latest); + getStore().setLastNonLocalCommitTime(latestNonLocal); + } + + /** + * @since 3.0 + */ + protected abstract void doCommit(OMMonitor monitor); + + public final void rollback() + { + if (TRACER.isEnabled()) + { + TRACER.format("Rolling back transaction: {0}", getTransaction()); //$NON-NLS-1$ + } + + for (CommitContext commitContext : commitContexts) + { + doRollback(commitContext); + } + } + + protected abstract void doRollback(CommitContext commitContext); + + /** + * @since 3.0 + */ + public CDOID readResourceID(CDOID folderID, String name, CDOBranchPoint branchPoint) + { + QueryResourcesContext.ExactMatch context = Store.createExactMatchContext(folderID, name, branchPoint); + queryResources(context); + return context.getResourceID(); + } + + /** + * @since 3.0 + */ + public CDOCommitData loadCommitData(long timeStamp) + { + CommitDataRevisionHandler handler = new CommitDataRevisionHandler(this, timeStamp); + return handler.getCommitData(); + } + + /** + * Add ID mappings for all new objects of a transaction to the commit context. The implementor must, for each new + * object of the commit context, determine a permanent CDOID and make it known to the context by calling + * {@link InternalCommitContext#addIDMapping(CDOID, CDOID)}. + * + * @since 3.0 + */ + public void addIDMappings(InternalCommitContext commitContext, OMMonitor monitor) + { + try + { + CDORevision[] newObjects = commitContext.getNewObjects(); + monitor.begin(newObjects.length); + for (CDORevision revision : newObjects) + { + CDOID id = revision.getID(); + if (id instanceof CDOIDTemp) + { + CDOIDTemp oldID = (CDOIDTemp)id; + CDOID newID = getNextCDOID(revision); + if (CDOIDUtil.isNull(newID) || newID.isTemporary()) + { + throw new IllegalStateException("newID=" + newID); //$NON-NLS-1$ + } + + commitContext.addIDMapping(oldID, newID); + } + + monitor.worked(); + } + } + finally + { + monitor.done(); + } + } + + protected abstract CDOID getNextCDOID(CDORevision revision); + + protected void doPassivate() throws Exception + { + } + + protected void doUnpassivate() throws Exception + { + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static class CommitDataRevisionHandler implements CDORevisionHandler + { + private IStoreAccessor storeAccessor; + + private long timeStamp; + + private InternalCDORevisionManager revisionManager; + + private List<CDOPackageUnit> newPackageUnits = new ArrayList<CDOPackageUnit>(); + + private List<CDOIDAndVersion> newObjects = new ArrayList<CDOIDAndVersion>(); + + private List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>(); + + private DetachCounter detachCounter = new DetachCounter(); + + public CommitDataRevisionHandler(IStoreAccessor storeAccessor, long timeStamp) + { + this.storeAccessor = storeAccessor; + this.timeStamp = timeStamp; + + InternalStore store = (InternalStore)storeAccessor.getStore(); + InternalRepository repository = store.getRepository(); + revisionManager = repository.getRevisionManager(); + + InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false); + InternalCDOPackageUnit[] packageUnits = packageRegistry.getPackageUnits(timeStamp, timeStamp); + for (InternalCDOPackageUnit packageUnit : packageUnits) + { + if (!packageUnit.isSystem()) + { + newPackageUnits.add(packageUnit); + } + } + } + + public CDOCommitData getCommitData() + { + storeAccessor.handleRevisions(null, null, timeStamp, true, new CDORevisionHandler.Filtered.Undetached(this)); + + List<CDOIDAndVersion> detachedObjects = detachCounter.getDetachedObjects(); + return new CDOCommitDataImpl(newPackageUnits, newObjects, changedObjects, detachedObjects); + } + + /** + * @since 4.0 + */ + public boolean handleRevision(CDORevision rev) + { + if (rev.getTimeStamp() != timeStamp) + { + throw new IllegalArgumentException("Invalid revision time stamp: " + + CDOCommonUtil.formatTimeStamp(rev.getTimeStamp())); + } + + if (rev instanceof DetachedCDORevision) + { + // Do nothing. Detached objects are handled by detachCounter. + } + else + { + InternalCDORevision revision = (InternalCDORevision)rev; + CDOID id = revision.getID(); + CDOBranch branch = revision.getBranch(); + int version = revision.getVersion(); + if (version > CDOBranchVersion.FIRST_VERSION) + { + CDOBranchVersion oldVersion = branch.getVersion(version - 1); + InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, oldVersion, CDORevision.UNCHUNKED, + true); + InternalCDORevisionDelta delta = revision.compare(oldRevision); + changedObjects.add(delta); + + detachCounter.update(oldRevision, delta); + } + else + { + InternalCDORevision oldRevision = getRevisionFromBase(id, branch); + if (oldRevision != null) + { + InternalCDORevisionDelta delta = revision.compare(oldRevision); + changedObjects.add(delta); + } + else + { + InternalCDORevision newRevision = revision.copy(); + newRevision.setRevised(CDOBranchPoint.UNSPECIFIED_DATE); + newObjects.add(newRevision); + } + } + } + + return true; + } + + private InternalCDORevision getRevisionFromBase(CDOID id, CDOBranch branch) + { + if (branch.isMainBranch()) + { + return null; + } + + CDOBranchPoint base = branch.getBase(); + InternalCDORevision revision = revisionManager.getRevision(id, base, CDORevision.UNCHUNKED, + CDORevision.DEPTH_NONE, true); + if (revision == null) + { + revision = getRevisionFromBase(id, base.getBranch()); + } + + return revision; + } + + /** + * @author Eike Stepper + */ + private static final class DetachCounter extends CDOFeatureDeltaVisitorImpl + { + private Map<CDOID, AtomicInteger> counters = new HashMap<CDOID, AtomicInteger>(); + + private InternalCDORevision oldRevision; + + public DetachCounter() + { + } + + public void update(InternalCDORevision oldRevision, InternalCDORevisionDelta delta) + { + try + { + this.oldRevision = oldRevision; + delta.accept(this); + } + finally + { + this.oldRevision = null; + } + } + + public List<CDOIDAndVersion> getDetachedObjects() + { + List<CDOIDAndVersion> result = new ArrayList<CDOIDAndVersion>(); + for (Entry<CDOID, AtomicInteger> entry : counters.entrySet()) + { + int value = entry.getValue().get(); + if (value == -1) + { + CDOID id = entry.getKey(); + result.add(CDOIDUtil.createIDAndVersion(id, CDOBranchVersion.UNSPECIFIED_VERSION)); + } + } + + return result; + } + + @Override + public void visit(CDOAddFeatureDelta delta) + { + if (isContainment(delta.getFeature())) + { + handleContainment(delta.getValue(), 1); + } + } + + @Override + public void visit(CDORemoveFeatureDelta delta) + { + if (isContainment(delta.getFeature())) + { + handleContainment(delta.getValue(), -1); + } + } + + @Override + public void visit(CDOSetFeatureDelta delta) + { + if (isContainment(delta.getFeature())) + { + handleContainment(delta.getValue(), 1); + } + } + + @Override + public void visit(CDOUnsetFeatureDelta delta) + { + EStructuralFeature feature = delta.getFeature(); + if (isContainment(feature)) + { + Object value = oldRevision.getValue(feature); + handleContainment(value, -1); + } + } + + @Override + public void visit(CDOClearFeatureDelta delta) + { + EStructuralFeature feature = delta.getFeature(); + if (isContainment(feature)) + { + CDOList list = oldRevision.getList(feature); + for (Object value : list) + { + handleContainment(value, -1); + } + } + } + + private void handleContainment(Object value, int delta) + { + CDOID id = (CDOID)value; + AtomicInteger counter = counters.get(id); + if (counter == null) + { + counter = new AtomicInteger(); + counters.put(id, counter); + } + + counter.addAndGet(delta); + } + + private static boolean isContainment(EStructuralFeature feature) + { + if (feature instanceof EReference) + { + EReference reference = (EReference)feature; + return reference.isContainment(); + } + + return false; + } + } + } +} |