blob: 189ab87a5b1ce9e63f99217edef0023d0946ef9b [file] [log] [blame]
/**
* 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
* Simon McDuff - http://bugs.eclipse.org/201266
* Simon McDuff - http://bugs.eclipse.org/213402
* Caspar De Groot - https://bugs.eclipse.org/333260
*/
package org.eclipse.emf.cdo.spi.server;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDTemp;
import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
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.InternalCDOPackageUnit;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eike Stepper
* @since 2.0
*/
public abstract class StoreAccessor extends Lifecycle implements IStoreAccessor
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, StoreAccessor.class);
private List<CommitContext> commitContexts = new ArrayList<CommitContext>();
private Store store;
private Object context;
private boolean reader;
private StoreAccessor(Store store, Object context, boolean reader)
{
this.store = store;
this.context = context;
this.reader = reader;
}
protected StoreAccessor(Store store, ISession session)
{
this(store, session, true);
}
protected StoreAccessor(Store store, ITransaction transaction)
{
this(store, transaction, false);
}
public Store getStore()
{
return store;
}
public boolean isReader()
{
return reader;
}
public ISession getSession()
{
if (context instanceof ITransaction)
{
return ((ITransaction)context).getSession();
}
return (ISession)context;
}
public ITransaction getTransaction()
{
if (context instanceof ITransaction)
{
return (ITransaction)context;
}
return null;
}
public CDOID readResourceID(CDOID folderID, String name, long timeStamp)
{
IStoreAccessor.QueryResourcesContext.ExactMatch context = //
Store.createExactMatchContext(folderID, name, timeStamp);
queryResources(context);
return context.getResourceID();
}
public InternalCDORevision verifyRevision(InternalCDORevision revision)
{
return revision;
}
public void write(CommitContext context, OMMonitor monitor)
{
if (TRACER.isEnabled())
{
TRACER.format("Writing transaction: {0}", getTransaction()); //$NON-NLS-1$
}
commitContexts.add(context);
long timeStamp = context.getTimeStamp();
boolean deltas = store.getRepository().isSupportingRevisionDeltas();
InternalCDOPackageUnit[] newPackageUnits = context.getNewPackageUnits();
InternalCDORevision[] newObjects = context.getNewObjects();
CDOID[] detachedObjects = context.getDetachedObjects();
int dirtyCount = deltas ? context.getDirtyObjectDeltas().length : context.getDirtyObjects().length;
try
{
monitor.begin(newPackageUnits.length + 2 + newObjects.length + detachedObjects.length + dirtyCount);
if (newPackageUnits.length != 0)
{
writePackageUnits(newPackageUnits, monitor.fork(newPackageUnits.length));
}
addIDMappings(context, monitor.fork());
context.applyIDMappings(monitor.fork());
if (detachedObjects.length != 0)
{
detachObjects(detachedObjects, timeStamp - 1, monitor.fork(detachedObjects.length));
}
if (newObjects.length != 0)
{
writeRevisions(newObjects, monitor.fork(newObjects.length));
}
if (dirtyCount != 0)
{
if (deltas)
{
writeRevisionDeltas(context.getDirtyObjectDeltas(), timeStamp, monitor.fork(dirtyCount));
}
else
{
writeRevisions(context.getDirtyObjects(), monitor.fork(dirtyCount));
}
}
}
finally
{
monitor.done();
}
}
public void rollback()
{
if (TRACER.isEnabled())
{
TRACER.format("Rolling back transaction: {0}", getTransaction()); //$NON-NLS-1$
}
for (CommitContext commitContext : commitContexts)
{
rollback(commitContext);
}
}
protected abstract void rollback(IStoreAccessor.CommitContext commitContext);
public final void release()
{
store.releaseAccessor(this);
commitContexts.clear();
}
/**
* 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 CommitContext#addIDMapping(CDOIDTemp, CDOID)}.
*/
protected abstract void addIDMappings(CommitContext context, OMMonitor monitor);
protected abstract void writeRevisions(InternalCDORevision[] revisions, OMMonitor monitor);
protected abstract void writeRevisionDeltas(InternalCDORevisionDelta[] revisionDeltas, long created, OMMonitor monitor);
protected abstract void detachObjects(CDOID[] detachedObjects, long revised, OMMonitor monitor);
@Override
protected abstract void doActivate() throws Exception;
@Override
protected abstract void doDeactivate() throws Exception;
protected abstract void doPassivate() throws Exception;
protected abstract void doUnpassivate() throws Exception;
public void handleRevisions(CDORevisionHandler handler)
{
throw new RuntimeException("handleRevisions not supported");
}
}