package org.simantics.scl.db;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import org.cojen.classfile.TypeDesc;
import org.simantics.Simantics;
import org.simantics.db.service.SerialisationSupport;
import org.simantics.db.service.VirtualGraphSupport;
import org.simantics.layer0.utils.triggers.IActivationManager;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
+import org.simantics.scl.compiler.errors.DoesNotExist;
import org.simantics.scl.compiler.errors.Failable;
+import org.simantics.scl.compiler.errors.Failure;
import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
import org.simantics.scl.compiler.module.Module;
import org.simantics.scl.compiler.module.repository.ImportFailureException;
import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
+import org.simantics.scl.compiler.runtime.RuntimeModule;
+import org.simantics.scl.compiler.top.ValueNotFound;
+import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+import org.simantics.scl.compiler.types.util.MultiFunction;
import org.simantics.scl.osgi.SCLOsgi;
+import org.simantics.scl.reflection.ValueNotFoundException;
import org.simantics.scl.runtime.SCLContext;
import org.simantics.scl.runtime.function.Function;
import org.simantics.scl.runtime.function.Function1;
return null;
}
}
+
+ public static Function resolveFunction(RuntimeModule rm, String function) throws ValueNotFound {
+ return (Function)rm.getValue(function);
+ }
+
+ private static SCLValue resolveSCLValue(RuntimeModule rm, String function) throws ValueNotFound {
+ return rm.getModule().getValue(function);
+ }
+
+ private static RuntimeModule resolveRuntimeModule(String module) throws ValueNotFound {
+ Failable<RuntimeModule> f = SCLOsgi.MODULE_REPOSITORY.getRuntimeModule(module);
+ if(f.didSucceed())
+ return f.getResult();
+ else if(f == DoesNotExist.INSTANCE)
+ throw new ValueNotFound("Didn't find module " + module);
+ else
+ throw new ValueNotFound(((Failure)f).toString());
+ }
+
+ private static List<TCon> getEffects(SCLValue value) throws ValueNotFoundException, ValueNotFound, MatchException {
+
+ Type type = value.getType();
+ MultiFunction mfun = Types.matchFunction(type, 1);
+ ArrayList<TCon> concreteEffects = new ArrayList<>();
+ mfun.effect.collectConcreteEffects(concreteEffects);
+ return concreteEffects;
+
+ }
+
+ public static List<TCon> getEffects(RuntimeModule rm, String function) throws ValueNotFoundException, ValueNotFound, MatchException {
+ return getEffects(resolveSCLValue(rm, function));
+ }
+
+ public static List<TCon> getEffects(String module, String function) throws ValueNotFoundException, ValueNotFound, MatchException {
+ return getEffects(resolveSCLValue(resolveRuntimeModule(module), function));
+ }
+
+ private static <T> T evaluate(Function function, Object ... args) {
+ return (T)function.applyArray(args);
+ }
+
+ private static <T> T evaluate(RuntimeModule rm, String function, Object ... args) throws ValueNotFound {
+ return evaluate(resolveFunction(rm, function));
+ }
+
+ public static <T> T evaluate(String module, String function, Object ... args) throws ValueNotFound {
+ return evaluate(resolveRuntimeModule(module), function, args);
+ }
+
+ public static <T> T evaluateDB(String module, String function, Object ... args) throws DatabaseException {
+ try {
+ RuntimeModule rm = resolveRuntimeModule(module);
+ List<TCon> effects = getEffects(resolveSCLValue(rm, function));
+ Function f = resolveFunction(rm, function);
+ if(effects.contains(Types.WRITE_GRAPH)) {
+ return syncWrite(f, args);
+ } else if(effects.contains(Types.READ_GRAPH)) {
+ return syncRead(f, args);
+ } else {
+ return evaluate(f, args);
+ }
+ } catch (ValueNotFound e) {
+ throw new DatabaseException("SCL Value not found: " + e.name);
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ }
+ }
- public static void asyncRead(final Function f) throws DatabaseException {
+ public static <T> T evaluateGraph(String module, String function, Object graph, Object ... args) throws DatabaseException {
+ final SCLContext context = SCLContext.getCurrent();
+ SCLContext.push(context);
+ Object oldGraph = context.put(GRAPH, graph);
+ try {
+ return evaluateDB(module, function, args);
+ } finally {
+ context.put(GRAPH, oldGraph);
+ SCLContext.pop();
+ }
+ }
+
+ private static Object[] NO_ARGS = new Object[] { Tuple0.INSTANCE };
+
+ public static <T> void asyncRead(final Function f) throws DatabaseException {
+ asyncRead(f, NO_ARGS);
+ }
+
+ public static void asyncRead(final Function f, final Object ... args) throws DatabaseException {
final SCLContext context = SCLContext.createDerivedContext();
Simantics.getSession().asyncRequest(new ReadRequest() {
@Override
}
public static <T> T syncRead(final Function f) throws DatabaseException {
+ return syncRead(f, NO_ARGS);
+ }
+
+ public static <T> T syncRead(final Function f, final Object ... args) throws DatabaseException {
final SCLContext context = SCLContext.getCurrent();
Object graph = context.get(GRAPH);
if (graph != null) {
- return (T)f.apply(Tuple0.INSTANCE);
+ return (T)f.applyArray(args);
} else {
return Simantics.getSession().syncRequest(new Read<T>() {
@Override
});
}
}
-
+
public static void asyncWrite(final Function f) throws DatabaseException {
+ asyncWrite(f, NO_ARGS);
+ }
+
+ public static void asyncWrite(final Function f, final Object ... args) throws DatabaseException {
SCLContext context = SCLContext.createDerivedContext();
if (Simantics.peekSession() != null) {
Simantics.getSession().asyncRequest(new WriteRequest() {
SCLContext.push(context);
context.put(GRAPH, graph);
try {
- f.apply(Tuple0.INSTANCE);
+ f.apply(args);
} finally {
SCLContext.pop();
}
}
public static <T> T syncWrite(final Function f) throws DatabaseException {
+ return syncWrite(f, NO_ARGS);
+ }
+
+ public static <T> T syncWrite(final Function f, final Object ... args) throws DatabaseException {
final SCLContext context = SCLContext.getCurrent();
Object graph = context.get(GRAPH);
if (graph != null) {
SCLReportingHandler oldPrinter = (SCLReportingHandler)context.put(SCLReportingHandler.REPORTING_HANDLER, printer);
ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
try {
- return (T)f.apply(Tuple0.INSTANCE);
+ return (T)f.apply(args);
} finally {
context.put(GRAPH, oldGraph);
context.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
public static <T> T delayedSyncWrite(final Function f) throws DatabaseException {
final SCLContext context = SCLContext.getCurrent();
- final DataContainer<T> dc = new DataContainer<T>(null);
+ final DataContainer<T> dc = new DataContainer<T>(null);
DelayedWriteRequest request = new DelayedWriteRequest() {
@Override
public void perform(WriteGraph graph) throws DatabaseException {
- final SCLContext context = SCLContext.getCurrent();
- SCLContext.push(context);
+ final SCLContext context = SCLContext.getCurrent();
+ SCLContext.push(context);
ReadGraph oldGraph = (ReadGraph)context.put(GRAPH, graph);
try {
dc.set((T)f.apply(Tuple0.INSTANCE));
}
}
};
-
+
Object graph = context.get(GRAPH);
if (graph != null) {
if (graph instanceof WriteGraph) {
- ((WriteGraph)graph).syncRequest(request);
+ ((WriteGraph)graph).syncRequest(request);
} else {
- throw new DatabaseException("Caller is inside a read transaction.");
+ throw new DatabaseException("Caller is inside a read transaction.");
}
} else {
Simantics.getSession().syncRequest(request);
}
- return dc.get();
+ return dc.get();
}
public static <T> T virtualSyncWriteMem(WriteGraph graph, String virtualGraphId, final Function f) throws DatabaseException {
@Override
public T perform(ReadGraph graph) throws DatabaseException {
return Variables.getVariable(graph, uri).getValue(graph);
- }
+ }
});
}
@Override
public void perform(WriteGraph graph) throws DatabaseException {
Variables.getVariable(graph, uri).setValue(graph, value);
- }
+ }
});
}
public static class SCLUnaryRead extends BinaryRead<Function1<Object,Object>, Object, Object> {
- public SCLUnaryRead(Function1<Object, Object> parameter1, Object parameter2) {
- super(parameter1, parameter2);
- }
+ public SCLUnaryRead(Function1<Object, Object> parameter1, Object parameter2) {
+ super(parameter1, parameter2);
+ }
+
+ @Override
+ public Object perform(ReadGraph graph) throws DatabaseException {
+ return Simantics.applySCLRead(graph, parameter, parameter2);
+ }
- @Override
- public Object perform(ReadGraph graph) throws DatabaseException {
- return Simantics.applySCLRead(graph, parameter, parameter2);
- }
-
}
public static Object unaryQuery(ReadGraph graph, Function1<Object,Object> fn, Object value) throws DatabaseException {
- return graph.syncRequest(new SCLUnaryRead(fn, value));
+ return graph.syncRequest(new SCLUnaryRead(fn, value));
}
public static Object unaryQueryCached(ReadGraph graph, Function1<Object,Object> fn, Object value) throws DatabaseException {
- return graph.syncRequest(new SCLUnaryRead(fn, value), TransientCacheAsyncListener.<Object>instance());
+ return graph.syncRequest(new SCLUnaryRead(fn, value), TransientCacheAsyncListener.<Object>instance());
}
}
public static Object possibleFromDynamic(Type expectedType, String moduleName, Object value) {
-
+
try {
-
+
Failable<Module> failable = SCLOsgi.MODULE_REPOSITORY.getModule(moduleName);
Module module = failable.getResult();
- RuntimeEnvironment env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(
- EnvironmentSpecification.of(moduleName, ""), module.getParentClassLoader());
+ RuntimeEnvironment env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(
+ EnvironmentSpecification.of(moduleName, ""), module.getParentClassLoader());
JavaTypeTranslator tr = new JavaTypeTranslator(env.getEnvironment());
TypeDesc desc = tr.toTypeDesc(expectedType);
public static void restrictQueries(ReadGraph graph, int amount, int step, int maxTimeInMs) {
- QueryControl qc = graph.getService(QueryControl.class);
- long start = System.currentTimeMillis();
- while(true) {
- int current = qc.count();
- if(current < amount) return;
- qc.gc(graph, step);
- long duration = System.currentTimeMillis() - start;
- if(duration > maxTimeInMs) return;
- }
+ QueryControl qc = graph.getService(QueryControl.class);
+ long start = System.currentTimeMillis();
+ while(true) {
+ int current = qc.count();
+ if(current < amount) return;
+ qc.gc(graph, step);
+ long duration = System.currentTimeMillis() - start;
+ if(duration > maxTimeInMs) return;
+ }
}
public static int countQueries(ReadGraph graph) {
- QueryControl qc = graph.getService(QueryControl.class);
- return qc.count();
+ QueryControl qc = graph.getService(QueryControl.class);
+ return qc.count();
}