diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/optimizer/Optimizer.java')
-rw-r--r-- | plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/optimizer/Optimizer.java | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/optimizer/Optimizer.java b/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/optimizer/Optimizer.java new file mode 100644 index 0000000000..4b41d96793 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.lissome/src/org/eclipse/emf/cdo/server/internal/lissome/optimizer/Optimizer.java @@ -0,0 +1,328 @@ +/* + * 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.server.internal.lissome.optimizer; + +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.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.CDORevisionCacheAdder; +import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; +import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; +import org.eclipse.emf.cdo.eresource.EresourcePackage; +import org.eclipse.emf.cdo.server.IStoreAccessor; +import org.eclipse.emf.cdo.server.IStoreAccessor.QueryResourcesContext; +import org.eclipse.emf.cdo.server.internal.lissome.LissomeStore; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache; + +import org.eclipse.net4j.util.ObjectUtil; +import org.eclipse.net4j.util.concurrent.Worker; +import org.eclipse.net4j.util.io.IORuntimeException; +import org.eclipse.net4j.util.lifecycle.Lifecycle; + +import org.eclipse.emf.ecore.EClass; + +import java.io.IOException; +import java.util.LinkedList; + +/** + * @author Eike Stepper + */ +public class Optimizer extends Lifecycle +{ + private final LissomeStore store; + + private final boolean async; + + private final LinkedList<OptimizerTask> queue = new LinkedList<OptimizerTask>(); + + private Worker worker; + + private Cache cache; + + public Optimizer(LissomeStore store, boolean async) + { + this.store = store; + this.async = async; + } + + public LissomeStore getStore() + { + return store; + } + + public boolean isAsync() + { + return async; + } + + public OptimizerTask[] getTasks() + { + return getCache().getTasks(); + } + + public void addTask(OptimizerTask task) + { + synchronized (queue) + { + cache = null; + queue.addLast(task); + queue.notifyAll(); + } + + if (!async) + { + try + { + executeFirstTask(); + } + catch (InterruptedException ignore) + { + // Can not happen + } + } + } + + protected void executeFirstTask() throws InterruptedException + { + try + { + OptimizerTask task = getFirstTask(); + task.execute(this); + removeFirstTask(); + } + catch (InterruptedException ex) + { + throw ex; + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + } + + protected OptimizerTask getFirstTask() throws InterruptedException + { + OptimizerTask task; + synchronized (queue) + { + while (queue.isEmpty()) + { + queue.wait(100); + } + + task = queue.getFirst(); + } + + return task; + } + + protected void removeFirstTask() + { + synchronized (queue) + { + cache = null; + queue.removeFirst(); + queue.notifyAll(); + } + } + + @Override + protected void doActivate() throws Exception + { + super.doActivate(); + if (async) + { + worker = new TaskWorker(); + worker.activate(); + } + } + + @Override + protected void doDeactivate() throws Exception + { + synchronized (queue) + { + while (!queue.isEmpty()) + { + queue.wait(100); + } + } + + if (async) + { + worker.deactivate(); + worker = null; + } + + super.doDeactivate(); + } + + protected Cache getCache() + { + synchronized (queue) + { + if (cache == null) + { + boolean supportingBranches = store.getRepository().isSupportingBranches(); + cache = new Cache(queue, supportingBranches); + } + + return cache; + } + } + + public boolean queryResources(IStoreAccessor.QueryResourcesContext context) + { + Cache cache = getCache(); + return cache.queryResources(context); + } + + public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint) + { + Cache cache = getCache(); + return cache.readRevision(id, branchPoint); + } + + public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime, + CDORevisionHandler handler) + { + // TODO: implement Optimizer.handleRevisions(eClass, branch, timeStamp, exactTime, handler) + } + + /** + * @author Eike Stepper + */ + private final class TaskWorker extends Worker + { + @Override + protected String getThreadName() + { + return "OptimizerTaskWorker"; + } + + @Override + protected void work(WorkContext context) throws Exception + { + executeFirstTask(); + } + } + + /** + * @author Eike Stepper + */ + private static final class Cache + { + private final OptimizerTask[] tasks; + + private final boolean supportingBranches; + + private CDORevisionCache revisionCache; + + public Cache(LinkedList<OptimizerTask> queue, boolean supportingBranches) + { + this.supportingBranches = supportingBranches; + tasks = queue.toArray(new OptimizerTask[queue.size()]); + } + + public OptimizerTask[] getTasks() + { + return tasks; + } + + public synchronized CDORevisionCache getRevisionCache() + { + if (revisionCache == null) + { + revisionCache = CDORevisionUtil.createRevisionCache(true, supportingBranches); + + CDORevisionCacheAdder adder = new CDORevisionCacheAdder() + { + public void addRevision(CDORevision revision) + { + reviseOldRevision(revision); + revisionCache.addRevision(revision); + } + + private void reviseOldRevision(CDORevision revision) + { + int version = revision.getVersion(); + if (version > CDOBranchVersion.FIRST_VERSION) + { + CDOID id = revision.getID(); + CDOBranchVersion oldVersion = revision.getBranch().getVersion(version - 1); + InternalCDORevision oldRevision = (InternalCDORevision)revisionCache.getRevisionByVersion(id, oldVersion); + if (oldRevision != null) + { + oldRevision.setRevised(revision.getTimeStamp() - 1); + } + } + } + }; + + for (OptimizerTask task : tasks) + { + if (task instanceof CommitTransactionTask) + { + CommitTransactionTask commitTask = (CommitTransactionTask)task; + commitTask.cacheRevisions(adder); + } + } + } + + return revisionCache; + } + + public boolean queryResources(QueryResourcesContext context) + { + InternalCDORevisionCache revisionCache = (InternalCDORevisionCache)getRevisionCache(); + for (CDORevision revision : revisionCache.getRevisions(context)) + { + if (!revision.isResourceNode()) + { + continue; + } + + CDOID folderID = (CDOID)revision.data().getContainerID(); + if (!ObjectUtil.equals(folderID, context.getFolderID())) + { + continue; + } + + String name = context.getName(); + String revisionName = (String)revision.data().get(EresourcePackage.Literals.CDO_RESOURCE_NODE__NAME, 0); + boolean useEquals = context.exactMatch() || revisionName == null || name == null; + boolean match = useEquals ? ObjectUtil.equals(revisionName, name) : revisionName.startsWith(name); + if (!match) + { + continue; + } + + if (!context.addResource(revision.getID())) + { + // No more results allowed + return false; + } + } + + return true; + } + + public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint) + { + CDORevisionCache revisionCache = getRevisionCache(); + return (InternalCDORevision)revisionCache.getRevision(id, branchPoint); + } + } +} |