blob: 813c53af65cc2c6fb79193549fedfa42ae8404d8 [file] [log] [blame]
/*
* Copyright (c) 2009-2014 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:
* Simon McDuff - initial API and implementation
* Eike Stepper - maintenance
* Simon McDuff - bug 213402
*/
package org.eclipse.emf.cdo.internal.server.mem;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.revision.CDORevisionCacheAdder;
import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
import org.eclipse.emf.cdo.server.IQueryContext;
import org.eclipse.emf.cdo.server.IQueryHandler;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking2;
import org.eclipse.emf.cdo.server.IStoreAccessor.Raw;
import org.eclipse.emf.cdo.server.ITransaction;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader3;
import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
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.emf.cdo.spi.server.InternalCommitContext;
import org.eclipse.emf.cdo.spi.server.LongIDStoreAccessor;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Simon McDuff
*/
public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, DurableLocking2, BranchLoader3
{
private final IQueryHandler testQueryHandler = new IQueryHandler()
{
public void executeQuery(CDOQueryInfo info, IQueryContext queryContext)
{
List<Object> filters = new ArrayList<Object>();
Object context = info.getParameters().get("context"); //$NON-NLS-1$
Long sleep = (Long)info.getParameters().get("sleep"); //$NON-NLS-1$
Integer integers = (Integer)info.getParameters().get("integers"); //$NON-NLS-1$
Integer error = (Integer)info.getParameters().get("error"); //$NON-NLS-1$
if (integers != null)
{
executeQuery(integers, error, queryContext);
return;
}
if (context != null)
{
if (context instanceof EClass)
{
final EClass eClass = (EClass)context;
filters.add(new Object()
{
@Override
public int hashCode()
{
return eClass.hashCode();
}
@Override
public boolean equals(Object obj)
{
InternalCDORevision revision = (InternalCDORevision)obj;
return revision.getEClass().equals(eClass);
}
});
}
}
int i = 0;
for (InternalCDORevision revision : getStore().getCurrentRevisions())
{
if (sleep != null)
{
try
{
Thread.sleep(sleep);
}
catch (InterruptedException ex)
{
throw WrappedException.wrap(ex);
}
}
if (isValid(revision, filters))
{
throwExceptionAt(error, ++i);
if (!queryContext.addResult(revision))
{
// No more results allowed
break;
}
}
}
}
private void throwExceptionAt(Integer error, int i)
{
if (error != null && i == error)
{
throw new RuntimeException("Simulated problem in query execution at result " + i);
}
}
private void executeQuery(int integers, Integer error, IQueryContext queryContext)
{
for (int i = 1; i <= integers; ++i)
{
throwExceptionAt(error, i);
if (!queryContext.addResult(i))
{
// No more results allowed
break;
}
}
}
private boolean isValid(InternalCDORevision revision, List<Object> filters)
{
for (Object filter : filters)
{
if (!filter.equals(revision))
{
return false;
}
}
return true;
}
};
private List<InternalCDORevision> newRevisions = new ArrayList<InternalCDORevision>();
public MEMStoreAccessor(MEMStore store, ISession session)
{
super(store, session);
}
/**
* @since 2.0
*/
public MEMStoreAccessor(MEMStore store, ITransaction transaction)
{
super(store, transaction);
}
@Override
public MEMStore getStore()
{
return (MEMStore)super.getStore();
}
/**
* @since 2.0
*/
public MEMStoreChunkReader createChunkReader(InternalCDORevision revision, EStructuralFeature feature)
{
return new MEMStoreChunkReader(this, revision, feature);
}
public Collection<InternalCDOPackageUnit> readPackageUnits()
{
return Collections.emptySet();
}
public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit)
{
throw new UnsupportedOperationException();
}
public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
{
return getStore().createBranch(branchID, branchInfo);
}
public BranchInfo loadBranch(int branchID)
{
return getStore().loadBranch(branchID);
}
public SubBranchInfo[] loadSubBranches(int branchID)
{
return getStore().loadSubBranches(branchID);
}
public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler)
{
return getStore().loadBranches(startID, endID, branchHandler);
}
@Deprecated
public void deleteBranch(int branchID)
{
throw new UnsupportedOperationException();
}
@Deprecated
public void renameBranch(int branchID, String newName)
{
throw new UnsupportedOperationException();
}
public void renameBranch(int branchID, String oldName, String newName)
{
getStore().renameBranch(branchID, oldName, newName);
}
public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
{
getStore().loadCommitInfos(branch, startTime, endTime, handler);
}
public Set<CDOID> readChangeSet(OMMonitor monitor, CDOChangeSetSegment... segments)
{
return getStore().readChangeSet(segments);
}
public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint, int listChunk,
CDORevisionCacheAdder cache)
{
return getStore().getRevision(id, branchPoint);
}
public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk,
CDORevisionCacheAdder cache)
{
return getStore().getRevisionByVersion(id, branchVersion);
}
public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime,
CDORevisionHandler handler)
{
getStore().handleRevisions(eClass, branch, timeStamp, exactTime, handler);
}
/**
* @since 2.0
*/
@Override
protected void doCommit(OMMonitor monitor)
{
// Do nothing
}
@Override
public void doWrite(InternalCommitContext context, OMMonitor monitor)
{
MEMStore store = getStore();
synchronized (store)
{
super.doWrite(context, monitor);
}
}
@Override
protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID,
String comment, OMMonitor monitor)
{
getStore().addCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment);
}
@Override
protected void doRollback(CommitContext context)
{
MEMStore store = getStore();
synchronized (store)
{
for (InternalCDORevision revision : newRevisions)
{
store.rollbackRevision(revision);
}
}
}
public void writePackageUnits(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
{
// Do nothing
}
@Override
protected void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor)
{
for (InternalCDORevision revision : revisions)
{
writeRevision(revision);
}
}
protected void writeRevision(InternalCDORevision revision)
{
newRevisions.add(revision);
getStore().addRevision(revision, false);
}
/**
* @since 2.0
*/
@Override
protected void writeRevisionDeltas(InternalCDORevisionDelta[] revisionDeltas, CDOBranch branch, long created,
OMMonitor monitor)
{
for (InternalCDORevisionDelta revisionDelta : revisionDeltas)
{
writeRevisionDelta(revisionDelta, branch, created);
}
}
/**
* @since 2.0
*/
protected void writeRevisionDelta(InternalCDORevisionDelta revisionDelta, CDOBranch branch, long created)
{
CDOID id = revisionDelta.getID();
CDOBranchVersion version = revisionDelta.getBranch().getVersion(revisionDelta.getVersion());
InternalCDORevision revision = getStore().getRevisionByVersion(id, version);
if (revision.getVersion() != revisionDelta.getVersion())
{
throw new ConcurrentModificationException("Trying to update object " + id //$NON-NLS-1$
+ " that was already modified"); //$NON-NLS-1$
}
InternalCDORevision newRevision = revision.copy();
newRevision.adjustForCommit(branch, created);
revisionDelta.applyTo(newRevision);
writeRevision(newRevision);
}
@Override
protected void detachObjects(CDOID[] detachedObjects, CDOBranch branch, long timeStamp, OMMonitor monitor)
{
for (CDOID id : detachedObjects)
{
detachObject(id, branch, timeStamp);
}
}
/**
* @since 3.0
*/
protected void detachObject(CDOID id, CDOBranch branch, long timeStamp)
{
getStore().detachObject(id, branch, timeStamp);
}
/**
* @since 2.0
*/
public void queryResources(QueryResourcesContext context)
{
getStore().queryResources(context);
}
public void queryXRefs(QueryXRefsContext context)
{
getStore().queryXRefs(context);
}
public IQueryHandler getQueryHandler(CDOQueryInfo info)
{
if ("TEST".equals(info.getQueryLanguage())) //$NON-NLS-1$
{
return testQueryHandler;
}
return null;
}
public void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime)
throws IOException
{
getStore().rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime);
}
public void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime,
OMMonitor monitor) throws IOException
{
getStore().rawImport(in, fromBranchID, toBranchID, fromCommitTime, toCommitTime, monitor);
}
public void rawStore(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
{
writePackageUnits(packageUnits, monitor);
}
public void rawStore(InternalCDORevision revision, OMMonitor monitor)
{
getStore().addRevision(revision, true);
}
public void rawStore(byte[] id, long size, InputStream inputStream) throws IOException
{
writeBlob(id, size, inputStream);
}
public void rawStore(byte[] id, long size, Reader reader) throws IOException
{
writeClob(id, size, reader);
}
public void rawStore(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment,
OMMonitor monitor)
{
writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, monitor);
}
public void rawDelete(CDOID id, int version, CDOBranch branch, EClass eClass, OMMonitor monitor)
{
getStore().rawDelete(id, version, branch);
}
public void rawCommit(double commitWork, OMMonitor monitor)
{
// Do nothing
}
public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
Map<CDOID, LockGrade> locks)
{
return getStore().createLockArea(userID, branchPoint, readOnly, locks);
}
public LockArea createLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint, boolean readOnly,
Map<CDOID, LockGrade> locks)
{
return getStore().createLockArea(durableLockingID, userID, branchPoint, readOnly, locks);
}
public void updateLockArea(LockArea lockArea)
{
getStore().updateLockArea(lockArea);
}
public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException
{
return getStore().getLockArea(durableLockingID);
}
public void getLockAreas(String userIDPrefix, Handler handler)
{
getStore().getLockAreas(userIDPrefix, handler);
}
public void deleteLockArea(String durableLockingID)
{
getStore().deleteLockArea(durableLockingID);
}
public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock)
{
getStore().lock(durableLockingID, type, objectsToLock);
}
public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock)
{
getStore().unlock(durableLockingID, type, objectsToUnlock);
}
public void unlock(String durableLockingID)
{
getStore().unlock(durableLockingID);
}
public void queryLobs(List<byte[]> ids)
{
getStore().queryLobs(ids);
}
public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException
{
getStore().handleLobs(fromTime, toTime, handler);
}
public void loadLob(byte[] id, OutputStream out) throws IOException
{
getStore().loadLob(id, out);
}
@Override
protected void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException
{
getStore().writeBlob(id, size, inputStream);
}
@Override
protected void writeClob(byte[] id, long size, Reader reader) throws IOException
{
getStore().writeClob(id, size, reader);
}
@Override
protected void doActivate() throws Exception
{
// Do nothing
}
@Override
protected void doDeactivate() throws Exception
{
newRevisions.clear();
}
@Override
protected void doPassivate() throws Exception
{
// Pooling of store accessors not supported
}
@Override
protected void doUnpassivate() throws Exception
{
// Pooling of store accessors not supported
}
}