/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.db.impl.query; import java.util.concurrent.Semaphore; import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.impl.procedure.InternalProcedure; import org.simantics.db.procedure.ListenerBase; final public class ValueQuery extends UnaryQuery> { private ValueQuery(final int resource) { super(resource); } final static ValueQuery entry(final QueryProcessor provider, final int r) { return (ValueQuery)provider.valueMap.get(r); } final static byte[] runner(final ReadGraphImpl graph, final int r, CacheEntry parent, final ListenerBase listener, final InternalProcedure procedure) { QueryProcessor processor = graph.processor; ValueQuery entry = (ValueQuery)processor.valueMap.get(r); if(entry == null) { entry = new ValueQuery(r); entry.setPending(); entry.clearResult(processor.querySupport); entry.putEntry(processor); return (byte[])processor.performForEach(graph, entry, parent, listener, procedure); } else { return (byte[])processor.performForEach(graph, entry, parent, listener, procedure); } } final public static byte[] queryEach(ReadGraphImpl graph, final int r, final CacheEntry parent, final ListenerBase listener, final InternalProcedure procedure) { assert(r != 0); if(graph.parent == null && listener == null) { return ValueQuery.computeForEach(graph, r, null, procedure); } else { return runner(graph, r, parent, listener, procedure); } } final public static byte[] queryEach(ReadGraphImpl graph, final int r, final CacheEntry parent) { assert(r != 0); if(graph.parent == null) { return ValueQuery.computeForEach(graph, r); } else { return runner(graph, r, parent, null, null); } } @Override public UnaryQuery> getEntry(QueryProcessor provider) { return provider.valueMap.get(id); } @Override public void putEntry(QueryProcessor provider) { provider.valueMap.put(id, this); } @Override final public void removeEntry(QueryProcessor provider) { provider.valueMap.remove(id); } public static byte[] computeForEach(ReadGraphImpl graph, final int r, final ValueQuery entry, final InternalProcedure procedure) { graph.ensureLoaded(r); byte[] value = graph.getValue(r); if(entry != null) { entry.setResult(value); entry.setReady(); } if(procedure != null) { procedure.execute(graph, value); } return value; } public static byte[] computeForEach(ReadGraphImpl graph, final int r) { graph.ensureLoaded(r); return graph.getValue(r); } @Override public Object computeForEach(ReadGraphImpl graph, final QueryProcessor queryProvider, final InternalProcedure procedure, final boolean store) { return computeForEach(graph, id, this, procedure); } @Override public String toString() { return "Value[" + id + "]"; } @Override public Object performFromCache(ReadGraphImpl graph, QueryProcessor queryProvider, InternalProcedure procedure) { return computeForEach(graph, queryProvider, procedure, false); } @Override public void recompute(ReadGraphImpl graph, QueryProcessor provider) { final Semaphore s = new Semaphore(0); computeForEach(graph, provider, new InternalProcedure() { @Override public void execute(ReadGraphImpl graph, byte[] result) { s.release(); } @Override public void exception(ReadGraphImpl graph, Throwable t) { throw new Error("Error in recompute.", t); } }, true); while(!s.tryAcquire()) { provider.resume(graph); } } @Override boolean isImmutable(ReadGraphImpl graph) { return graph.processor.isImmutable(id); } }