return System.nanoTime() - start;
}
-
}
package org.simantics.db.impl;
import org.simantics.db.AsyncReadGraph;
-import org.simantics.db.common.utils.Logger;
import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.impl.graph.AsyncBarrierImpl;
+import org.simantics.db.impl.graph.BarrierTracing;
import org.simantics.db.impl.graph.ReadGraphImpl;
+import org.simantics.db.impl.query.AsyncReadEntry;
+import org.simantics.db.impl.query.PendingTaskSupport;
import org.simantics.db.procedure.AsyncProcedure;
public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
private static final Object NO_RESULT = new Object();
- private final Object key;
- private final AsyncBarrierImpl barrier;
- private final ReadGraphImpl procedureGraph;
- private final AsyncProcedure<Result> procedure;
+ public final Object key;
+ public final ReadGraphImpl queryGraph;
+ public final ReadGraphImpl callerGraph;
+ public final AsyncProcedure<Result> procedure;
+ public PendingTaskSupport pendingTaskSupport;
+ public Object result = NO_RESULT;
+ public Throwable exception = null;
- private Object result = NO_RESULT;
- private Throwable exception = null;
+ private ReadGraphImpl queryGraph() {
+ return queryGraph;
+ }
+
+ public BlockingAsyncProcedure(ReadGraphImpl callerGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure, Object key, boolean needsToBlock) {
+
+ // A new graph for evaluating the query with correct parent and asyncBarrier
+ queryGraph = callerGraph.withParent(entry, () -> {
+
+ dispatchProcedure(queryGraph(), callerGraph, entry, procedure, needsToBlock);
+
+ });
+
+ queryGraph.asyncBarrier.inc();
- public BlockingAsyncProcedure(AsyncBarrierImpl barrier, ReadGraphImpl procedureGraph, AsyncProcedure<Result> procedure, Object key) {
this.procedure = procedure;
this.key = key;
- this.barrier = barrier;
- this.barrier.inc();
- this.procedureGraph = procedureGraph;
+ this.queryGraph.asyncBarrier.inc();
+ this.callerGraph = callerGraph;
+ if (BarrierTracing.BOOKKEEPING) {
+ BarrierTracing.registerBAP(this);
+ }
}
@Override
public void execute(AsyncReadGraph graph_, Result result) {
+
this.result = result;
- try {
- if(procedure != null) procedure.execute(procedureGraph, result);
- } catch (Throwable throwable) {
- Logger.defaultLogError("AsyncProcedure.execute threw for " + procedure, throwable);
- } finally {
- barrier.dec();
- }
+ queryGraph.asyncBarrier.dec();
+
}
@Override
public void exception(AsyncReadGraph graph_, Throwable t) {
+
this.exception = t;
- try {
- if(procedure != null) procedure.exception(procedureGraph, t);
- } catch (Throwable throwable) {
- Logger.defaultLogError("AsyncProcedure.exception threw for " + procedure, throwable);
- } finally {
- barrier.dec();
- }
+ queryGraph.asyncBarrier.dec();
+
}
-
+
public void waitBarrier() {
- barrier.waitBarrier(key, procedureGraph);
+ queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
+ }
+
+ public void dec() {
+
+ queryGraph.asyncBarrier.dec();
+
}
@SuppressWarnings("unchecked")
public Result get() throws DatabaseException {
- barrier.waitBarrier(key, procedureGraph);
+ queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
if(exception != null) {
if(exception instanceof DatabaseException) throw (DatabaseException)exception;
}
- public boolean isDone() {
- return barrier.get() == 0;
- }
-
@SuppressWarnings("unchecked")
public Result getResult() {
return (Result)result;
public String toString() {
return "." + procedure;
}
+
+ private void dispatchProcedure(ReadGraphImpl queryGraph, ReadGraphImpl parentGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure_, boolean needsToBlock) {
+
+ AsyncProcedure<Result> procedure = entry != null ? entry : procedure_;
+
+ ReadGraphImpl executeGraph = parentGraph.withParent(parentGraph.parent);
+ executeGraph.asyncBarrier.inc();
+ try {
+ if(procedure != null) {
+ procedure.execute(executeGraph, get());
+ }
+ } catch (DatabaseException e) {
+ if(procedure != null) procedure.exception(executeGraph, e);
+ exception = e;
+ } catch (Throwable t) {
+ DatabaseException dbe = new DatabaseException(t);
+ if(procedure != null) procedure.exception(executeGraph, dbe);
+ exception = dbe;
+ } finally {
+
+ if (entry != null) {
+ assert(entry.isReady());
+ // This does not throw
+ entry.performFromCache(executeGraph, procedure_);
+ }
+
+ executeGraph.asyncBarrier.dec();
+ if(needsToBlock)
+ executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
+ }
+
+ if (BarrierTracing.BOOKKEEPING) {
+ BarrierTracing.unregisterBAP(this);
+ }
+
+ }
}
import org.simantics.db.exception.RuntimeDatabaseException;
import org.simantics.db.impl.query.CacheEntry;
import org.simantics.db.impl.query.QueryProcessor.AsyncBarrier;
+import org.simantics.db.impl.query.QueryProcessor.SessionTask;
final public class AsyncBarrierImpl extends AtomicInteger implements AsyncBarrier {
private static final long serialVersionUID = 4724463372850048672L;
- static final int WAIT_TIME = 600;
+ static final int WAIT_TIME = 60000;
public static final boolean PRINT = false;
final public AsyncBarrierImpl caller;
+
+ final public Runnable callback;
- public AsyncBarrierImpl(AsyncBarrierImpl caller, CacheEntry<?> entry) {
+ public AsyncBarrierImpl(AsyncBarrierImpl caller, CacheEntry<?> entry, Runnable callback) {
super(0);
this.caller = caller;
+ this.callback = callback;
if (BarrierTracing.BOOKKEEPING) {
BarrierTracing.trace(this, entry);
}
new Exception());
}
assert (count >= 0);
+
+ if(callback != null)
+ callback.run();
+
}
}
e.printStackTrace();
}
}
- if(waitCount > WAIT_TIME*1000) {
+ if(waitCount > WAIT_TIME) {
System.err.println("AsyncBarrierImpl.waitBarrier("
+ request
synchronized (BarrierTracing.reverseLookup) {
printReverse(this, 0);
}
+ BarrierTracing.printBAPS();
+ }
+
+ for(SessionTask t : impl.processor.freeScheduling) {
+ System.err.println("Pending task:" + t);
}
// if(Development.DEVELOPMENT) {
import java.util.HashMap;
import java.util.Map;
+import org.simantics.db.impl.BlockingAsyncProcedure;
import org.simantics.db.impl.query.CacheEntry;
import org.simantics.db.impl.query.QueryProcessor.SessionTask;
public class BarrierTracing {
public static final boolean BOOKKEEPING = false;
- static final boolean RESTART_GUARD = BOOKKEEPING && false;
+ static final boolean RESTART_GUARD = BOOKKEEPING && true;
public static Map<SessionTask,Exception> tasks = new HashMap<>();
public static final HashMap<AsyncBarrierImpl, Collection<AsyncBarrierImpl>> reverseLookup = new HashMap<>();
public static final HashMap<AsyncBarrierImpl, CacheEntry<?>> entryMap = new HashMap<>();
public static final HashMap<AsyncBarrierImpl, Throwable> restartMap = new HashMap<>();
public static final HashMap<AsyncBarrierImpl, Throwable> startMap = new HashMap<>();
+ public static final HashMap<BlockingAsyncProcedure, Throwable> baps = new HashMap<>();
+ synchronized public static void registerBAP(BlockingAsyncProcedure bap) {
+ baps.put(bap, new Exception());
+ }
+
+ synchronized public static void unregisterBAP(BlockingAsyncProcedure bap) {
+ baps.remove(bap);
+ }
+
+ synchronized public static void printBAPS() {
+ for(BlockingAsyncProcedure bap : baps.keySet()) {
+ Throwable e = baps.get(bap);
+ System.err.println("BlockingAsyncProcedure");
+ System.err.println("-key: " + bap.key);
+ System.err.println("-queryGraph: " + bap.queryGraph);
+ System.err.println("-callerGraph: " + bap.callerGraph);
+ System.err.println("-procedure: " + bap.procedure);
+ System.err.println("-pendingTaskSupport: " + bap.pendingTaskSupport);
+ System.err.println("-result: " + bap.result);
+ System.err.println("-exception: " + bap.exception);
+ e.printStackTrace();
+ }
+ }
+
public static void trace(AsyncBarrierImpl barrier, CacheEntry<?> entry) {
if (RESTART_GUARD) {
public <T> T syncRequest(final Read<T> request) throws DatabaseException {
assert (request != null);
- ITask task = ThreadLogger.task(request);
+ //ITask task = ThreadLogger.task(request);
T result = (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true);
- task.finish();
+ //task.finish();
return result;
}
assert (request != null);
- ITask task = ThreadLogger.task(request);
ListenerBase listener = procedure != null ? getListenerBase(procedure) : null;
- T result = QueryCache.resultReadEntry(this, request, parent, listener, procedure);
- task.finish();
+ T result = (T)QueryCache.runnerReadEntry(this, request, parent, listener, procedure, true);
return result;
}
assert (request != null);
- ITask task = ThreadLogger.task(request);
+ //ITask task = ThreadLogger.task(request);
ListenerBase listener = getListenerBase(procedure);
T result = (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true);
- task.finish();
+ //task.finish();
return result;
}
assert (request != null);
assert (procedure != null);
-
+
+ AsyncBarrierImpl barrier = asyncBarrier;
+ if(barrier != null)
+ barrier.inc();
+
processor.scheduleNow(new SessionTask(this) {
@Override
QueryCache.runnerReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false);
} catch (DatabaseException e) {
Logger.defaultLogError(e);
+ } finally {
+ if(barrier != null)
+ barrier.dec();
}
}
assert (request != null);
assert (procedure != null);
- ITask task = ThreadLogger.task(request);
+ //ITask task = ThreadLogger.task(request);
+
+ AsyncBarrierImpl barrier = asyncBarrier;
+ if(barrier != null)
+ barrier.inc();
processor.scheduleNow(new SessionTask(this) {
@Override
public void run0(int thread) {
- try {
+
+ if(barrier != null)
+ barrier.inc();
+
+ try {
final ListenerBase listener = getListenerBase(procedure);
QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, new AsyncProcedure<T>() {
@Override
public void execute(AsyncReadGraph graph, T result) {
- task.finish();
+ //task.finish();
procedure.execute(graph, result);
+ if(barrier != null)
+ barrier.dec();
}
@Override
public void exception(AsyncReadGraph graph, Throwable throwable) {
- task.finish();
+ //task.finish();
procedure.exception(graph, throwable);
+ if(barrier != null)
+ barrier.dec();
}
}, false);
+ if(barrier != null)
+ barrier.dec();
} catch (DatabaseException e) {
Logger.defaultLogError(e);
}
this.parentGraph = parentGraph;
this.parent = parent;
this.processor = support;
- this.asyncBarrier = new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent);
+ this.asyncBarrier = new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent, null);
}
+ ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, QueryProcessor support, AsyncBarrierImpl asyncBarrier) {
+ this.parentGraph = parentGraph;
+ this.parent = parent;
+ this.processor = support;
+ this.asyncBarrier = asyncBarrier;
+ }
+
ReadGraphImpl(ReadGraphImpl graph, CacheEntry parent) {
this(graph, parent, graph.processor);
}
+ ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, Runnable callback) {
+ this(parentGraph, parent, parentGraph.processor, new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent, callback));
+ }
+
ReadGraphImpl(ReadGraphImpl graph) {
this(graph, graph.parent);
}
- public ReadGraphImpl withParent(CacheEntry parent) {
- return new ReadGraphImpl(this, parent);
+ public ReadGraphImpl withParent(CacheEntry parent, Runnable callback) {
+ return new ReadGraphImpl(this, parent, callback);
}
+ public ReadGraphImpl withParent(CacheEntry parent) {
+ return withParent(parent, null);
+ }
+
+ public ReadGraphImpl syncWithParent(CacheEntry parent) {
+ return new ReadGraphImpl(this, parent, processor, null);
+ }
+
public ReadGraphImpl forRecompute(CacheEntry parent) {
return new ReadGraphImpl(null, parent, processor);
}
public static ReadGraphImpl create(QueryProcessor support) {
- return new ReadGraphImpl(null, null, support);
+ ReadGraphImpl result = new ReadGraphImpl(null, null, support);
+ return result;
}
public ReadGraphImpl newRestart(ReadGraphImpl impl) {
else return 1 + getLevelStatic(impl.parentGraph);
}
+ public boolean isParent(ReadGraphImpl impl) {
+ if(impl == null) return false;
+ if(this == impl) return true;
+ return isParent(impl.parentGraph);
+ }
+
public ReadGraphImpl getTopLevelGraph() {
return getTopLevelGraphStatic(this);
}
*******************************************************************************/
package org.simantics.db.impl.query;
+import java.util.Collection;
+
import org.simantics.databoard.Bindings;
import org.simantics.db.AsyncReadGraph;
import org.simantics.db.DevelopmentKeys;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.impl.BlockingAsyncProcedure;
-import org.simantics.db.impl.graph.AsyncBarrierImpl;
-import org.simantics.db.impl.graph.BarrierTracing;
import org.simantics.db.impl.graph.ReadGraphImpl;
import org.simantics.db.impl.query.QueryProcessor.SessionTask;
import org.simantics.db.procedure.AsyncProcedure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final public class AsyncReadEntry<T> extends CacheEntryBase<AsyncProcedure<T>> implements AsyncProcedure<T> {
+final public class AsyncReadEntry<T> extends CacheEntryBase<AsyncProcedure<T>> implements AsyncProcedure<T>, IPending {
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncReadEntry.class);
protected AsyncRead<T> id;
+ protected PendingTaskSupport pendingTaskSupport;
AsyncReadEntry(AsyncRead<T> request) {
this.id = request;
try {
- BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure<>(graph.asyncBarrier, graph, new AsyncProcedure<T>() {
+ BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure(graph, AsyncReadEntry.this, new AsyncProcedure<T>() {
@Override
public void execute(AsyncReadGraph graph, T result) {
except(t);
}
- }, id);
-
- id.perform(graph, proc);
+ }, id, true);
+ id.perform(proc.queryGraph, proc);
+
+ proc.dec();
proc.get();
} catch (Throwable t) {
}
- public static <T> T computeForEach(ReadGraphImpl graph, AsyncRead<T> request, AsyncReadEntry<T> entry,
+ public static <T> T computeForEach(ReadGraphImpl callerGraph, AsyncRead<T> request, AsyncReadEntry<T> entry,
AsyncProcedure<T> procedure_, boolean needsToBlock) throws DatabaseException {
- AsyncProcedure<T> procedure = entry != null ? entry : procedure_;
-
- ReadGraphImpl queryGraph = graph.withParent(entry);
- queryGraph.asyncBarrier.inc();
-
- BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure<>(queryGraph.asyncBarrier, graph, null, request);
-
- class AsyncTask extends SessionTask {
-
- int counter = 0;
- T result;
- DatabaseException exception;
-
- public AsyncTask(ReadGraphImpl graph) {
- this(graph, 1);
- }
-
- public AsyncTask(ReadGraphImpl graph, int pos) {
- super(graph);
- this.position = pos;
- if(this.position < 1024)
- this.position *= 2;
- }
-
- @Override
- public void run0(int thread) {
- if(needsToBlock) proc.waitBarrier();
- if(proc.isDone()) {
- ReadGraphImpl executeGraph = graph.withParent(graph.parent);
- executeGraph.asyncBarrier.inc();
- try {
- result = (T)proc.get();
- if(procedure != null) {
- procedure.execute(executeGraph, result);
- }
- } catch (DatabaseException e) {
- if(procedure != null) procedure.exception(executeGraph, e);
- exception = e;
- } catch (Throwable t) {
- DatabaseException dbe = new DatabaseException(t);
- if(procedure != null) procedure.exception(executeGraph, dbe);
- exception = dbe;
- } finally {
- if (entry != null) {
- // This does not throw
- entry.performFromCache(executeGraph, procedure_);
- }
- executeGraph.asyncBarrier.dec();
- executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
- }
- } else {
- if(counter++ > 10000) {
- if(BarrierTracing.BOOKKEEPING) {
- AsyncBarrierImpl.printReverse(queryGraph.asyncBarrier, 2);
- AsyncBarrierImpl caller = queryGraph.asyncBarrier.caller;
- while(caller != null) {
- System.err.println("called by " + AsyncBarrierImpl.report(caller));
- caller = caller.caller;
- }
- for(AsyncBarrierImpl ab : BarrierTracing.debuggerMap.keySet()) {
- AsyncBarrierImpl.printReverse(ab, 2);
- }
- }
- throw new IllegalStateException("Eternal loop in queries.");
- }
- graph.processor.scheduleLater(new AsyncTask(graph, position));
- }
- }
-
- @Override
- public boolean maybeReady() {
- return proc.isDone();
- }
-
- }
+ BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure(callerGraph, entry, procedure_, request, needsToBlock);
try {
- request.perform(queryGraph, proc);
+ request.perform(proc.queryGraph, proc);
} finally {
- queryGraph.asyncBarrier.dec();
+ proc.queryGraph.asyncBarrier.dec();
}
- AsyncTask task = new AsyncTask(graph);
-
- if(needsToBlock) task.run(0);
- else if (proc.isDone()) task.run(0);
- else {
- graph.processor.scheduleLater(task);
+ if(needsToBlock) {
+ proc.waitBarrier();
+ return proc.get();
+ } else {
return null;
}
- if(task.exception != null) throw task.exception;
- else return task.result;
-
}
@Override
@Override
public void execute(AsyncReadGraph graph, T result) {
- setResult(result);
- setReady();
+ Collection<SessionTask> tasks = null;
+ synchronized(this) {
+ setResult(result);
+ setReady();
+ if(pendingTaskSupport != null)
+ tasks = pendingTaskSupport.executePending();
+ }
+ if(tasks != null)
+ for(SessionTask task : tasks)
+ ((ReadGraphImpl)graph).processor.scheduleNow(task);
}
@Override
- public void exception(AsyncReadGraph graph, Throwable throwable) {
- except(throwable);
+ public synchronized void exception(AsyncReadGraph graph, Throwable throwable) {
+ Collection<SessionTask> tasks = null;
+ synchronized(this) {
+ except(throwable);
+ if(pendingTaskSupport != null)
+ tasks = pendingTaskSupport.executePending();
+ }
+ if(tasks != null)
+ for(SessionTask task : tasks)
+ ((ReadGraphImpl)graph).processor.scheduleNow(task);
+ }
+
+ public void executeWhenResultIsAvailable(QueryProcessor processor, SessionTask task) {
+ boolean ready = false;
+ synchronized(this) {
+ if(pendingTaskSupport == null)
+ pendingTaskSupport = new PendingTaskSupport(this);
+ ready = pendingTaskSupport.executeWhenResultIsAvailable(task);
+ }
+ if(ready) {
+ processor.scheduleNow(task);
+ }
}
}
--- /dev/null
+package org.simantics.db.impl.query;
+
+public interface IPending {
+
+ boolean isPending();
+
+}
--- /dev/null
+package org.simantics.db.impl.query;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.simantics.db.impl.query.QueryProcessor.SessionTask;
+
+/*
+ * Support class for queuing pending tasks to be executed when result gets ready
+ */
+public class PendingTaskSupport {
+
+ private ArrayList<SessionTask> pendingTasks;
+ private IPending pending;
+
+ public PendingTaskSupport(IPending pending) {
+ this.pending = pending;
+ }
+
+ /*
+ * We assume here that the associated IPending performs this atomically
+ * The caller is responsible for execution of the returned task after the critical section
+ */
+ public boolean executeWhenResultIsAvailable(SessionTask task) {
+ if(pending.isPending()) {
+ if(pendingTasks == null)
+ pendingTasks = new ArrayList<SessionTask>();
+ pendingTasks.add(task);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /*
+ * We assume here that the associated IPending performs this atomically after changing the pending result
+ * The caller is responsible for execution of the returned task after the critical section
+ */
+ public Collection<SessionTask> executePending() {
+ ArrayList<SessionTask> ret = pendingTasks;
+ pendingTasks = null;
+ return ret;
+ }
+
+}
}
}
- ReadEntry getOrCreateReadEntry(ReadGraphImpl graph, Read<?> r, boolean needsToBlock) throws DatabaseException {
+ private final ReadEntry getOrCreateReadEntry(ReadGraphImpl graph, Read<?> r, boolean needsToBlock) throws DatabaseException {
ReadEntry existing = null;
synchronized(readEntryMap) {
existing = (ReadEntry)readEntryMap.get(r);
}
ReadEntry entry = (ReadEntry)cache.getOrCreateReadEntry(graph, r, needsToBlock);
if(entry == null) {
- graph.processor.scheduleNow(new SessionTask(graph) {
+ graph.asyncBarrier.inc();
+ graph.processor.scheduleNow(new SessionTask() {
@Override
public void run0(int thread) {
try {
runnerReadEntry(graph, r, parent, listener, procedure, needsToBlock);
+ graph.asyncBarrier.dec();
} catch (DatabaseException e) {
Logger.defaultLogError(e);
}
}
}
- AsyncReadEntry getOrCreateAsyncReadEntry(ReadGraphImpl graph, AsyncRead<?> r, boolean needsToBlock) throws DatabaseException {
+ AsyncReadEntry getOrCreateAsyncReadEntry(ReadGraphImpl graph, AsyncRead<?> r, CacheEntry parent, ListenerBase listener, final AsyncProcedure procedure, boolean needsToBlock) throws DatabaseException {
AsyncReadEntry existing = null;
synchronized(asyncReadEntryMap) {
existing = (AsyncReadEntry)asyncReadEntryMap.get(r);
}
}
if(existing.isPending()) {
- if(needsToBlock)
- waitPending(graph, existing);
- else {
- return null;
- }
+ if(needsToBlock)
+ waitPending(graph, existing);
+ else {
+ existing.executeWhenResultIsAvailable(graph.processor, new SessionTask(graph) {
+ @Override
+ public void run0(int thread) {
+ try {
+ runnerAsyncReadEntry(graph, r, parent, listener, procedure, needsToBlock);
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
+ }
+ }
+ });
+ return null;
+ }
}
return existing;
}
}
return AsyncReadEntry.computeForEach(graph, r, null, procedure, needsToBlock);
}
- AsyncReadEntry entry = (AsyncReadEntry)cache.getOrCreateAsyncReadEntry(graph, r, needsToBlock);
+ AsyncReadEntry entry = (AsyncReadEntry)cache.getOrCreateAsyncReadEntry(graph, r, parent, listener, procedure, needsToBlock);
if(entry == null) {
- graph.processor.scheduleNow(new SessionTask(graph) {
- @Override
- public void run0(int thread) {
- try {
- runnerAsyncReadEntry(graph, r, parent, listener, procedure, needsToBlock);
- } catch (DatabaseException e) {
- Logger.defaultLogError(e);
- }
- }
- });
- return null;
+ // Entry was pending and this request has been queued
+ return null;
}
AsyncProcedure procedure_ = procedure != null ? procedure : emptyProcedureAsyncReadEntry;
if(entry.isReady()) {
int counter = 0;
while(entry.isPending()) {
try {
- boolean performed = graph.performPending();
+ boolean performed = false;//graph.performPending();
if(!performed) {
Thread.sleep(1);
counter++;
return wrap.get();
}
- public static <T> T resultReadEntry(ReadGraphImpl graph, Read r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
- return (T)QueryCache.runnerReadEntry(graph, r, parent, listener, procedure, true);
- }
-
public static <T> T resultAsyncReadEntry(ReadGraphImpl graph, AsyncRead r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
return (T)QueryCache.runnerAsyncReadEntry(graph, r, parent, listener, procedure, true);
}
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
import org.simantics.databoard.Bindings;
import org.simantics.db.DevelopmentKeys;
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(QueryListening.class);
- final private QueryProcessor processor;
- private THashSet<ListenerEntry> scheduledListeners = new THashSet<ListenerEntry>();
- private boolean firingListeners = false;
- final THashMap<CacheEntry, ArrayList<ListenerEntry>> listeners = new THashMap<CacheEntry, ArrayList<ListenerEntry>>(10, 0.75f);
- private BlockingQueue<Runnable> tasks = new ArrayBlockingQueue<Runnable>(2048);
- private Map<ListenerBase,ListenerEntry> addedEntries = new HashMap<>();
-
- QueryListening(QueryProcessor processor) {
- this.processor = processor;
- new DependencyManagementThread(processor, tasks).start();
- }
-
- public void sync() {
- Semaphore s = new Semaphore(0);
- try {
- tasks.put(() -> {
- s.release();
- });
- s.acquire();
- } catch (Throwable t) {
- LOGGER.error("Error while waiting for query dependency management", t);
- }
- }
-
- static class DependencyManagementThread extends Thread {
-
- final private QueryProcessor processor;
- final BlockingQueue<Runnable> tasks;
-
- DependencyManagementThread(QueryProcessor processor, BlockingQueue<Runnable> tasks) {
- setName("Query Dependency Manager");
- this.processor = processor;
- this.tasks = tasks;
- }
-
- @Override
- public void run() {
- while(processor.isAlive()) {
- try {
- Runnable r = tasks.take();
- r.run();
- } catch (Throwable t) {
- // Spurious problems?
- LOGGER.error("Error while waiting for query dependency management tasks", t);
- }
- }
- }
-
- }
-
- public boolean hasScheduledUpdates() {
- return !scheduledListeners.isEmpty();
- }
-
- void registerDependencies(ReadGraphImpl graph, CacheEntry child, CacheEntry parent, ListenerBase listener, Object procedure, boolean inferred) {
-
- try {
- tasks.put(() -> {
-
- if (parent != null && !inferred) {
- try {
- if(!child.isImmutable(graph))
- child.addParent(parent);
- } catch (DatabaseException e) {
- LOGGER.error("Error while registering query dependencies", e);
- }
- if (Development.DEVELOPMENT) {
- if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_DEPENDENCIES, Bindings.BOOLEAN)) {
- System.out.println(child + " -> " + parent);
- }
- }
- }
-
- if (listener != null)
- registerListener(child, listener, procedure);
-
- });
- } catch (InterruptedException e) {
- LOGGER.error("Error while registering dependencies", e);
- }
-
- }
-
- void registerFirstKnown(ListenerBase base, Object result) {
-
- tasks.offer(() -> {
-
- ListenerEntry entry = addedEntries.get(base);
- if(entry != null) entry.setLastKnown(result);
-
- });
-
- }
-
- public ListenerEntry registerListener(final CacheEntry entry, final ListenerBase base, final Object procedure) {
-
- assert (entry != null);
-
- if (base.isDisposed())
- return null;
-
- return addListener(entry, base, procedure);
-
- }
-
- /*
- * Registers a listener and returns an entry iff the entry was added
- */
- private ListenerEntry addListener(CacheEntry entry, ListenerBase base, Object procedure) {
-
- assert (entry != null);
- assert (procedure != null);
-
- ArrayList<ListenerEntry> list = listeners.get(entry);
- if (list == null) {
- list = new ArrayList<>(1);
- listeners.put(entry, list);
- }
-
- ListenerEntry result = new ListenerEntry(entry, base, procedure);
- // Equals is here based on base
- int currentIndex = list.indexOf(result);
- // There was already a listener
- if(currentIndex > -1) {
- ListenerEntry current = list.get(currentIndex);
- if(!current.base.isDisposed()) return null;
- list.set(currentIndex, result);
- } else {
- list.add(result);
- }
-
- if (Development.DEVELOPMENT) {
- if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
- new Exception().printStackTrace();
- System.err.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure);
- }
- }
-
- addedEntries.put(base, result);
-
- return result;
-
- }
-
- void scheduleListener(ListenerEntry entry) {
- assert (entry != null);
- if (Development.DEVELOPMENT) {
- if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
- System.err.println("Scheduled " + entry.procedure);
- }
- }
- scheduledListeners.add(entry);
- }
-
- private void removeListener(ListenerEntry entry) {
- assert (entry != null);
- ArrayList<ListenerEntry> list = listeners.get(entry.entry);
- if(list == null) return;
- boolean success = list.remove(entry);
- assert (success);
- if (list.isEmpty())
- listeners.remove(entry.entry);
- }
-
- boolean hasListener(CacheEntry entry) {
- if(listeners.get(entry) != null) return true;
- return false;
- }
-
- boolean hasListenerAfterDisposing(CacheEntry entry) {
- if(listeners.get(entry) != null) {
- ArrayList<ListenerEntry> entries = listeners.get(entry);
- ArrayList<ListenerEntry> list = null;
- for (ListenerEntry e : entries) {
- if (e.base.isDisposed()) {
- if(list == null) list = new ArrayList<ListenerEntry>();
- list.add(e);
- }
- }
- if(list != null) {
- for (ListenerEntry e : list) {
- entries.remove(e);
- }
- }
- if (entries.isEmpty()) {
- listeners.remove(entry);
- return false;
- }
- return true;
- }
- return false;
- }
-
- List<ListenerEntry> getListenerEntries(CacheEntry entry) {
- hasListenerAfterDisposing(entry);
- if(listeners.get(entry) != null)
- return listeners.get(entry);
- else
- return Collections.emptyList();
- }
-
- void processListenerReport(CacheEntry<?> entry, Map<CacheEntry, Set<ListenerBase>> workarea) {
-
- if(!workarea.containsKey(entry)) {
-
- HashSet<ListenerBase> ls = new HashSet<ListenerBase>();
- for(ListenerEntry e : getListenerEntries(entry))
- ls.add(e.base);
-
- workarea.put(entry, ls);
-
- for(CacheEntry parent : entry.getParents(processor)) {
- processListenerReport(parent, workarea);
- ls.addAll(workarea.get(parent));
- }
-
- }
-
- }
-
- public synchronized ListenerReport getListenerReport() throws IOException {
-
- class ListenerReportImpl implements ListenerReport {
-
- Map<CacheEntry, Set<ListenerBase>> workarea = new HashMap<CacheEntry, Set<ListenerBase>>();
-
- @Override
- public void print(PrintStream b) {
- Map<ListenerBase, Integer> hist = new HashMap<ListenerBase, Integer>();
- for(Map.Entry<CacheEntry, Set<ListenerBase>> e : workarea.entrySet()) {
- for(ListenerBase l : e.getValue()) {
- Integer i = hist.get(l);
- hist.put(l, i != null ? i-1 : -1);
- }
- }
-
- for(Pair<ListenerBase, Integer> p : CollectionUtils.valueSortedEntries(hist)) {
- b.print("" + -p.second + " " + p.first + "\n");
- }
-
- b.flush();
- }
-
- }
-
- ListenerReportImpl result = new ListenerReportImpl();
-
- Collection<CacheEntryBase> all = processor.allCaches(new CacheCollectionResult()).toCollection();
- for(CacheEntryBase entry : all) {
- hasListenerAfterDisposing(entry);
- }
- for(CacheEntryBase entry : all) {
- processListenerReport(entry, result.workarea);
- }
-
- return result;
-
- }
-
- public synchronized String reportListeners(File file) throws IOException {
-
- if (!processor.isAlive())
- return "Disposed!";
-
- PrintStream b = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
- ListenerReport report = getListenerReport();
- report.print(b);
-
- return "Done reporting listeners.";
-
- }
-
- public void fireListeners(WriteGraphImpl graph) {
-
- assert (!processor.updating);
- assert (!processor.cache.collecting);
- assert (!firingListeners);
-
- firingListeners = true;
-
- try {
-
- // Performing may cause further events to be scheduled.
- while (!scheduledListeners.isEmpty()) {
-
- // Clone current events to make new entries possible during
- // firing.
- THashSet<ListenerEntry> entries = scheduledListeners;
- scheduledListeners = new THashSet<ListenerEntry>();
+ final private QueryProcessor processor;
+ private THashSet<ListenerEntry> scheduledListeners = new THashSet<ListenerEntry>();
+ private boolean firingListeners = false;
+ final THashMap<CacheEntry, ArrayList<ListenerEntry>> listeners = new THashMap<CacheEntry, ArrayList<ListenerEntry>>(10, 0.75f);
+ private EventBusImpl eventBus;
+ private Consumer<Runnable> consumer;
+ private Map<ListenerBase,ListenerEntry> addedEntries = new HashMap<>();
+
+ static class TL extends ThreadLocal<ArrayList<Runnable>> {
+
+ Map<Thread,ArrayList<Runnable>> allQueues = new HashMap<>();
+ ArrayList<ArrayList<Runnable>> dispatchedQueues = new ArrayList<>();
+
+ @Override
+ protected synchronized ArrayList<Runnable> initialValue() {
+ ArrayList<Runnable> result = new ArrayList<>();
+ allQueues.put(Thread.currentThread(), result);
+ return result;
+ }
+
+ synchronized void sendToExecution() {
+ ArrayList<Runnable> rs = allQueues.remove(Thread.currentThread());
+ dispatchedQueues.add(rs);
+ notify();
+ }
+
+ synchronized ArrayList<ArrayList<Runnable>> getDispatchedQueues() {
+ ArrayList<ArrayList<Runnable>> result = dispatchedQueues;
+ dispatchedQueues = new ArrayList<>();
+ return result;
+ }
+
+ }
+
+ static class EventBusImpl {
+
+ private static final int BUFFER_SIZE = 100;
+
+ TL queues = new TL();
+ Semaphore flush = null;
+
+ public boolean isTerminated() {
+ return false;
+ }
+
+ public Consumer<Runnable> newConsumer() {
+ return new Consumer<Runnable>() {
+
+ @Override
+ public void accept(Runnable arg0) {
+ ArrayList<Runnable> l = queues.get();
+ l.add(arg0);
+ if(l.size() == BUFFER_SIZE) {
+ queues.remove();
+ queues.sendToExecution();
+ }
+ }
+ };
+ }
+
+ public void shutdown() {
+ }
+
+ public void start(ThreadFactory arg1) {
+ arg1.newThread(new Runnable() {
+
+ @Override
+ public void run() {
+ synchronized(queues) {
+ while(!isTerminated()) {
+ try {
+ ArrayList<ArrayList<Runnable>> qs = queues.getDispatchedQueues();
+ for(ArrayList<Runnable> queue : qs) {
+ for(Runnable r : queue)
+ r.run();
+ }
+ if(flush != null) {
+ for(ArrayList<Runnable> queue : queues.allQueues.values()) {
+ for(Runnable r : queue) {
+ r.run();
+ }
+ queue.clear();
+ }
+ Semaphore s = flush;
+ flush = null;
+ s.release();
+ }
+ queues.wait(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ }).start();
+ }
+
+ void flush() {
+ synchronized(queues) {
+ flush = new Semaphore(0);
+ queues.notify();
+ }
+ try {
+ flush.acquire();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ QueryListening(QueryProcessor processor) {
+ this.processor = processor;
+ eventBus = new EventBusImpl();
+ consumer = eventBus.newConsumer();
+ eventBus.start(new ThreadFactory()
+ {
+ @Override
+ public Thread newThread(Runnable r) {
+ System.err.println("new Thread " + r);
+ return new Thread(r, "QueryDependencyManager");
+ }
+ });
+ }
+
+ public void sync() {
+ try {
+ eventBus.flush();
+ } catch (Throwable t) {
+ LOGGER.error("Error while waiting for query dependency management", t);
+ }
+ }
+
+ public boolean hasScheduledUpdates() {
+ return !scheduledListeners.isEmpty();
+ }
+
+ static class RegisterParentRunnable implements Runnable {
+
+ final CacheEntry parent;
+ final CacheEntry child;
+
+ public RegisterParentRunnable(CacheEntry parent, CacheEntry child) {
+ this.parent = parent;
+ this.child = child;
+ }
+
+ @Override
+ public void run() {
+ child.addParent(parent);
+ if (Development.DEVELOPMENT) {
+ if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_DEPENDENCIES, Bindings.BOOLEAN)) {
+ System.out.println(child + " -> " + parent);
+ }
+ }
+ }
+
+ }
+
+ static class RegisterListenerRunnable implements Runnable {
+
+ final QueryListening queryListening;
+ final ListenerBase base;
+ final Object procedure;
+ final CacheEntry parent;
+ final CacheEntry entry;
+
+ public RegisterListenerRunnable(QueryListening queryListening, ListenerBase base, Object procedure, CacheEntry parent, CacheEntry entry) {
+ this.queryListening = queryListening;
+ this.base = base;;
+ this.procedure = procedure;
+ this.parent = parent;
+ this.entry = entry;
+ }
+
+ @Override
+ public void run() {
+ queryListening.addListener(entry, base, procedure);
+ }
+
+ }
+
+ void registerDependencies(ReadGraphImpl graph, CacheEntry child, CacheEntry parent, ListenerBase listener, Object procedure, boolean inferred) {
+
+ if(inferred) {
+ assert(listener == null);
+ return;
+ }
+
+ if(parent != null) {
+ try {
+ if(!child.isImmutable(graph))
+ consumer.accept(new RegisterParentRunnable(parent, child));
+ } catch (DatabaseException e) {
+ LOGGER.error("Error while registering query dependencies", e);
+ }
+ }
+
+ if(listener != null)
+ if(!listener.isDisposed())
+ consumer.accept(new RegisterListenerRunnable(this, listener, procedure, parent, child));
+
+ }
+
+ void registerFirstKnown(ListenerBase base, Object result) {
+
+ if(base == null) return;
+
+ consumer.accept(() -> {
+ ListenerEntry entry = addedEntries.get(base);
+ if(entry != null) entry.setLastKnown(result);
+ });
+
+ }
+
+ /*
+ * Registers a listener and returns an entry iff the entry was added
+ */
+ private ListenerEntry addListener(CacheEntry entry, ListenerBase base, Object procedure) {
+
+ assert (entry != null);
+ assert (procedure != null);
+
+ ArrayList<ListenerEntry> list = listeners.get(entry);
+ if (list == null) {
+ list = new ArrayList<>(1);
+ listeners.put(entry, list);
+ }
+
+ ListenerEntry result = new ListenerEntry(entry, base, procedure);
+ // Equals is here based on base
+ int currentIndex = list.indexOf(result);
+ // There was already a listener
+ if(currentIndex > -1) {
+ ListenerEntry current = list.get(currentIndex);
+ if(!current.base.isDisposed()) return null;
+ list.set(currentIndex, result);
+ } else {
+ list.add(result);
+ }
+
+ if (Development.DEVELOPMENT) {
+ if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
+ new Exception().printStackTrace();
+ System.err.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure);
+ }
+ }
+
+ addedEntries.put(base, result);
+
+ return result;
+
+ }
+
+ void scheduleListener(ListenerEntry entry) {
+ assert (entry != null);
+ if (Development.DEVELOPMENT) {
+ if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
+ System.err.println("Scheduled " + entry.procedure);
+ }
+ }
+ scheduledListeners.add(entry);
+ }
+
+ private void removeListener(ListenerEntry entry) {
+ assert (entry != null);
+ ArrayList<ListenerEntry> list = listeners.get(entry.entry);
+ if(list == null) return;
+ boolean success = list.remove(entry);
+ assert (success);
+ if (list.isEmpty())
+ listeners.remove(entry.entry);
+ }
+
+ boolean hasListener(CacheEntry entry) {
+ if(listeners.get(entry) != null) return true;
+ return false;
+ }
+
+ boolean hasListenerAfterDisposing(CacheEntry entry) {
+ if(listeners.get(entry) != null) {
+ ArrayList<ListenerEntry> entries = listeners.get(entry);
+ ArrayList<ListenerEntry> list = null;
+ for (ListenerEntry e : entries) {
+ if (e.base.isDisposed()) {
+ if(list == null) list = new ArrayList<ListenerEntry>();
+ list.add(e);
+ }
+ }
+ if(list != null) {
+ for (ListenerEntry e : list) {
+ entries.remove(e);
+ }
+ }
+ if (entries.isEmpty()) {
+ listeners.remove(entry);
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ List<ListenerEntry> getListenerEntries(CacheEntry entry) {
+ hasListenerAfterDisposing(entry);
+ if(listeners.get(entry) != null)
+ return listeners.get(entry);
+ else
+ return Collections.emptyList();
+ }
+
+ void processListenerReport(CacheEntry<?> entry, Map<CacheEntry, Set<ListenerBase>> workarea) {
+
+ if(!workarea.containsKey(entry)) {
+
+ HashSet<ListenerBase> ls = new HashSet<ListenerBase>();
+ for(ListenerEntry e : getListenerEntries(entry))
+ ls.add(e.base);
+
+ workarea.put(entry, ls);
+
+ for(CacheEntry parent : entry.getParents(processor)) {
+ processListenerReport(parent, workarea);
+ ls.addAll(workarea.get(parent));
+ }
+
+ }
+
+ }
+
+ public synchronized ListenerReport getListenerReport() throws IOException {
+
+ class ListenerReportImpl implements ListenerReport {
+
+ Map<CacheEntry, Set<ListenerBase>> workarea = new HashMap<CacheEntry, Set<ListenerBase>>();
+
+ @Override
+ public void print(PrintStream b) {
+ Map<ListenerBase, Integer> hist = new HashMap<ListenerBase, Integer>();
+ for(Map.Entry<CacheEntry, Set<ListenerBase>> e : workarea.entrySet()) {
+ for(ListenerBase l : e.getValue()) {
+ Integer i = hist.get(l);
+ hist.put(l, i != null ? i-1 : -1);
+ }
+ }
+
+ for(Pair<ListenerBase, Integer> p : CollectionUtils.valueSortedEntries(hist)) {
+ b.print("" + -p.second + " " + p.first + "\n");
+ }
+
+ b.flush();
+ }
+
+ }
+
+ ListenerReportImpl result = new ListenerReportImpl();
+
+ Collection<CacheEntryBase> all = processor.allCaches(new CacheCollectionResult()).toCollection();
+ for(CacheEntryBase entry : all) {
+ hasListenerAfterDisposing(entry);
+ }
+ for(CacheEntryBase entry : all) {
+ processListenerReport(entry, result.workarea);
+ }
+
+ return result;
+
+ }
+
+ public synchronized String reportListeners(File file) throws IOException {
+
+ if (!processor.isAlive())
+ return "Disposed!";
+
+ PrintStream b = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
+ ListenerReport report = getListenerReport();
+ report.print(b);
+
+ return "Done reporting listeners.";
+
+ }
+
+ public void fireListeners(WriteGraphImpl graph) {
+
+ assert (!processor.updating);
+ assert (!processor.cache.collecting);
+ assert (!firingListeners);
+
+ firingListeners = true;
+
+ try {
- ArrayList<ListenerEntry> schedule = new ArrayList<ListenerEntry>();
+ // Performing may cause further events to be scheduled.
+ while (!scheduledListeners.isEmpty()) {
- for (ListenerEntry listenerEntry : entries) {
+ // Clone current events to make new entries possible during
+ // firing.
+ THashSet<ListenerEntry> entries = scheduledListeners;
+ scheduledListeners = new THashSet<ListenerEntry>();
- if (pruneListener(listenerEntry)) {
- if (Development.DEVELOPMENT) {
- if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
- new Exception().printStackTrace();
- System.err.println("Pruned " + listenerEntry.procedure);
- }
- }
- continue;
- }
+ ArrayList<ListenerEntry> schedule = new ArrayList<ListenerEntry>();
- final CacheEntry entry = listenerEntry.entry;
- assert (entry != null);
+ for (ListenerEntry listenerEntry : entries) {
- Object newValue = processor.compareTo(graph, entry, listenerEntry.getLastKnown());
+ if (pruneListener(listenerEntry)) {
+ if (Development.DEVELOPMENT) {
+ if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
+ new Exception().printStackTrace();
+ System.err.println("Pruned " + listenerEntry.procedure);
+ }
+ }
+ continue;
+ }
+
+ final CacheEntry entry = listenerEntry.entry;
+ assert (entry != null);
+
+ Object newValue = processor.compareTo(graph, entry, listenerEntry.getLastKnown());
+
+ if (newValue != ListenerEntry.NOT_CHANGED) {
+ if (Development.DEVELOPMENT) {
+ if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
+ new Exception().printStackTrace();
+ System.err.println("Add to schedule " + listenerEntry.procedure + " with " + newValue);
+ }
+ }
+ schedule.add(listenerEntry);
+ listenerEntry.setLastKnown(entry.getResult());
+ }
+
+ }
+
+ for(ListenerEntry listenerEntry : schedule) {
+ final CacheEntry entry = listenerEntry.entry;
+ if (Development.DEVELOPMENT) {
+ if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
+ System.err.println("Firing " + listenerEntry.procedure);
+ }
+ }
+ try {
+ if (Development.DEVELOPMENT) {
+ if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
+ System.err.println("Firing " + listenerEntry.procedure + " for " + listenerEntry.entry);
+ }
+ }
+ entry.performFromCache(graph, listenerEntry.procedure);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ }
+
+ } finally {
+ firingListeners = false;
+ }
+
+ }
+
+ void updateParents(int indent, CacheEntry entry, LinkedList<UpdateEntry> todo) {
+
+ Iterable<CacheEntry> oldParents = entry.getParents(processor);
+ for (CacheEntry parent : oldParents) {
+ if(!parent.isDiscarded())
+ todo.push(new UpdateEntry(entry, parent, indent + 2));
+ }
+
+ }
+
+ private boolean pruneListener(ListenerEntry entry) {
+ if (entry.base.isDisposed()) {
+ removeListener(entry);
+ return true;
+ } else {
+ return false;
+ }
+ }
- if (newValue != ListenerEntry.NOT_CHANGED) {
- if (Development.DEVELOPMENT) {
- if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
- new Exception().printStackTrace();
- System.err.println("Add to schedule " + listenerEntry.procedure + " with " + newValue);
- }
- }
- schedule.add(listenerEntry);
- listenerEntry.setLastKnown(entry.getResult());
- }
-
- }
-
- for(ListenerEntry listenerEntry : schedule) {
- final CacheEntry entry = listenerEntry.entry;
- if (Development.DEVELOPMENT) {
- if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
- System.err.println("Firing " + listenerEntry.procedure);
- }
- }
- try {
- if (Development.DEVELOPMENT) {
- if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
- System.err.println("Firing " + listenerEntry.procedure + " for " + listenerEntry.entry);
- }
- }
- entry.performFromCache(graph, listenerEntry.procedure);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
- }
-
- } finally {
- firingListeners = false;
- }
-
- }
-
- void updateParents(int indent, CacheEntry entry, LinkedList<UpdateEntry> todo) {
-
- Iterable<CacheEntry> oldParents = entry.getParents(processor);
- for (CacheEntry parent : oldParents) {
- if(!parent.isDiscarded())
- todo.push(new UpdateEntry(entry, parent, indent + 2));
- }
-
- }
-
- private boolean pruneListener(ListenerEntry entry) {
- if (entry.base.isDisposed()) {
- removeListener(entry);
- return true;
- } else {
- return false;
- }
- }
-
}
QueryThread[] executors;
public LinkedList<SessionTask> freeScheduling = new LinkedList<SessionTask>();
+
+ public LinkedList<SessionTask> topLevelTasks = new LinkedList<SessionTask>();
enum ThreadState {
public void close() {
}
- public SessionTask getSubTask(ReadGraphImpl impl) {
+ public SessionTask getSubTask(ReadGraphImpl parent) {
synchronized(querySupportLock) {
int index = 0;
while(index < freeScheduling.size()) {
SessionTask task = freeScheduling.get(index);
- if(task.hasCommonParent(task.graph, impl) && task.maybeReady()) {
- queueLength.decrementAndGet();
+ if(task.isSubtask(parent) && task.maybeReady()) {
return freeScheduling.remove(index);
}
index++;
* We are running errands while waiting for requests to complete.
* We can only run work that is part of the current root request to avoid any deadlocks
*/
- public boolean performPending(ReadGraphImpl graph) {
- SessionTask task = getSubTask(graph);
+ public boolean performPending(ReadGraphImpl under) {
+ SessionTask task = getSubTask(under);
if(task != null) {
- task.run(QueryProcessor.thread.get());
+ task.run(thread.get());
return true;
}
return false;
}
-
+
final public void scheduleNow(SessionTask request) {
- schedule(request, false);
+ SessionTask toExecute = scheduleOrReturnForExecution(request);
+ if(toExecute != null)
+ toExecute.run(thread.get());
}
- final public void scheduleLater(SessionTask request) {
- schedule(request, true);
- }
+ final public SessionTask scheduleOrReturnForExecution(SessionTask request) {
- AtomicInteger queueLength = new AtomicInteger(0);
-
- final public void schedule(SessionTask request, boolean late) {
-
- int queueLengthEstimate = queueLength.get();
- if(!late && queueLengthEstimate > 80) {
- request.run(thread.get());
- return;
- }
-
- assert(request != null);
-
- synchronized(querySupportLock) {
+ assert(request != null);
- if(BarrierTracing.BOOKKEEPING) {
- Exception current = new Exception();
- Exception previous = BarrierTracing.tasks.put(request, current);
- if(previous != null) {
- previous.printStackTrace();
- current.printStackTrace();
- }
- }
+ synchronized(querySupportLock) {
- if(late) {
- int pos = request.position - 1;
- if(pos < freeScheduling.size()) {
- freeScheduling.add(pos, request);
- queueLength.incrementAndGet();
- requests.release();
- } else {
- freeScheduling.addLast(request);
- queueLength.incrementAndGet();
- requests.release();
- }
- }
- else {
- if(request.getLevel() < 4) {
- if(freeScheduling.size() < 100) {
- freeScheduling.addFirst(request);
- queueLength.incrementAndGet();
- requests.release();
- } else {
- request.run(thread.get());
- }
- } else {
- if(freeScheduling.size() < 20) {
- freeScheduling.addFirst(request);
- queueLength.incrementAndGet();
- requests.release();
- } else {
- request.run(thread.get());
- }
- }
- }
+ LinkedList<SessionTask> queue = request.rootGraph != null ? freeScheduling : topLevelTasks;
+
+ if(BarrierTracing.BOOKKEEPING) {
+ Exception current = new Exception();
+ Exception previous = BarrierTracing.tasks.put(request, current);
+ if(previous != null) {
+ previous.printStackTrace();
+ current.printStackTrace();
+ }
+ }
+ queue.addFirst(request);
+ requests.release();
- }
+ }
- }
+ return null;
+
+ }
final int THREADS;
public static abstract class SessionTask {
- public final ReadGraphImpl graph;
+ final protected ReadGraphImpl rootGraph;
private int counter = 0;
protected int position = 1;
private Exception trace;
- public SessionTask(ReadGraphImpl graph) {
- this.graph = graph;
- if(graph != null) graph.asyncBarrier.inc();
+ public SessionTask() {
+ this(null);
}
-
- public static boolean hasCommonParent(ReadGraphImpl r1, ReadGraphImpl r2) {
- if(r1 == null || r2 == null) return false;
- return r1.getTopLevelGraph() == r2.getTopLevelGraph();
- }
+
+ public SessionTask(ReadGraphImpl rootGraph) {
+ this.rootGraph = rootGraph;
+ }
+
+ public boolean isSubtask(ReadGraphImpl graph) {
+ return graph.isParent(rootGraph);
+ }
public abstract void run0(int thread);
trace = new Exception();
}
run0(thread);
- if(graph != null) graph.asyncBarrier.dec();
+ //if(graph != null && graph.asyncBarrier != null) graph.asyncBarrier.dec();
}
public boolean maybeReady() {
@Override
public String toString() {
- if(graph == null)
+ if(rootGraph == null)
return "SessionTask[no graph]";
else
- return "SessionTask[" + graph.parent + "]";
+ return "SessionTask[" + rootGraph.parent + "]";
}
- public int getLevel() {
- if(graph == null) return 0;
- else return graph.getLevel();
- }
+// public int getLevel() {
+// if(graph == null) return 0;
+// else return graph.getLevel();
+// }
}
}
private boolean pumpTask() {
- if(!processor.freeScheduling.isEmpty()) {
- tasks.add(processor.freeScheduling.removeFirst());
- processor.queueLength.decrementAndGet();
- return true;
- }
+ // First finish existing executions
+ if(!processor.freeScheduling.isEmpty()) {
+ tasks.add(processor.freeScheduling.removeFirst());
+ return true;
+ }
+ // Check for new tasks
+ if(!processor.topLevelTasks.isEmpty()) {
+ tasks.add(processor.topLevelTasks.removeFirst());
+ return true;
+ }
return false;
}
@Override
public void run() {
- processor.thread.set(index);
-
QuerySupport support = this.querySupport;
try {
while(!tasks.isEmpty()) {
SessionTask task = tasks.remove(tasks.size()-1);
-// System.err.println("QT " + index + " runs " + task);
- task.run(index);
+ task.run(0);
}
-// for(int performer=0;performer<THREADS;performer++) {
-// if(!delayQueues[index * THREADS + performer].isEmpty()) {
-// synchronized(executors[performer]) {
-// threadLocks[performer].lock();
-// queues[performer].addAll(delayQueues[index * THREADS + performer]);
-// delayQueues[index * THREADS + performer].clear();
-// executors[performer].notify();
-// threadLocks[performer].unlock();
-// }
-// }
-// }
-
}
} catch (Throwable t) {
} finally {
executeGraph.asyncBarrier.dec();
- executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
+ if(needsToBlock)
+ executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
}
public class PropertyInfo {
public final Resource predicate;
public final String name;
+ public final boolean isImmutable;
public final boolean isHasProperty;
public final boolean isFunctional;
public final Set<String> classifications;
public final Map<String,Pair<Resource, ChildReference>> subliteralPredicates;
public final ValueAccessor valueAccessor;
public final boolean hasEnumerationRange;
- public PropertyInfo(Resource predicate, String name, boolean isFunctional, boolean isHasProperty, Set<String> classifications, VariableBuilder builder, Resource literalRange, Datatype requiredDatatype, String definedUnit, String requiredValueType, Binding defaultBinding, Map<String,Pair<Resource, ChildReference>> subliteralPredicates, ValueAccessor valueAccessor, boolean hasEnumerationRange) {
+ public PropertyInfo(Resource predicate, String name, boolean isImmutable, boolean isFunctional, boolean isHasProperty, Set<String> classifications, VariableBuilder builder, Resource literalRange, Datatype requiredDatatype, String definedUnit, String requiredValueType, Binding defaultBinding, Map<String,Pair<Resource, ChildReference>> subliteralPredicates, ValueAccessor valueAccessor, boolean hasEnumerationRange) {
this.predicate = predicate;
this.name = name;
+ this.isImmutable = isImmutable;
this.isFunctional = isFunctional;
this.isHasProperty = isHasProperty;
this.classifications = classifications;
this.hasEnumerationRange = hasEnumerationRange;
}
public static PropertyInfo make(ReadGraph graph, Resource predicate, String name, boolean isFunctional, boolean isHasProperty, Set<String> classifications, VariableBuilder builder, Resource literalRange, Datatype requiredDatatype, String definedUnit, String requiredValueType, Map<String,Pair<Resource, ChildReference>> subliteralPredicates, ValueAccessor valueAccessor, boolean hasEnumerationRange) throws DatabaseException {
-
Layer0 L0 = Layer0.getInstance(graph);
if(literalRange != null) {
Collection<Resource> dts = graph.getAssertedObjects(literalRange, L0.HasDataType);
if(requiredDatatype == null) requiredDatatype = dt;
}
}
-
Binding defaultBinding = requiredDatatype != null ? Bindings.getBinding(requiredDatatype) : null;
-
- return new PropertyInfo(predicate, name, isFunctional, isHasProperty, classifications, builder, literalRange, requiredDatatype, definedUnit, requiredValueType, defaultBinding, subliteralPredicates, valueAccessor, hasEnumerationRange);
-
+ return new PropertyInfo(predicate, name, graph.isImmutable(predicate), isFunctional, isHasProperty, classifications, builder, literalRange, requiredDatatype, definedUnit, requiredValueType, defaultBinding, subliteralPredicates, valueAccessor, hasEnumerationRange);
}
public boolean hasClassification(String classification) {
return classifications.contains(classification);
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((builder == null) ? 0 : builder.hashCode());
- result = prime * result + ((classifications == null) ? 0 : classifications.hashCode());
- result = prime * result + ((defaultBinding == null) ? 0 : defaultBinding.hashCode());
- result = prime * result + ((definedUnit == null) ? 0 : definedUnit.hashCode());
- result = prime * result + (hasEnumerationRange ? 1231 : 1237);
- result = prime * result + (isFunctional ? 1231 : 1237);
- result = prime * result + (isHasProperty ? 1231 : 1237);
- result = prime * result + ((literalRange == null) ? 0 : literalRange.hashCode());
- result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((predicate == null) ? 0 : predicate.hashCode());
- result = prime * result + ((requiredDatatype == null) ? 0 : requiredDatatype.hashCode());
- result = prime * result + ((requiredValueType == null) ? 0 : requiredValueType.hashCode());
- result = prime * result + ((subliteralPredicates == null) ? 0 : subliteralPredicates.hashCode());
- result = prime * result + ((valueAccessor == null) ? 0 : valueAccessor.hashCode());
+ if(!isImmutable) {
+ result = prime * result + ((builder == null) ? 0 : builder.hashCode());
+ result = prime * result + ((classifications == null) ? 0 : classifications.hashCode());
+ result = prime * result + ((defaultBinding == null) ? 0 : defaultBinding.hashCode());
+ result = prime * result + ((definedUnit == null) ? 0 : definedUnit.hashCode());
+ result = prime * result + (hasEnumerationRange ? 1231 : 1237);
+ result = prime * result + (isFunctional ? 1231 : 1237);
+ result = prime * result + (isHasProperty ? 1231 : 1237);
+ result = prime * result + ((literalRange == null) ? 0 : literalRange.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((requiredDatatype == null) ? 0 : requiredDatatype.hashCode());
+ result = prime * result + ((requiredValueType == null) ? 0 : requiredValueType.hashCode());
+ result = prime * result + ((subliteralPredicates == null) ? 0 : subliteralPredicates.hashCode());
+ result = prime * result + ((valueAccessor == null) ? 0 : valueAccessor.hashCode());
+ }
return result;
}
@Override
if (getClass() != obj.getClass())
return false;
PropertyInfo other = (PropertyInfo) obj;
+ if (predicate == null) {
+ if (other.predicate != null)
+ return false;
+ } else if (!predicate.equals(other.predicate))
+ return false;
+ if(isImmutable)
+ return true;
if (builder == null) {
if (other.builder != null)
return false;
return false;
} else if (!name.equals(other.name))
return false;
- if (predicate == null) {
- if (other.predicate != null)
- return false;
- } else if (!predicate.equals(other.predicate))
- return false;
if (requiredDatatype == null) {
if (other.requiredDatatype != null)
return false;
return DEFAULT_EXPECTED_EFFECT;
}
- private ExpressionEvaluator prepareEvaluator(final ReadGraph graph, final CompilationContext context, Type expectedType) throws DatabaseException {
+ protected ExpressionEvaluator prepareEvaluator(final ReadGraph graph, final CompilationContext context, Type expectedType) throws DatabaseException {
final Variable contextVariable = new Variable("context", getContextVariableType());
LocalEnvironment localEnvironment = new AbstractLocalEnvironment() {
THashMap<String,Pair<Variable,Expression>> precalculatedVariables = new THashMap<String,Pair<Variable,Expression>>();
}
@SuppressWarnings("unchecked")
- private Function1<EvaluationContext, Object> eval(ExpressionEvaluator evaluator, ReadGraph graph) throws DatabaseException {
+ protected Function1<EvaluationContext, Object> eval(ExpressionEvaluator evaluator, ReadGraph graph) throws DatabaseException {
Object oldGraph = SCLContext.getCurrent().put("graph", graph);
try {
return (Function1<EvaluationContext,Object>)evaluator.eval();
public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
private static final Logger LOGGER = LoggerFactory.getLogger(StandardGraphPropertyVariable.class);
- protected static final PropertyInfo NO_PROPERTY = new PropertyInfo(null, null,
+ protected static final PropertyInfo NO_PROPERTY = new PropertyInfo(null, null, true,
false, false, Collections.<String> emptySet(), null, null, null, null, null, null,
Collections.<String, Pair<Resource, ChildReference>> emptyMap(),
null, false);
} else {
- BlockingAsyncProcedure<T> wrap = new BlockingAsyncProcedure<T>(newGraph.asyncBarrier, newGraph, procedure, request) {
+ BlockingAsyncProcedure<T> wrap = new BlockingAsyncProcedure<T>(newGraph, null, procedure, request, true) {
public void execute(AsyncReadGraph graph_, T result) {
task.finish();
try {
request.perform(newGraph, wrap);
+ wrap.dec();
wrap.get();
} catch (DatabaseException e) {
public int getAmountOfQueryThreads() {
// This must be a power of two
- return 1;
+ return 32;
// return Integer.highestOneBit(Runtime.getRuntime().availableProcessors());
}
--- /dev/null
+/*******************************************************************************
+ * 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.diagram.adapter;
+
+import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.primitiverequest.Adapter;
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
+import org.simantics.db.procedure.AsyncProcedure;
+import org.simantics.diagram.synchronization.ErrorHandler;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.element.ElementClass;
+import org.simantics.g2d.element.IElement;
+import org.simantics.scl.runtime.tuple.Tuple3;
+
+/**
+ * @author Antti Villberg
+ */
+public class ConnectionRequest2 extends BaseRequest2<Resource, Tuple3> {
+
+ final IDiagram diagram;
+ final ErrorHandler errorHandler;
+
+ public ConnectionRequest2(ICanvasContext canvas, IDiagram diagram, Resource resource, ErrorHandler errorHandler) {
+ super(canvas, resource);
+ this.diagram = diagram;
+ this.errorHandler = errorHandler;
+ }
+
+ @Override
+ public void perform(AsyncReadGraph graph, final AsyncProcedure<Tuple3> procedure) {
+
+ graph.forHasStatement(data, new AsyncProcedure<Boolean>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ procedure.exception(graph, throwable);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, Boolean result) {
+
+ if (!result) {
+ procedure.execute(graph, null);
+ return;
+ }
+
+ graph.asyncRequest(new Adapter<ElementFactory>(data, ElementFactory.class), new TransientCacheAsyncListener<ElementFactory>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ errorHandler.error("Unexpected ElementFactory adaption failure", throwable);
+ procedure.execute(graph, null);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, final ElementFactory factory) {
+
+ graph.asyncRequest(new GetElementClassRequest(factory, data, canvas, diagram), new TransientCacheAsyncListener<ElementClass>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ errorHandler.error("Unexpected ElementClass creation failure", throwable);
+ procedure.execute(graph, null);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, final ElementClass ec) {
+
+ graph.asyncRequest(new SpawnRequest(canvas, ec, data), new TransientCacheAsyncListener<IElement>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ errorHandler.error("Unexpected SpawnRequest failure", throwable);
+ procedure.execute(graph, null);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, IElement element) {
+ procedure.execute(graph, new Tuple3(element, ec, factory));
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+}
import org.simantics.scenegraph.profile.DataNodeConstants;
import org.simantics.scenegraph.profile.DataNodeMap;
import org.simantics.scenegraph.profile.common.ProfileObserver;
+import org.simantics.scl.runtime.tuple.Tuple3;
import org.simantics.structural2.modelingRules.IModelingRules;
import org.simantics.utils.datastructures.ArrayMap;
import org.simantics.utils.datastructures.MapSet;
this.removedRouteGraphConnections.clear();
}
+ class LoadNodeListener extends DisposableListener<IElement> {
+
+ final Resource element;
+ public IElement lastLoaded;
+
+ public LoadNodeListener(ListenerSupport support, Resource element) {
+ super(support);
+ this.element = element;
+ }
+
+ @Override
+ public String toString() {
+ return "Node load listener for " + element;
+ }
+
+ public void applyFirst(IElement loaded) {
+
+ Object data = loaded.getHint(ElementHints.KEY_OBJECT);
+
+ if (addedElementMap.containsKey(data)) {
+ // This element was just loaded, in
+ // which case its hints need to
+ // uploaded to the real mapped
+ // element immediately.
+ IElement mappedElement = getMappedElement(data);
+ if (DebugPolicy.DEBUG_NODE_LISTENER)
+ System.out.println("LOADED ADDED ELEMENT, currently mapped element: " + mappedElement);
+ if (mappedElement != null && (mappedElement instanceof Element)) {
+ if (DebugPolicy.DEBUG_NODE_LISTENER) {
+ System.out.println(" mapped hints: " + mappedElement.getHints());
+ System.out.println(" loaded hints: " + loaded.getHints());
+ }
+ updateMappedElement((Element) mappedElement, loaded);
+ }
+ }
+
+ }
+
+ @Override
+ public void execute(IElement loaded) {
+
+ // Invoked when the element has been loaded.
+ if (DebugPolicy.DEBUG_NODE_LISTENER)
+ System.out.println("NODE LoadListener for " + loaded);
+
+ if (loaded == null) {
+ disposeListener();
+ return;
+ }
+
+
+ boolean first = lastLoaded == null;
+
+ lastLoaded = loaded;
+
+ /*
+ * The first invocation is postponed
+ */
+ if(first) {
+ applyFirst(loaded);
+ return;
+ }
+
+ Object data = loaded.getHint(ElementHints.KEY_OBJECT);
+
+ // Logic for disposing listener
+ if (!previousContent.nodeSet.contains(data)) {
+ if (DebugPolicy.DEBUG_NODE_LISTENER)
+ System.out.println("NODE LoadListener, node not in current content: " + data + ". Disposing.");
+ disposeListener();
+ return;
+ }
+
+ // This element was already loaded.
+ // Just schedule an update some time
+ // in the future.
+ if (DebugPolicy.DEBUG_NODE_LISTENER)
+ System.out.println("PREVIOUSLY LOADED NODE UPDATED, scheduling update into the future");
+ offerGraphUpdate( nodeUpdater(element, loaded) );
+
+ }
+
+ }
+
void processNodes(AsyncReadGraph graph) throws DatabaseException {
for (Map.Entry<Resource, Change> entry : changes.elements.entrySet()) {
@Override
public void execute(AsyncReadGraph graph, final IElement e) {
+ mapElement(element, e);
+ synchronized (GraphToDiagramUpdater.this) {
+ addedElements.add(e);
+ addedElementMap.put(element, e);
+ addedConnectionMap.put(element, e);
+ }
+
// Read connection type
graph.forSingleType(element, br.DIA.Connection, new Procedure<Resource>() {
@Override
});
} else if (content.nodeSet.contains(element)) {
- Listener<IElement> loadListener = new DisposableListener<IElement>(canvasListenerSupport) {
-
- boolean firstTime = true;
+ graph.asyncRequest(new ReadRequest() {
@Override
- public String toString() {
- return "Node load listener for " + element;
- }
- @Override
- public void execute(IElement loaded) {
- // Invoked when the element has been loaded.
- if (DebugPolicy.DEBUG_NODE_LISTENER)
- System.out.println("NODE LoadListener for " + loaded);
-
- if (loaded == null) {
- disposeListener();
- return;
- }
-
- if (firstTime) {
-
- // This is invoked before the element is actually loaded.
- //System.out.println("NodeRequestProcedure " + e);
- if (DebugPolicy.DEBUG_NODE_LOAD)
- System.out.println("MAPPING ADDED NODE: " + element + " -> " + loaded);
- mapElement(element, loaded);
- synchronized (GraphToDiagramUpdater.this) {
- addedElements.add(loaded);
- addedElementMap.put(element, loaded);
- }
-
- firstTime = false;
-
- }
-
- Object data = loaded.getHint(ElementHints.KEY_OBJECT);
+ public void run(ReadGraph graph) throws DatabaseException {
- // Logic for disposing listener
- if (!previousContent.nodeSet.contains(data)) {
- if (DebugPolicy.DEBUG_NODE_LISTENER)
- System.out.println("NODE LoadListener, node not in current content: " + data + ". Disposing.");
- disposeListener();
+ LoadNodeListener loadListener = new LoadNodeListener(canvasListenerSupport, element);
+ Tuple3 t = graph.syncRequest(new NodeRequest2(canvas, diagram, element));
+ IElement e = (IElement)t.c0;
+ ElementClass ec = (ElementClass)t.c1;
+ org.simantics.diagram.adapter.ElementFactory ef = (org.simantics.diagram.adapter.ElementFactory)t.c2;
+ if (e == null)
return;
+
+ // This is invoked before the element is actually loaded.
+ //System.out.println("NodeRequestProcedure " + e);
+ if (DebugPolicy.DEBUG_NODE_LOAD)
+ System.out.println("MAPPING ADDED NODE: " + element + " -> " + e);
+ mapElement(element, e);
+ synchronized (GraphToDiagramUpdater.this) {
+ addedElements.add(e);
+ addedElementMap.put(element, e);
}
- if (addedElementMap.containsKey(data)) {
- // This element was just loaded, in
- // which case its hints need to
- // uploaded to the real mapped
- // element immediately.
- IElement mappedElement = getMappedElement(data);
- if (DebugPolicy.DEBUG_NODE_LISTENER)
- System.out.println("LOADED ADDED ELEMENT, currently mapped element: " + mappedElement);
- if (mappedElement != null && (mappedElement instanceof Element)) {
- if (DebugPolicy.DEBUG_NODE_LISTENER) {
- System.out.println(" mapped hints: " + mappedElement.getHints());
- System.out.println(" loaded hints: " + loaded.getHints());
- }
- updateMappedElement((Element) mappedElement, loaded);
- }
- } else {
- // This element was already loaded.
- // Just schedule an update some time
- // in the future.
- if (DebugPolicy.DEBUG_NODE_LISTENER)
- System.out.println("PREVIOUSLY LOADED NODE UPDATED, scheduling update into the future");
- offerGraphUpdate( nodeUpdater(element, loaded) );
- }
- }
- };
-
- //System.out.println("NODE REQUEST: " + element);
- graph.asyncRequest(new NodeRequest(canvas, diagram, element, loadListener), new AsyncProcedure<IElement>() {
- @Override
- public void execute(AsyncReadGraph graph, IElement e) {
- }
-
- @Override
- public void exception(AsyncReadGraph graph, Throwable throwable) {
- error(throwable);
+ graph.syncRequest(new LoadRequest(canvas, diagram, ef, ec, element), loadListener);
+
}
+
});
} else {
}
}
}
+
+ class LoadRouteGraphConnectionListener extends DisposableListener<IElement> {
+
+ final Resource connection;
+ public IElement lastLoaded;
+
+ public LoadRouteGraphConnectionListener(ListenerSupport support, Resource connection) {
+ super(support);
+ this.connection = connection;
+ }
+
+ @Override
+ public String toString() {
+ return "processRouteGraphConnections " + connection;
+ }
+
+ public void applyFirst(IElement loaded) {
+
+ Object data = loaded.getHint(ElementHints.KEY_OBJECT);
+ if (addedElementMap.containsKey(data)) {
+ // This element was just loaded, in
+ // which case its hints need to
+ // uploaded to the real mapped
+ // element immediately.
+ IElement mappedElement = getMappedElement(data);
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
+ System.out.println("LOADED ADDED ROUTE GRAPH CONNECTION, currently mapped connection: " + mappedElement);
+ if (mappedElement instanceof Element) {
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER) {
+ System.out.println(" mapped hints: " + mappedElement.getHints());
+ System.out.println(" loaded hints: " + loaded.getHints());
+ }
+ updateMappedElement((Element) mappedElement, loaded);
+ }
+ }
+
+ }
+
+ @Override
+ public void execute(IElement loaded) {
+
+ // Invoked when the element has been loaded.
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
+ System.out.println("ROUTE GRAPH CONNECTION LoadListener for " + loaded);
+
+ if (loaded == null) {
+ disposeListener();
+ return;
+ }
+
+ boolean first = lastLoaded == null;
+
+ lastLoaded = loaded;
+
+ /*
+ * The first invocation is postponed
+ */
+ if(first) {
+ applyFirst(loaded);
+ return;
+ }
+
+ Object data = loaded.getHint(ElementHints.KEY_OBJECT);
+
+ // Logic for disposing listener
+ if (!previousContent.routeGraphConnectionSet.contains(data)) {
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
+ System.out.println("ROUTE GRAPH CONNECTION LoadListener, connection not in current content: " + data + ". Disposing.");
+ disposeListener();
+ return;
+ }
+
+ if (addedElementMap.containsKey(data)) {
+ // This element was just loaded, in
+ // which case its hints need to
+ // uploaded to the real mapped
+ // element immediately.
+ IElement mappedElement = getMappedElement(data);
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
+ System.out.println("LOADED ADDED ROUTE GRAPH CONNECTION, currently mapped connection: " + mappedElement);
+ if (mappedElement instanceof Element) {
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER) {
+ System.out.println(" mapped hints: " + mappedElement.getHints());
+ System.out.println(" loaded hints: " + loaded.getHints());
+ }
+ updateMappedElement((Element) mappedElement, loaded);
+ }
+ } else {
+ // This element was already loaded.
+ // Just schedule an update some time
+ // in the future.
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
+ System.out.println("PREVIOUSLY LOADED ROUTE GRAPH CONNECTION UPDATED, scheduling update into the future: " + connection);
+
+ Set<Object> dirtyNodes = new THashSet<Object>(4);
+ IElement mappedElement = getMappedElement(connection);
+ ConnectionEntity ce = mappedElement.getHint(ElementHints.KEY_CONNECTION_ENTITY);
+ if (ce != null) {
+ for (Connection conn : ce.getTerminalConnections(null)) {
+ Object o = conn.node.getHint(ElementHints.KEY_OBJECT);
+ if (o != null) {
+ dirtyNodes.add(o);
+ if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
+ System.out.println("Marked connectivity dirty for node: " + conn.node);
+ }
+ }
+ }
+
+ offerGraphUpdate( routeGraphConnectionUpdater(connection, loaded, dirtyNodes) );
+ }
+ }
+ };
- void processRouteGraphConnections(ReadGraph graph) throws DatabaseException {
+
+ void processRouteGraphConnections(AsyncReadGraph graph) throws DatabaseException {
for (Map.Entry<Resource, Change> entry : changes.routeGraphConnections.entrySet()) {
final Resource connection = entry.getKey();
if (mappedElement != null)
continue;
- Listener<IElement> loadListener = new DisposableListener<IElement>(canvasListenerSupport) {
-
- boolean firstTime = true;
+
+ graph.asyncRequest(new ReadRequest() {
@Override
- public String toString() {
- return "processRouteGraphConnections " + connection;
- }
- @Override
- public void execute(IElement loaded) {
- // Invoked when the element has been loaded.
- if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
- System.out.println("ROUTE GRAPH CONNECTION LoadListener for " + loaded);
+ public void run(ReadGraph graph) throws DatabaseException {
- if (loaded == null) {
- disposeListener();
- return;
- }
-
- if(firstTime) {
- if (DebugPolicy.DEBUG_NODE_LOAD)
- System.out.println("MAPPING ADDED ROUTE GRAPH CONNECTION: " + connection + " -> " + loaded);
- mapElement(connection, loaded);
- synchronized (GraphToDiagramUpdater.this) {
- addedElements.add(loaded);
- addedElementMap.put(connection, loaded);
- addedRouteGraphConnectionMap.put(connection, loaded);
- }
- firstTime = false;
- }
+ LoadRouteGraphConnectionListener loadListener = new LoadRouteGraphConnectionListener(canvasListenerSupport, connection);
- Object data = loaded.getHint(ElementHints.KEY_OBJECT);
+ Tuple3 t = graph.syncRequest(new ConnectionRequest2(canvas, diagram, connection, errorHandler));
+ IElement e = (IElement)t.c0;
+ ElementClass ec = (ElementClass)t.c1;
+ org.simantics.diagram.adapter.ElementFactory ef = (org.simantics.diagram.adapter.ElementFactory)t.c2;
- // Logic for disposing listener
- if (!previousContent.routeGraphConnectionSet.contains(data)) {
- if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
- System.out.println("ROUTE GRAPH CONNECTION LoadListener, connection not in current content: " + data + ". Disposing.");
- disposeListener();
+ if (e == null)
return;
+
+ //System.out.println("ConnectionRequestProcedure " + e);
+ if (DebugPolicy.DEBUG_NODE_LOAD)
+ System.out.println("MAPPING ADDED ROUTE GRAPH CONNECTION: " + connection + " -> " + e);
+ mapElement(connection, e);
+ synchronized (GraphToDiagramUpdater.this) {
+ addedElements.add(e);
+ addedElementMap.put(connection, e);
+ addedRouteGraphConnectionMap.put(connection, e);
}
- if (addedElementMap.containsKey(data)) {
- // This element was just loaded, in
- // which case its hints need to
- // uploaded to the real mapped
- // element immediately.
- IElement mappedElement = getMappedElement(data);
- if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
- System.out.println("LOADED ADDED ROUTE GRAPH CONNECTION, currently mapped connection: " + mappedElement);
- if (mappedElement instanceof Element) {
- if (DebugPolicy.DEBUG_CONNECTION_LISTENER) {
- System.out.println(" mapped hints: " + mappedElement.getHints());
- System.out.println(" loaded hints: " + loaded.getHints());
- }
- updateMappedElement((Element) mappedElement, loaded);
- }
- } else {
- // This element was already loaded.
- // Just schedule an update some time
- // in the future.
- if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
- System.out.println("PREVIOUSLY LOADED ROUTE GRAPH CONNECTION UPDATED, scheduling update into the future: " + connection);
-
- Set<Object> dirtyNodes = new THashSet<Object>(4);
- IElement mappedElement = getMappedElement(connection);
- ConnectionEntity ce = mappedElement.getHint(ElementHints.KEY_CONNECTION_ENTITY);
- if (ce != null) {
- for (Connection conn : ce.getTerminalConnections(null)) {
- Object o = conn.node.getHint(ElementHints.KEY_OBJECT);
- if (o != null) {
- dirtyNodes.add(o);
- if (DebugPolicy.DEBUG_CONNECTION_LISTENER)
- System.out.println("Marked connectivity dirty for node: " + conn.node);
- }
- }
- }
+ graph.syncRequest(new LoadRequest(canvas, diagram, ef, ec, connection), loadListener);
- offerGraphUpdate( routeGraphConnectionUpdater(connection, loaded, dirtyNodes) );
- }
}
- };
- graph.syncRequest(new ConnectionRequest(canvas, diagram, connection, errorHandler, loadListener), new Procedure<IElement>() {
- @Override
- public void execute(final IElement e) {
- }
- @Override
- public void exception(Throwable throwable) {
- error(throwable);
- }
});
+
+
break;
}
case REMOVED: {
Listener<IElement> loadListener = new DisposableListener<IElement>(canvasListenerSupport) {
- boolean firstTime = true;
-
@Override
public String toString() {
return "processBranchPoints for " + element;
return;
}
- if (firstTime) {
-
- mapElement(element, loaded);
- synchronized (GraphToDiagramUpdater.this) {
- addedBranchPoints.add(loaded);
- addedElementMap.put(element, loaded);
- ConnectionEntityImpl ce = getConnectionEntity(element);
- loaded.setHint(ElementHints.KEY_CONNECTION_ENTITY, ce);
- loaded.setHint(ElementHints.KEY_PARENT_ELEMENT, ce.getConnectionElement());
- }
-
- firstTime = false;
-
- }
-
Object data = loaded.getHint(ElementHints.KEY_OBJECT);
if (addedElementMap.containsKey(data)) {
// This element was just loaded, in
return "processBranchPoints";
}
});
+
}
//System.out.println("---- PROCESS BRANCH POINTS END");
task = Timing.BEGIN("processRouteGraphConnections");
if (!changes.routeGraphConnections.isEmpty()) {
- graph.syncRequest(new ReadRequest() {
+ graph.syncRequest(new AsyncReadRequest() {
@Override
- public void run(ReadGraph graph) throws DatabaseException {
+ public void run(AsyncReadGraph graph) throws DatabaseException {
processRouteGraphConnections(graph);
}
@Override
diagramUpdateLock.lock();
try {
- if (DebugPolicy.DEBUG_DIAGRAM_UPDATE)
+ if (DebugPolicy.DEBUG_DIAGRAM_UPDATE) {
System.out.println("In diagramGraphUpdater:");
+ System.out.println("-content = " + content);
+ System.out.println("-previousContent = " + previousContent);
+ }
// Find out what has changed since the last query.
Object task = Timing.BEGIN("diagramContentDifference");
--- /dev/null
+/*******************************************************************************
+ * 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.diagram.adapter;
+
+import java.util.List;
+
+import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.primitiverequest.Adapter;
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
+import org.simantics.db.procedure.AsyncProcedure;
+import org.simantics.db.procedure.Listener;
+import org.simantics.diagram.synchronization.ErrorHandler;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.handler.SubstituteElementClass;
+import org.simantics.g2d.element.ElementClass;
+import org.simantics.g2d.element.IElement;
+import org.simantics.scl.runtime.tuple.Tuple3;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Antti Villberg
+ */
+public class NodeRequest2 extends BaseRequest2<Resource, Tuple3> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NodeRequest2.class);
+
+ final IDiagram diagram;
+
+ public NodeRequest2(ICanvasContext canvas, IDiagram diagram, Resource resource) {
+ super(canvas, resource);
+ this.diagram = diagram;
+ }
+
+ @Override
+ public void perform(AsyncReadGraph graph, final AsyncProcedure<Tuple3> procedure) {
+ // Keep this code from crashing the whole DB client by unexpected
+ // throwing of NPE's somewhere in the following code that leads to
+ // procedure not getting called properly.
+ if (diagram == null) {
+ procedure.exception(graph, new NullPointerException("null diagram specified for resource " + data));
+ return;
+ }
+
+ final ErrorHandler eh = ElementFactoryUtil.getErrorHandler(diagram);
+
+ graph.forHasStatement(data, new AsyncProcedure<Boolean>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ eh.error("NodeRequest.forHasStatement failed", throwable);
+ procedure.execute(graph, null);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, Boolean result) {
+
+ if(!result) {
+ procedure.execute(graph, null);
+ return;
+ }
+
+ graph.asyncRequest(new Adapter<ElementFactory>(data, ElementFactory.class), new TransientCacheAsyncListener<ElementFactory>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ eh.error("NodeRequest.asyncRequest(Adapter<ElementFactory>) failed", throwable);
+ procedure.execute(graph, null);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, final ElementFactory factory) {
+
+ graph.asyncRequest(new GetElementClassRequest(factory, data, canvas, diagram), new TransientCacheAsyncListener<ElementClass>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ LOGGER.error("Unexpected error in GetElementClassRequest", throwable);
+ procedure.execute(graph, null);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, ElementClass mutableClazz) {
+ List<SubstituteElementClass> substitutes = diagram.getDiagramClass().getItemsByClass(SubstituteElementClass.class);
+ for (SubstituteElementClass subs : substitutes) {
+ mutableClazz = subs.substitute(diagram, mutableClazz);
+ }
+ final ElementClass clazz = mutableClazz;
+ graph.asyncRequest(new SpawnRequest(canvas, clazz, data), new TransientCacheAsyncListener<IElement>() {
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ LOGGER.error("Unexpected error in SpawnRequest", throwable);
+ procedure.execute(graph, null);
+ }
+
+ @Override
+ public void execute(AsyncReadGraph graph, IElement element) {
+ procedure.execute(graph, new Tuple3(element, clazz, factory));
+ }
+
+ });
+
+ }
+
+ });
+
+ }
+
+ });
+
+ }
+
+ });
+
+ }
+
+}
for(int i=0;i<res.length;i++) {
if(pos > 0) json.append(",");
Object r = res[i];
- if(r instanceof IdentifiedObject) {
- Object id = ((IdentifiedObject) r).getId();
+ if(r instanceof IIdentifiedObject) {
+ Object id = ((IIdentifiedObject) r).getId();
if(id instanceof IAdaptable) {
Object resource = ((IAdaptable) id).getAdapter(Resource.class);
if(resource != null) {
import java.util.List;
import java.util.Set;
+import org.simantics.db.AsyncReadGraph;
import org.simantics.db.ReadGraph;
import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
+import org.simantics.db.common.request.AsyncReadRequest;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.request.VariableRead;
import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.procedure.AsyncProcedure;
import org.simantics.document.server.JSONObject;
public class DocumentRequest extends VariableRead<List<JSONObject>> {
- public static boolean PROFILE = false;
+ public static boolean PROFILE = true;
// Thresholds in microseconds
public static int PROFILE_THRESHOLD_NODEREQUEST = 2000;
public static int PROFILE_THRESHOLD_VALUEREQUEST = 500;
if(nodes.isEmpty()) {
return Collections.emptyList();
}
-
-
- /*TreeMap<String, Variable> nodeMap = new TreeMap<String, Variable>();
-
- for (Variable node : nodes) {
- nodeMap.put(node.getURI(graph), node);
+
+ if(PROFILE) {
+ long dura = System.nanoTime()-s;
+ System.err.println("DocumentRequest1 " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
}
- System.out.println("*************************************************************************");
- for (Variable node : nodeMap.values()) {
- System.out.println(" " + node.getURI(graph));
- }*/
-
- for(Variable node : nodes) {
- rs.add(graph.syncRequest(new NodeRequest(node), TransientCacheAsyncListener.<JSONObject>instance()));
+
+ graph.syncRequest(new AsyncReadRequest() {
+
+ @Override
+ public void run(AsyncReadGraph graph) throws DatabaseException {
+
+ for(Variable node : nodes) {
+ graph.asyncRequest(new NodeRequest(node), new AsyncProcedure<JSONObject> () {
+
+ @Override
+ public void execute(AsyncReadGraph graph, JSONObject result) {
+ synchronized (rs) {
+ rs.add(result);
+ }
+ }
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ }
+
+ });
+
+ }
+
+ }
+
+ });
+
+
+ if(PROFILE) {
+ long dura = System.nanoTime()-s;
+ System.err.println("DocumentRequest2 " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
}
ArrayList<JSONObject> result = new ArrayList<JSONObject>(rs);
if(PROFILE) {
long dura = System.nanoTime()-s;
- System.err.println("DocumentRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
+ System.err.println("DocumentRequest3 " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
}
return result;
import org.simantics.db.layer0.request.VariableRead;
import org.simantics.db.layer0.variable.Variable;
import org.simantics.document.server.DocumentServerUtils.AttributesRequest;
+import org.simantics.utils.threads.logger.ITask;
+import org.simantics.utils.threads.logger.ThreadLogger;
import org.simantics.document.server.JSONObject;
public class NodeRequest extends VariableRead<JSONObject> {
@Override
public JSONObject perform(ReadGraph graph) throws DatabaseException {
- long s = DocumentRequest.PROFILE ? System.nanoTime() : 0L;
- JSONObject staticContent = graph.syncRequest(new AttributesRequest(variable));
+ ITask task = DocumentRequest.PROFILE ? ThreadLogger.task(this) : null;
- if (DocumentRequest.PROFILE) {
- long dura = System.nanoTime()-s;
- if (dura > DocumentRequest.PROFILE_THRESHOLD_NODEREQUEST * 1e3) {
- System.err.println("NodeRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
- }
- }
+ JSONObject staticContent = graph.syncRequest(new AttributesRequest(variable));
+ if(DocumentRequest.PROFILE) task.finish();
+
return staticContent;
}
package org.simantics.document.server.request;
-import gnu.trove.set.hash.THashSet;
-
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
+import org.simantics.db.AsyncReadGraph;
import org.simantics.db.ReadGraph;
+import org.simantics.db.common.request.AsyncReadRequest;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.request.VariableChildren;
import org.simantics.db.layer0.request.VariableRead;
import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.procedure.AsyncProcedure;
import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.utils.threads.logger.ITask;
+import org.simantics.utils.threads.logger.ThreadLogger;
+
+import gnu.trove.set.hash.THashSet;
public class NodesRequest extends VariableRead<Set<Variable>> {
public NodesRequest(Variable var) {
super(var);
- }
-
- @Override
- public Set<Variable> perform(ReadGraph graph) throws DatabaseException {
-
- long s = System.nanoTime();
-
- StructuralResource2.getInstance(graph);
- if(variable == null)
- return Collections.emptySet();
-
- Set<Variable> nodes = new THashSet<Variable>();
- Collection<Variable> children = graph.syncRequest(new VariableChildren(variable));
- for(Variable child : children) {
- Set<Variable> childNodes = graph.syncRequest(new NodesRequest2(child));
- nodes.addAll(childNodes);
- }
-
- if(DocumentRequest.PROFILE) {
- long dura = System.nanoTime()-s;
- System.err.println("NodesRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
- }
-
- return nodes;
-
- }
+ }
+
+ @Override
+ public Set<Variable> perform(ReadGraph graph) throws DatabaseException {
+
+ ITask task = DocumentRequest.PROFILE ? ThreadLogger.task(this) : null;
+
+ StructuralResource2.getInstance(graph);
+ if(variable == null)
+ return Collections.emptySet();
+
+ Set<Variable> nodes = new THashSet<Variable>();
+
+ Collection<Variable> children = graph.syncRequest(new VariableChildren(variable));
+
+ graph.syncRequest(new AsyncReadRequest() {
+
+ @Override
+ public void run(AsyncReadGraph graph) throws DatabaseException {
+
+ for(Variable child : children) {
+ graph.asyncRequest(new NodesRequest2(child), new AsyncProcedure<Set<Variable>>() {
+
+ @Override
+ public void execute(AsyncReadGraph graph, Set<Variable> result) {
+ synchronized(nodes) {
+ nodes.addAll(result);
+ }
+ }
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ }
+
+ });
+ }
+
+ }
+
+ });
+
+ if(DocumentRequest.PROFILE) task.finish();
+
+ return nodes;
+
+ }
}
\ No newline at end of file
import gnu.trove.set.hash.THashSet;
+import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.simantics.databoard.Bindings;
+import org.simantics.db.AsyncReadGraph;
import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
+import org.simantics.db.common.request.AsyncReadRequest;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.VariableChildren;
import org.simantics.db.layer0.request.VariableRead;
import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.procedure.AsyncProcedure;
import org.simantics.document.base.ontology.DocumentationResource;
+import org.simantics.utils.threads.logger.ITask;
+import org.simantics.utils.threads.logger.ThreadLogger;
public class NodesRequest2 extends VariableRead<Set<Variable>> {
public NodesRequest2(Variable var) {
super(var);
- }
-
- @Override
- public Set<Variable> perform(ReadGraph graph) throws DatabaseException {
-
- DocumentationResource DOC = DocumentationResource.getInstance(graph);
-
- Resource type = variable.getPossibleType(graph);
- if(type == null) return Collections.emptySet();
-
- if(!graph.isInheritedFrom(type, DOC.Components_Component)) return Collections.emptySet();
-
- Boolean pathExists = variable.getPossiblePropertyValue(graph, DOC.Properties_pathExists, Bindings.BOOLEAN);
- if(pathExists != null && !pathExists) return Collections.emptySet();
-
- if(graph.isInheritedFrom(type, DOC.Components_PrimitiveComponent)) {
- return Collections.singleton(variable);
- } else {
- Set<Variable> result = new THashSet<Variable>();
- for(Variable child : variable.getChildren(graph)) {
- Set<Variable> nodes = graph.syncRequest(new NodesRequest2(child));
- result.addAll(nodes);
- }
-
- return result;
- }
-
- }
+ }
+
+ @Override
+ public Set<Variable> perform(ReadGraph graph) throws DatabaseException {
+
+ ITask task = DocumentRequest.PROFILE ? ThreadLogger.task(this) : null;
+
+ DocumentationResource DOC = DocumentationResource.getInstance(graph);
+
+ Resource type = variable.getPossibleType(graph);
+ if(type == null) {
+ if(DocumentRequest.PROFILE) task.finish();
+ return Collections.emptySet();
+ }
+
+ if(!graph.isInheritedFrom(type, DOC.Components_Component)) {
+ if(DocumentRequest.PROFILE) task.finish();
+ return Collections.emptySet();
+ }
+
+ Boolean pathExists = variable.getPossiblePropertyValue(graph, DOC.Properties_pathExists, Bindings.BOOLEAN);
+ if(pathExists != null && !pathExists) {
+ if(DocumentRequest.PROFILE) task.finish();
+ return Collections.emptySet();
+ }
+
+ if(graph.isInheritedFrom(type, DOC.Components_PrimitiveComponent)) {
+ if(DocumentRequest.PROFILE) task.finish();
+ return Collections.singleton(variable);
+ } else {
+ Set<Variable> result = new THashSet<Variable>();
+ Collection<Variable> children = graph.syncRequest(new VariableChildren(variable));
+ graph.syncRequest(new AsyncReadRequest() {
+
+ @Override
+ public void run(AsyncReadGraph graph) throws DatabaseException {
+
+ for(Variable child : children) {
+ graph.asyncRequest(new NodesRequest2(child), new AsyncProcedure<Set<Variable>>() {
+
+ @Override
+ public void execute(AsyncReadGraph graph, Set<Variable> vars) {
+ synchronized(result) {
+ result.addAll(vars);
+ }
+ }
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ }
+
+ });
+ }
+
+ }
+
+ });
+
+ if(DocumentRequest.PROFILE) task.finish();
+ return result;
+
+ }
+
+ }
}
\ No newline at end of file
package org.simantics.document.server.request;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.simantics.db.Resource;
import org.simantics.db.common.procedure.adapter.TransientCacheListener;
import org.simantics.db.common.request.IndexRoot;
-import org.simantics.db.common.request.PossibleTypedParent;
import org.simantics.db.common.request.UnaryRead;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
-import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;
import org.simantics.db.layer0.variable.Variable;
-import org.simantics.document.base.ontology.DocumentationResource;
-import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext;
import org.simantics.layer0.Layer0;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EConstant;
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.kinds.Kinds;
+import org.simantics.scl.compiler.types.util.MultiFunction;
import org.simantics.scl.runtime.SCLContext;
import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.FunctionImpl1;
import org.simantics.structural2.scl.ComponentTypeProperty;
import org.simantics.structural2.scl.FindPossibleComponentTypeRequest;
import org.simantics.structural2.scl.ReadComponentTypeInterfaceRequest;
import org.simantics.utils.datastructures.Pair;
-public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Object> {
-
- private final Pair<Resource,Resource> componentTypeAndRoot;
- private final Resource literal;
- protected String possibleExpectedValueType;
-
- public static class CompilationContext extends AbstractExpressionCompilationContext {
- public final Map<String, ComponentTypeProperty> propertyMap;
-
- public CompilationContext(RuntimeEnvironment runtimeEnvironment,
- Map<String, ComponentTypeProperty> propertyMap) {
- super(runtimeEnvironment);
- this.propertyMap = propertyMap;
- }
- }
-
- private ServerSCLHandlerValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
- assert(literal != null);
- this.literal = literal;
- this.componentTypeAndRoot = componentTypeAndRoot;
- this.possibleExpectedValueType = possibleExpectedValueType;
- }
-
- public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
- this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
- }
-
- public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
- this(getComponentTypeAndRoot(graph, s, o), o, resolveExpectedValueType(graph, p));
- }
-
- private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property) throws DatabaseException {
- Variable parent = property.getParent(graph);
- Resource represents = parent.getRepresents(graph);
- if(represents != null) {
- Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents));
- if(type != null) {
- Resource root = graph.syncRequest(new IndexRoot(type));
- return Pair.make(type, root);
- }
- }
- parent = parent.getParent(graph);
- Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));
- return Pair.make(parent.getType(graph), root);
- }
-
- private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component, Resource literal) throws DatabaseException {
- if(component != null) {
- Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
- if(type != null) {
- Resource root = graph.syncRequest(new IndexRoot(type));
- return Pair.make(type, root);
- } else {
- Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
- Resource componentType = graph.getSingleType(doc);
- Resource root = graph.syncRequest(new IndexRoot(doc));
- return Pair.make(componentType, root);
- }
- // TODO: For Antti to consider and fix later
- // Introduced to handle procedural user components where component == null
- } else if (literal != null) {
- Resource root = graph.syncRequest(new IndexRoot(literal));
- return Pair.make(null, root);
- } else {
- throw new DatabaseException("Couldn't resolve component type and root for component == null && literal == null");
- }
- //throw new IllegalStateException();
- }
+public class ServerSCLHandlerValueRequest extends ServerSCLValueRequestBase<org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext> {
+
+ private final Pair<Resource,Resource> componentTypeAndRoot;
+ private final Resource literal;
+ protected String possibleExpectedValueType;
+
+ public static class CompilationContext extends AbstractExpressionCompilationContext {
+ public final Map<String, ComponentTypeProperty> propertyMap;
+
+ public CompilationContext(RuntimeEnvironment runtimeEnvironment,
+ Map<String, ComponentTypeProperty> propertyMap) {
+ super(runtimeEnvironment);
+ this.propertyMap = propertyMap;
+ }
+ }
+
+ private ServerSCLHandlerValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
+ assert(literal != null);
+ this.literal = literal;
+ this.componentTypeAndRoot = componentTypeAndRoot;
+ this.possibleExpectedValueType = possibleExpectedValueType;
+ }
+
+ public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
+ this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
+ }
+
+ public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+ this(getComponentTypeAndRoot(graph, s, o), o, resolveExpectedValueType(graph, p));
+ }
+
+ private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property) throws DatabaseException {
+ Variable parent = property.getParent(graph);
+ Resource represents = parent.getRepresents(graph);
+ if(represents != null) {
+ Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents));
+ if(type != null) {
+ Resource root = graph.syncRequest(new IndexRoot(type));
+ return Pair.make(type, root);
+ }
+ }
+ parent = parent.getParent(graph);
+ Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));
+ return Pair.make(parent.getType(graph), root);
+ }
+
public static List<TCon> getEffects(ReadGraph graph, Variable context) throws DatabaseException {
+ HandlerFn fn = (HandlerFn)compile(graph, context);
+ return fn.effects;
+ }
+
+ public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.get("graph");
try {
- ServerSCLHandlerValueRequest req = new ServerSCLHandlerValueRequest(graph, context);
- return req.getExpressionEffects(graph);
+ Function1<Object,Object> exp = graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context),
+ TransientCacheListener.instance());
+ sclContext.put("graph", graph);
+ return exp.apply(context);
} catch (DatabaseException e) {
throw (DatabaseException)e;
} catch (Throwable t) {
throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
}
}
- public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.get("graph");
- try {
- Function1<Object,Object> exp = graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context),
- TransientCacheListener.instance());
- sclContext.put("graph", graph);
- return exp.apply(context);
- } catch (DatabaseException e) {
- throw (DatabaseException)e;
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
- }
-
- public static Function1<Object, Object> compile(ReadGraph graph, Variable context) throws DatabaseException {
- return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.instance());
- }
-
- public static Function1<Object, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
- return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, s, o, p), TransientCacheListener.<Function1<Object,Object>>instance());
- }
-
- @Override
- protected String getExpressionText(ReadGraph graph)
- throws DatabaseException {
- Layer0 L0 = Layer0.getInstance(graph);
- String exp = graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);
- return "\\context -> " + exp;
- }
-
- protected RuntimeEnvironmentRequest2 getRuntimeEnvironmentRequest(Resource componentType, Resource indexRoot) {
- return new RuntimeEnvironmentRequest2(componentType, indexRoot) {
- @Override
- protected void fillEnvironmentSpecification(
- EnvironmentSpecification environmentSpecification) {
- }
- };
- }
-
- @Override
- protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {
- return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {
- @Override
- public CompilationContext perform(ReadGraph graph) throws DatabaseException {
- RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
+ public static Function1<Object, Object> compile(ReadGraph graph, Variable context) throws DatabaseException {
+ return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.instance());
+ }
+
+ public static Function1<Object, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+ return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, s, o, p), TransientCacheListener.instance());
+ }
+
+ public static class HandlerFn extends FunctionImpl1<Object,Object> {
+
+ Function1<Object,Object> handler;
+ ArrayList<TCon> effects;
+
+ HandlerFn(Function1<Object,Object> handler, Type type) {
+ try {
+ this.handler = handler;
+ this.effects = new ArrayList<TCon>();
+ MultiFunction mfun = Types.matchFunction(type, 1);
+ mfun.effect.collectConcreteEffects(this.effects);
+ } catch(MatchException e) {
+ // Should not happen!
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Object apply(Object p0) {
+ return handler.apply(p0);
+ }
+
+ }
+
+ @Override
+ public Function1<Object, Object> perform(ReadGraph graph) throws DatabaseException {
+
+ CompilationContext context = getCompilationContext(graph);
+ Type expectedType = getExpectedType(graph, context);
+ Function1<Object,Object> handler = eval(prepareEvaluator(graph, context, expectedType), graph);
+ return new HandlerFn(handler, expectedType);
+
+ }
+
+ @Override
+ protected String getExpressionText(ReadGraph graph)
+ throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ String exp = graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);
+ return "\\context -> " + exp;
+ }
+
+ protected RuntimeEnvironmentRequest2 getRuntimeEnvironmentRequest(Resource componentType, Resource indexRoot) {
+ return new RuntimeEnvironmentRequest2(componentType, indexRoot) {
+ @Override
+ protected void fillEnvironmentSpecification(
+ EnvironmentSpecification environmentSpecification) {
+ }
+ };
+ }
+
+ @Override
+ protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {
+ return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {
+ @Override
+ public CompilationContext perform(ReadGraph graph) throws DatabaseException {
+ RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
Map<String, ComponentTypeProperty> propertyMap;
if (parameter.first != null) {
propertyMap =
- graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
- TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
+ graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
+ TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
} else {
// TODO: Antti to consider
// To handle procedural user components
// Map<String, ComponentTypeProperty> propertyMap =
// graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
// TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
- return new CompilationContext(runtimeEnvironment, propertyMap);
- }
- });
- }
-
- @Override
- protected Type getContextVariableType() {
- return VARIABLE;
- }
-
- private static Expression accessInputVariable(Environment environment,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) {
- SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT);
- return new EApply(new EConstant(variableParentFunction),
- new EApply(new EConstant(variableParentFunction),
- new EVariable(contextVariable)));
- }
-
- protected static Expression standardGetProperty(
- Environment environment,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
- String name,
- Type type) {
- return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type);
- }
-
- @Override
- protected Expression getVariableAccessExpression(
- ReadGraph graph,
- CompilationContext context,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
- String name) throws DatabaseException {
- ComponentTypeProperty property = context.propertyMap.get(name);
- if(property != null)
- return standardGetProperty(
- context.runtimeEnvironment.getEnvironment(),
- contextVariable,
- name,
- property.type == null ? Types.metaVar(Kinds.STAR) : property.type);
- else {
-
+ return new CompilationContext(runtimeEnvironment, propertyMap);
+ }
+ });
+ }
+
+ @Override
+ protected Type getContextVariableType() {
+ return VARIABLE;
+ }
+
+ private static Expression accessInputVariable(Environment environment,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) {
+ SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT);
+ return new EApply(new EConstant(variableParentFunction),
+ new EApply(new EConstant(variableParentFunction),
+ new EVariable(contextVariable)));
+ }
+
+ protected static Expression standardGetProperty(
+ Environment environment,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
+ String name,
+ Type type) {
+ return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type);
+ }
+
+ @Override
+ protected Expression getVariableAccessExpression(
+ ReadGraph graph,
+ CompilationContext context,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
+ String name) throws DatabaseException {
+ ComponentTypeProperty property = context.propertyMap.get(name);
+ if(property != null)
+ return standardGetProperty(
+ context.runtimeEnvironment.getEnvironment(),
+ contextVariable,
+ name,
+ property.type == null ? Types.metaVar(Kinds.STAR) : property.type);
+ else {
+
// if(context.propertyMap.containsKey(name)) {
//
// org.simantics.scl.compiler.elaboration.expressions.Variable parametersVariable = new org.simantics.scl.compiler.elaboration.expressions.Variable("context", COMMAND_CONTEXT);
// new ELiteral(new StringConstant(name)));
//
// }
-
- return getSpecialVariableAccessExpression(graph, context, contextVariable, name);
-
- }
- }
-
- protected Expression getSpecialVariableAccessExpression(ReadGraph graph,
- CompilationContext context,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
- String name) throws DatabaseException {
- if(name.equals("input")) {
- Environment environment = context.runtimeEnvironment.getEnvironment();
- return accessInputVariable(environment, contextVariable);
- } else if(name.equals("self"))
- return new EVariable(contextVariable);
- else
- return null;
- }
+
+ return getSpecialVariableAccessExpression(graph, context, contextVariable, name);
+
+ }
+ }
+
+ protected Expression getSpecialVariableAccessExpression(ReadGraph graph,
+ CompilationContext context,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
+ String name) throws DatabaseException {
+ if(name.equals("input")) {
+ Environment environment = context.runtimeEnvironment.getEnvironment();
+ return accessInputVariable(environment, contextVariable);
+ } else if(name.equals("self"))
+ return new EVariable(contextVariable);
+ else
+ return null;
+ }
@Override
protected Type getExpectedType(ReadGraph graph, CompilationContext context) throws DatabaseException {
return super.getExpectedType(graph, context);
}
- @Override
- public int hashCode() {
- return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;
- return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
- }
+ @Override
+ public int hashCode() {
+ return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;
+ return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
+ }
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Object> {
+public class ServerSCLValueRequest extends ServerSCLValueRequestBase<org.simantics.document.server.request.ServerSCLValueRequest.CompilationContext> {
private final Pair<Resource,Resource> componentTypeAndRoot;
private final Resource literal;
return Pair.make(parent.getType(graph), root);
}
- private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component, Resource literal) throws DatabaseException {
- if(component != null) {
- Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
- if(type != null) {
- Resource root = graph.syncRequest(new IndexRoot(type));
- // System.err.println("getComponentTypeAndRoot3 " + graph.getPossibleURI(component) + " => " + graph.getPossibleURI(type) + " " + graph.getPossibleURI(root));
- return Pair.make(type, root);
- } else {
- Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
- if(doc != null) {
- Resource componentType = graph.getSingleType(doc);
- Resource root = graph.syncRequest(new IndexRoot(doc));
- return Pair.make(componentType, root);
- } else {
- //System.err.println("component = " + component);
- Resource root = graph.syncRequest(new IndexRoot(component));
-// Resource componentType = graph.getSingleType(doc);
- return Pair.make(null, root);
- }
- }
- // TODO: For Antti to consider and fix later
- // Introduced to handle procedural user components where component == null
- } else if (literal != null) {
- Resource root = graph.syncRequest(new IndexRoot(literal));
- return Pair.make(null, root);
- } else {
- throw new DatabaseException("Couldn't resolve component type and root for component == null && literal == null");
- }
- }
-
public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.get("graph");
+ Object oldGraph = sclContext.get("graph");
try {
Function1<Object,Object> exp = compile(graph, context);
sclContext.put("graph", graph);
} catch (Throwable t) {
throw new DatabaseException(t);
} finally {
- sclContext.put("graph", oldGraph);
+ sclContext.put("graph", oldGraph);
}
}
--- /dev/null
+package org.simantics.document.server.request;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.IndexRoot;
+import org.simantics.db.common.request.PossibleTypedParent;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
+import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
+import org.simantics.document.base.ontology.DocumentationResource;
+import org.simantics.structural2.scl.FindPossibleComponentTypeRequest;
+import org.simantics.utils.datastructures.Pair;
+
+abstract public class ServerSCLValueRequestBase<ASD extends AbstractExpressionCompilationContext> extends AbstractExpressionCompilationRequest<ASD, Object> {
+
+ static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component, Resource literal) throws DatabaseException {
+ if(component != null) {
+ Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
+ if(type != null) {
+ Resource root = graph.syncRequest(new IndexRoot(type));
+ return Pair.make(type, root);
+ } else {
+ Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
+ if(doc != null) {
+ Resource componentType = graph.getSingleType(doc);
+ Resource root = graph.syncRequest(new IndexRoot(doc));
+ return Pair.make(componentType, root);
+ } else {
+ Resource root = graph.syncRequest(new IndexRoot(component));
+ return Pair.make(null, root);
+ }
+ }
+ // TODO: For Antti to consider and fix later
+ // Introduced to handle procedural user components where component == null
+ } else if (literal != null) {
+ Resource root = graph.syncRequest(new IndexRoot(literal));
+ return Pair.make(null, root);
+ } else {
+ throw new DatabaseException("Couldn't resolve component type and root for component == null && literal == null");
+ }
+ }
+
+}
*******************************************************************************/
package org.simantics.issues.common;
+import java.util.Collection;
import java.util.Collections;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.simantics.db.AsyncReadGraph;
import org.simantics.db.Resource;
import org.simantics.db.common.request.TernaryAsyncRead;
-import org.simantics.db.procedure.AsyncMultiProcedure;
+import org.simantics.db.exception.DatabaseException;
import org.simantics.db.procedure.AsyncProcedure;
import org.simantics.issues.Severity;
/**
* @author Tuukka Lehtonen
*/
-public class ChildMaxIssueSeverity extends TernaryAsyncRead<Resource, Resource, Set<Resource>, Severity>{
+public class ChildMaxIssueSeverity extends TernaryAsyncRead<Resource, Resource, Set<Resource>, Severity> {
+ static class AsyncReadResult<T> {
+ private AtomicReference<T> resultRef;
+ private Throwable throwable;
+ private AtomicInteger counter = new AtomicInteger(1);
+ private AsyncProcedure<T> procedure;
+ AsyncReadResult(AsyncProcedure<T> procedure, AtomicReference<T> resultRef) {
+ this.procedure = procedure;
+ this.resultRef = resultRef;
+ }
+ void except(AsyncReadGraph graph, Throwable throwable) {
+ this.throwable = throwable;
+ dec(graph);
+ }
+ void set(AsyncReadGraph graph, T result) {
+ resultRef.set(result);
+ dec(graph);
+ }
+ void inc() {
+ counter.incrementAndGet();
+ }
+ void dec(AsyncReadGraph graph) {
+ if(counter.decrementAndGet() == 0) {
+ if(throwable != null)
+ procedure.exception(graph, throwable);
+ else
+ procedure.execute(graph, resultRef.get());
+ }
+ }
+
+ }
+
public ChildMaxIssueSeverity(Resource resource, Resource childRelation, Set<Resource> typesToRecurse) {
super(resource, childRelation, typesToRecurse);
}
-// @Override
-// public Severity perform(ReadGraph graph) throws DatabaseException {
-// Severity maxSeverity = null;
-// //System.out.println("severityForChildren: " + NameUtils.getSafeName(graph, resource));
-// for (Resource child : graph.getObjects(resource, resource2)) {
-// Severity s = graph.syncRequest(new MaxIssueSeverityRecursive(child));
-// maxSeverity = Severity.moreSevere(maxSeverity, s);
-// }
-// //System.out.println("severityForChildren: " + NameUtils.getSafeName(graph, resource) + " : " + maxSeverity);
-// return maxSeverity;
-// }
-
@Override
public void perform(AsyncReadGraph graph, final AsyncProcedure<Severity> procedure) {
- //System.out.println(getClass().getSimpleName() + ": " + parameter);
- graph.forTypes(parameter, new AsyncProcedure<Set<Resource>>() {
- @Override
- public void execute(AsyncReadGraph graph, Set<Resource> result) {
- if (!Collections.disjoint(parameter3, result)) {
- checkChildren(graph, procedure);
- } else {
- procedure.execute(graph, null);
- }
- }
- @Override
- public void exception(AsyncReadGraph graph, Throwable throwable) {
- procedure.exception(graph, throwable);
+ try {
+ Set<Resource> types = graph.getTypes(parameter);
+ if (!Collections.disjoint(parameter3, types)) {
+ checkChildren(graph, procedure);
+ } else {
+ procedure.execute(graph, null);
}
- });
+ } catch (DatabaseException e) {
+ procedure.exception(graph, e);
+ }
+
}
protected void checkChildren(AsyncReadGraph graph, final AsyncProcedure<Severity> procedure) {
- graph.forEachObject(parameter, parameter2, new AsyncMultiProcedure<Resource>() {
- AtomicReference<Severity> maxSeverity = new AtomicReference<Severity>();
- @Override
- public void execute(AsyncReadGraph graph, Resource child) {
+
+ AsyncReadResult<Severity> maxSeverity = new AsyncReadResult<Severity>(procedure, new AtomicReference<Severity>());
+
+ try {
+ Collection<Resource> children = graph.getObjects(parameter, parameter2);
+ for(Resource child : children) {
+ maxSeverity.inc();
graph.asyncRequest(new MaxIssueSeverityRecursive(child, parameter2, parameter3), new AsyncProcedure<Severity>() {
@Override
public void execute(AsyncReadGraph graph, Severity severity) {
if (severity != null) {
synchronized (maxSeverity) {
- maxSeverity.set(Severity.moreSevere(maxSeverity.get(), severity));
+ maxSeverity.set(graph, Severity.moreSevere(maxSeverity.resultRef.get(), severity));
}
+ } else {
+ maxSeverity.dec(graph);
}
}
@Override
public void exception(AsyncReadGraph graph, Throwable throwable) {
- procedure.exception(graph, throwable);
+ maxSeverity.except(graph, throwable);
}
});
}
- @Override
- public void finished(AsyncReadGraph graph) {
- procedure.execute(graph, maxSeverity.get());
- }
- @Override
- public void exception(AsyncReadGraph graph, Throwable throwable) {
- procedure.exception(graph, throwable);
- }
- });
+ maxSeverity.dec(graph);
+ } catch (DatabaseException e) {
+ maxSeverity.except(graph, e);
+ return;
+ }
+
}
}
*******************************************************************************/
package org.simantics.issues.common;
+import java.util.Collection;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
-import org.simantics.db.common.request.TernaryAsyncRead;
-import org.simantics.db.procedure.AsyncMultiProcedure;
-import org.simantics.db.procedure.AsyncProcedure;
+import org.simantics.db.common.request.TernaryRead;
+import org.simantics.db.exception.DatabaseException;
import org.simantics.issues.Severity;
import org.simantics.issues.ontology.IssueResource;
/**
* @author Tuukka Lehtonen
*/
-public class MaxIssueSeverityRecursive extends TernaryAsyncRead<Resource, Resource, Set<Resource>, Severity> {
+public class MaxIssueSeverityRecursive extends TernaryRead<Resource, Resource, Set<Resource>, Severity> {
public MaxIssueSeverityRecursive(Resource resource, Resource childRelation, Set<Resource> typesToRecurse) {
super(resource, childRelation, typesToRecurse);
}
@Override
- public void perform(AsyncReadGraph graph, final AsyncProcedure<Severity> procedure) {
+ public Severity perform(ReadGraph graph) throws DatabaseException {
IssueResource ISSUE = graph.getService(IssueResource.class);
- AtomicInteger issues = new AtomicInteger();
- AtomicBoolean excepted = new AtomicBoolean(false);
-
- graph.forEachObject(parameter, ISSUE.Issue_HasContext_Inverse, new AsyncMultiProcedure<Resource>() {
- @Override
- public void execute(AsyncReadGraph graph, Resource result) {
- issues.incrementAndGet();
- }
- @Override
- public void finished(AsyncReadGraph graph) {
-
- }
- @Override
- public void exception(AsyncReadGraph graph, Throwable throwable) {
- if(excepted.compareAndSet(false, true))
- procedure.exception(graph, throwable);
- }
- });
-
- graph.forEachObject(parameter, ISSUE.Issue_ContextList_Element_Inverse, new AsyncMultiProcedure<Resource>() {
- @Override
- public void execute(AsyncReadGraph graph, Resource result) {
- issues.incrementAndGet();
- }
- @Override
- public void finished(AsyncReadGraph graph) {
-
- }
- @Override
- public void exception(AsyncReadGraph graph, Throwable throwable) {
- if(excepted.compareAndSet(false, true))
- procedure.exception(graph, throwable);
- }
- });
-
- if(excepted.get()) return;
-
- if (issues.get() == 0) {
- // This content does not have directly attached issues, try to look
- // for some in the child components.
- graph.asyncRequest(new ChildMaxIssueSeverity(parameter, parameter2, parameter3), procedure);
- } else {
- // Try local issues first
- graph.asyncRequest(new MaxIssueSeveritySingle(parameter), new AsyncProcedure<Severity>() {
- @Override
- public void execute(AsyncReadGraph graph, Severity maxSeverity) {
- if (maxSeverity == null)
- // No severity for local issues, try children next.
- graph.asyncRequest(new ChildMaxIssueSeverity(parameter, parameter2, parameter3), procedure);
- else
- procedure.execute(graph, maxSeverity);
- }
- @Override
- public void exception(AsyncReadGraph graph, Throwable throwable) {
- if(excepted.compareAndSet(false, true))
- procedure.exception(graph, throwable);
- }
- });
+ Collection<Resource> inv = graph.getObjects(parameter, ISSUE.Issue_HasContext_Inverse);
+ Collection<Resource> inv2 = graph.getObjects(parameter, ISSUE.Issue_ContextList_Element_Inverse);
+ if(inv.isEmpty() && inv2.isEmpty()) {
+ return graph.syncRequest(new ChildMaxIssueSeverity(parameter, parameter2, parameter3));
}
+
+ Severity max = graph.syncRequest(new MaxIssueSeveritySingle(parameter));
+ if(max != null)
+ return max;
+ else
+ return graph.syncRequest(new ChildMaxIssueSeverity(parameter, parameter2, parameter3));
+
}
}
});
}
- IElement mappedElement = diagram.getDiagramClass().getSingleItem(DataElementMap.class).getElement(diagram, element);
+ IElement mappedElement = e;//diagram.getDiagramClass().getSingleItem(DataElementMap.class).getElement(diagram, element);
MonitorListener monitorListener = new MonitorListener(element, canvas, diagram, substitutions);
if (mappedElement != null) {
MonitorListener oldListener = mappedElement.getHint(KEY_VARIABLE_LISTENER);
}
private static boolean isImmutable(Bundle bundle) {
- String immutable = (String) bundle.getHeaders().get("Immutable");
- return immutable != null ? "true".equals(immutable) : true;
+ String immutable = (String) bundle.getHeaders().get("Immutable");
+ if(immutable == null)
+ return true;
+ if("false".equals(immutable))
+ return false;
+ if("trueWhenDeployed".equals(immutable)) {
+ String installHint = System.getProperty("installOntologiesAsDeployed");
+ if("true".equals(installHint))
+ return true;
+ else
+ return false;
+ }
+ return true;
}
public static class TGInfo {
public ModuleDebugInfo getModuleDebugInfo() {
return moduleDebugInfo;
}
+
+ public Map<String, byte[]> getClasses() {
+ return classes;
+ }
+
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
private final ModuleRepository parentRepository;
private final ModuleSourceRepository sourceRepository;
private ConcurrentHashMap<String, ModuleEntry> moduleCache = new ConcurrentHashMap<String, ModuleEntry>();
+ public Set<RuntimeEnvironment> runtimeEnvironments = new HashSet<RuntimeEnvironment>();
private static final ThreadLocal<THashSet<String>> PENDING_MODULES = new ThreadLocal<THashSet<String>>();
THashMap<String, Module> moduleMap = mapEntriesToModules(entries);
Environment environment = createEnvironment(moduleMap, imports);
THashMap<String, RuntimeModule> runtimeModuleMap = mapEntriesToRuntimeModules(entries);
- return new RuntimeEnvironmentImpl(environment, parentClassLoader, runtimeModuleMap);
+ RuntimeEnvironmentImpl result = new RuntimeEnvironmentImpl(environment, parentClassLoader, runtimeModuleMap);
+ runtimeEnvironments.add(result);
+ return result;
}
private static Environment createEnvironment(
public void setAdvisor(ModuleCompilationOptionsAdvisor advisor) {
this.advisor = advisor;
}
+
+ public Set<RuntimeEnvironment> getRuntimeEnvironments() {
+ return runtimeEnvironments;
+ }
}
\ No newline at end of file
public static final boolean TRACE_CLASS_CREATION = false;
String basePackageName;
- THashMap<String, byte[]> localClasses = new THashMap<String, byte[]>();
+ public THashMap<String, byte[]> localClasses = new THashMap<String, byte[]>();
THashMap<String, RuntimeModule> runtimeModuleMap;
int transientPackageId = 0;
THashMap<Constant,Object> valueCache = new THashMap<Constant,Object>();
if(bytes == null)
throw new ClassNotFoundException(name);
- return defineClass(name, bytes, 0, bytes.length);
+ clazz = defineClass(name, bytes, 0, bytes.length);
+ resolveClass(clazz);
+
+ return clazz;
+
}
@Override
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.commons.ClassRemapper;
+import org.objectweb.asm.commons.Remapper;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
import org.simantics.scl.compiler.internal.decompilation.DecompilerFactory;
import org.simantics.scl.compiler.internal.decompilation.IDecompiler;
+import org.simantics.scl.compiler.module.ConcreteModule;
import org.simantics.scl.compiler.module.Module;
import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
import org.simantics.scl.compiler.top.ValueNotFound;
}
private Class<?> getClass(String name) throws ClassNotFoundException {
- //System.out.println("getClass " + name);
+
+ Class<?> clazz = findLoadedClass(name);
+ if(clazz != null)
+ return clazz;
// If the class is not generated from SCL, use parent class loader
if(!name.startsWith(SCL_PACKAGE_PREFIX)) {
}
}
+// protected Class<?> loadClass(String name, boolean resolve)
+// throws ClassNotFoundException
+// {
+// synchronized (getClassLoadingLock(name)) {
+// // First, check if the class has already been loaded
+// Class<?> c = findLoadedClass(name);
+// if (c == null) {
+// c = getClass(name);
+// }
+// if (resolve) {
+// resolveClass(c);
+// }
+// return c;
+// }
+// }
+
@Override
public synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = getClass(name);
return clazz;
}
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return super.loadClass(name);
+ }
+
public Module getModule(String moduleName) {
//System.out.println("ModuleClassLoader.getModule(" + moduleName + ")");
if(moduleName.equals(this.moduleName))
classLoader = null;
classBuilder = null;
}
+
+ public class ClassNameRecordingRemapper extends Remapper {
+
+ private final Set<? super String> classNames;
+
+ public ClassNameRecordingRemapper(Set<? super String> classNames) {
+ this.classNames = classNames;
+ }
+
+ @Override
+ public String map(String typeName) {
+ classNames.add(typeName);
+ return super.map(typeName);
+ }
+
+ @Override
+ public String mapDesc(String desc) {
+ //classNames.add(desc);
+ return super.mapDesc(desc);
+ }
+ @Override
+ public String mapFieldName(String owner, String name, String desc) {
+ return super.mapFieldName(owner, name, desc);
+ }
+ @Override
+ public String mapInvokeDynamicMethodName(String name, String desc) {
+ // TODO Auto-generated method stub
+ return super.mapInvokeDynamicMethodName(name, desc);
+ }
+ @Override
+ public String mapMethodDesc(String desc) {
+ //classNames.add(desc);
+ return super.mapMethodDesc(desc);
+ }
+ @Override
+ public String mapMethodName(String owner, String name, String desc) {
+ // TODO Auto-generated method stub
+ return super.mapMethodName(owner, name, desc);
+ }
+ @Override
+ public String mapSignature(String signature, boolean typeSignature) {
+ //classNames.add(signature);
+ return super.mapSignature(signature, typeSignature);
+ }
+ @Override
+ public String mapType(String type) {
+ classNames.add(type);
+ return super.mapType(type);
+ }
+ @Override
+ public String[] mapTypes(String[] types) {
+ for(String type : types)
+ classNames.add(type);
+ // TODO Auto-generated method stub
+ return super.mapTypes(types);
+ }
+ @Override
+ public Object mapValue(Object value) {
+ //classNames.add(value.toString());
+ // TODO Auto-generated method stub
+ return super.mapValue(value);
+ }
+ }
+
+ public Set<String> classReferences(String className) {
+ try {
+ HashSet<String> referencedClasses = new HashSet<>();
+ ClassNameRecordingRemapper m = new ClassNameRecordingRemapper(referencedClasses);
+ ClassReader cr = new ClassReader(module.getClass(className));
+ int ASM5 = 5 << 16 | 0 << 8 | 0;
+ //TraceClassVisitor tcv = new TraceClassVisitor(null, new PrintWriter(System.err));
+ ClassVisitor cv1 = new ClassVisitor(ASM5) {};
+ ClassVisitor cv = new ClassRemapper(cv1, m);
+ cr.accept(cv, ClassReader.SKIP_DEBUG);
+ return referencedClasses;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public void loadClasses() {
+ if(module instanceof ConcreteModule) {
+ ConcreteModule cm = (ConcreteModule)module;
+ try {
+ for(String className : cm.getClasses().keySet()) {
+ Set<String> refs = classReferences(className);
+ for(String s : refs) {
+ String internalName = s.replace('/', '.');
+ try {
+ classLoader.getClass(internalName);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
}
\ No newline at end of file
import org.simantics.scl.compiler.errors.DoesNotExist;
import org.simantics.scl.compiler.errors.Failable;
+import org.simantics.scl.compiler.module.ConcreteModule;
import org.simantics.scl.compiler.module.Module;
import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;
import org.simantics.scl.compiler.module.repository.ModuleRepository;
+import org.simantics.scl.compiler.runtime.ExpressionClassLoader;
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
+import org.simantics.scl.compiler.runtime.RuntimeModule;
import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
import org.simantics.scl.compiler.testing.repository.TestRepository;
import org.simantics.scl.osgi.internal.Activator;
System.out.print(moduleName);
System.out.print(" - ");
Failable<Module> module = SCLOsgi.MODULE_REPOSITORY.getModule(moduleName);
- if(module.didSucceed())
+ if(module.didSucceed()) {
System.out.println("succeeded");
- else if(module == DoesNotExist.INSTANCE)
+ } else if(module == DoesNotExist.INSTANCE)
System.out.println("does not exist"); // should not happen
else {
System.out.println("error");
}
return null;
}
+
+ public static String primeClassloading() {
+ ArrayList<String> modulesWithErrors = new ArrayList<String>();
+ SCLOsgi.SOURCE_REPOSITORY.forAllModules(new TObjectProcedure<String>() {
+ @Override
+ public boolean execute(String moduleName) {
+ Failable<Module> module = SCLOsgi.MODULE_REPOSITORY.getModule(moduleName);
+ if(module.didSucceed()) {
+ Failable<RuntimeModule> frm = SCLOsgi.MODULE_REPOSITORY.getRuntimeModule(moduleName);
+ RuntimeModule rm = frm.getResult();
+ rm.loadClasses();
+ } else if(module == DoesNotExist.INSTANCE)
+ System.out.println("does not exist"); // should not happen
+ else {
+ System.out.println("error");
+ modulesWithErrors.add(moduleName);
+ }
+ return true;
+ }
+ });
+ for(RuntimeEnvironment env : SCLOsgi.MODULE_REPOSITORY.getRuntimeEnvironments()) {
+ ExpressionClassLoader ecl = (ExpressionClassLoader)env.getMutableClassLoader();
+ for(String name : ecl.localClasses.keySet()) {
+ try {
+ ecl.loadClass(name.replace("/", "."));
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return null;
+ }
+
}
}
}
+ public static Function1<Variable, Object> compile(ReadGraph graph, Resource componentType) throws DatabaseException {
+ return graph.syncRequest(new CompileProceduralComponentTypeRequest(componentType), TransientCacheListener.instance());
+ }
+
@Override
protected String getExpressionText(ReadGraph graph)
throws DatabaseException {
public class ThreadLogVisualizer {
// Do not show tasks shorter than 5ms
- final public static long DISCARD_LIMIT = 2 * 1000 * 1000;
+ final public static long DISCARD_LIMIT = 50 * 1000 * 1000;
// 1s columns
final public static long COLUMN_WIDTH = 1000000000;
public static String LOG_FILE = "threads.log";
- public static boolean LOG = false;
+ public static boolean LOG = true;
static Object loggerCreationLock = new Object();
static ThreadLogger logger = null;