}
protected String getRealmId() {
- return realm.id;
+ return realm.getId();
}
public Node getRoot() {
checkThreadAccess();
valueCache.put(node, value);
realm.getEngine().setValue(node, value);
- realm.nodeManager.valueCache.put(node, value);
+ realm.getNodeManager().valueCache.put(node, value);
refreshVariables();
}
}
return null;
}
-
+
+ public void clear() {
+ valueCache.clear();
+ listeners.clear();
+ }
}
package org.simantics.db.layer0;
+import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import org.simantics.simulator.variable.Realm;
abstract public class StandardRealm<Node, Engine extends StandardEngine<Node>> implements Realm {
-
- String id;
- Thread executorThread;
- ExecutorService executor = new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
- @Override
- public Thread newThread(Runnable r) {
- executorThread = new Thread(r);
- return executorThread;
- }
- });
-
- Semaphore beginSyncExec = new Semaphore(0);
- Semaphore endSyncExec = new Semaphore(0);
+
+ private String id;
+ private Thread executorThread;
+ private StandardRealmThreadFactory factory = new StandardRealmThreadFactory(this);
+ private ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>(), factory);
+ private Semaphore beginSyncExec = new Semaphore(0);
+ private Semaphore endSyncExec = new Semaphore(0);
- Engine engine;
- StandardSessionManager<Node, Engine> sessionManager;
- StandardNodeManager<Node, Engine> nodeManager;
+ private Engine engine;
+ private StandardNodeManager<Node, Engine> nodeManager;
- Runnable scheduleSyncExec = new Runnable() {
+ private Runnable scheduleSyncExec = new Runnable() {
@Override
public void run() {
beginSyncExec.release();
}
};
- protected StandardRealm(StandardSessionManager<Node, Engine> sessionManager, Engine engine, String id) {
- this.sessionManager = sessionManager;
+ protected StandardRealm(Engine engine, String id) {
this.engine = engine;
this.id = id;
this.nodeManager = createManager();
}
-
+
abstract protected StandardNodeManager<Node, Engine> createManager();
protected String getSCLContextKey() {
}
public void close() {
- sessionManager.removeRealm(id);
executor.shutdown();
try {
- executor.awaitTermination(500L, TimeUnit.MILLISECONDS);
+ if (!executor.awaitTermination(500L, TimeUnit.MILLISECONDS)) {
+ List<Runnable> runnablesLeft = executor.shutdownNow();
+ if (!runnablesLeft.isEmpty()) {
+ getLogger().info("Runnables left for realm " + this + " after executor shutdown! " + runnablesLeft);
+ }
+ }
} catch (InterruptedException e) {
+ getLogger().info("Could not shutdown executor " + executor + " for realm " + this, e);
}
+
+ factory.clear();
+ factory = null;
+ // Should never be true
+ if (!executorThread.isAlive())
+ executorThread.interrupt();
+ executorThread = null;
+ executor = null;
+
+ // Clear nodeManager
+ nodeManager.clear();
+ nodeManager = null;
}
public StandardNodeManager<Node, Engine> getNodeManager() {
return nodeManager;
}
-
+
+ public abstract org.slf4j.Logger getLogger();
+
+ private void setExecutorThread(Thread t) {
+ executorThread = t;
+ }
+
+ private static class StandardRealmThreadFactory implements ThreadFactory {
+
+ private StandardRealm<?, ?> realm;
+
+ public StandardRealmThreadFactory(StandardRealm<?, ?> realm) {
+ this.realm = realm;
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ realm.setExecutorThread(t);
+ return t;
+ }
+
+ void clear() {
+ realm = null;
+ }
+ }
}
import java.util.concurrent.ConcurrentHashMap;
import org.simantics.db.ReadGraph;
+import org.simantics.db.WriteGraph;
import org.simantics.db.common.request.ParametrizedPrimitiveRead;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.variable.NodeSupport;
if(realm != null) {
REALMS.put(key, realm);
} else {
- REALMS.remove(key);
+ StandardRealm<Node, Engine> removedRealm = REALMS.remove(key);
+ if (removedRealm != null)
+ removedRealm.close();
}
Listener<StandardRealm<Node,Engine>> listener = getOrDisposeListener(key);
if(listener != null) {
protected abstract Engine createEngine(ReadGraph graph, String id) throws DatabaseException;
protected abstract StandardRealm<Node,Engine> createRealm(Engine engine, String id);
- public void removeRealm(String id) {
+ public void removeRealm(WriteGraph graph, String id) throws DatabaseException {
modifyRealms(id, null);
+ // remove listeners from this realm
+ realmListeners.remove(id);
// if node support has been created remove it as well
- SUPPORTS.remove(id);
+ NodeSupport<Node> support = SUPPORTS.remove(id);
+ if (support != null)
+ support.dispose();
}
public Collection<String> getRealms() {
contextDocument :: CommandContext -> <Proc> IDocument
contextDocument ctx = justValue ctx "__document__"
+
+importJava "org.simantics.document.server.io.IRequest" where
+ @private
+ data IRequest
+
+ @private
+ getParameter :: IRequest -> String -> <Proc> Maybe String
+
+possibleQueryParameterFromContext :: CommandContext -> String -> <Proc> Maybe String
+possibleQueryParameterFromContext context parameter = do
+ request = fromJust $ possibleValue context "__request__"
+ getParameter request parameter
@Override
public String getName(String node) {
if(ROOT.equals(node)) {
- String id = realm.id;
+ String id = realm.getId();
int lastSlash = id.lastIndexOf("/");
if(lastSlash == -1) throw new IllegalStateException("Invalid realm id " + id);
String name = id.substring(lastSlash+1);
checkThreadAccess();
valueCache.put(node, value);
realm.getConnection().setVariable(node, getType(node), value);
- realm.nodeManager.valueCache.put(node, value);
+ realm.getNodeManager().valueCache.put(node, value);
refreshVariables();
}
support.structureCache.put(ROOT, null);
support.valueCache.put(node, null);
- realm.nodeManager.valueCache.put(node, value);
- realm.nodeManager.
+ realm.getNodeManager().valueCache.put(node, value);
+ realm.getNodeManager().
refreshVariables();
}
public String getPropertyURI(String parent, String property) {
return ModelingResources.URIs.SCLCommandSession_hasValue;
}
+
+ public void clear() {
+ valueCache.clear();
+ listeners.clear();
+ }
}
package org.simantics.modeling.scl;
import java.io.IOException;
+import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadFactory;
import org.simantics.scl.runtime.SCLContext;
import org.simantics.scl.runtime.function.Function;
import org.simantics.scl.runtime.tuple.Tuple0;
-import org.simantics.simulator.variable.NodeManager;
import org.simantics.simulator.variable.Realm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public static final String SCL = "scl";
- THashMap<String,Type> contextTypes = new THashMap<String,Type>();
+ private THashMap<String,Type> contextTypes = new THashMap<String,Type>();
- CommandSession connection;
- String id;
- Thread executorThread;
- ExecutorService executor = new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
- @Override
- public Thread newThread(Runnable r) {
- executorThread = new Thread(r);
- return executorThread;
- }
- });
+ private CommandSession connection;
+ private String id;
+ private Thread executorThread;
+ private SCLRealmThreadFactory factory = new SCLRealmThreadFactory(this);
+ private ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>(), factory);
- Semaphore beginSyncExec = new Semaphore(0);
- Semaphore endSyncExec = new Semaphore(0);
+ private Semaphore beginSyncExec = new Semaphore(0);
+ private Semaphore endSyncExec = new Semaphore(0);
- SCLNodeManager nodeManager;
+ private SCLNodeManager nodeManager;
- Runnable scheduleSyncExec = new Runnable() {
+ private Runnable scheduleSyncExec = new Runnable() {
@Override
public void run() {
beginSyncExec.release();
SCLSessionManager.CONNECTIONS.remove(id);
executor.shutdown();
try {
- executor.awaitTermination(500L, TimeUnit.MILLISECONDS);
+ if (!executor.awaitTermination(500L, TimeUnit.MILLISECONDS)) {
+ List<Runnable> runnables = executor.shutdownNow();
+ if (!runnables.isEmpty()) {
+ LOGGER.info("Some runnables left to execute in realm " + this + ": " + runnables);
+ }
+ }
} catch (InterruptedException e) {
+ LOGGER.info("Could not shutdown executor " + executor + " in realm " + this, e);
}
//connection.close();
+
+ factory.clear();
+ factory = null;
+ // Should not happen
+ if (executorThread.isAlive())
+ executorThread.interrupt();
+ executorThread = null;
+ executor = null;
+
+ // clear nodeManager
+ nodeManager.clear();
}
- public NodeManager<String> getNodeManager() {
+ public SCLNodeManager getNodeManager() {
return nodeManager;
}
}
}
+ private static class SCLRealmThreadFactory implements ThreadFactory {
+
+ private SCLRealm realm;
+
+ public SCLRealmThreadFactory(SCLRealm realm) {
+ this.realm = realm;
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ realm.setThread(t);
+ return t;
+ }
+
+ void clear() {
+ realm = null;
+ }
+ }
+
+ private void setThread(Thread t) {
+ this.executorThread = t;
+ }
}
}
public static synchronized void removeRealm(String id) {
- CONNECTIONS.remove(id);
+ SCLRealm realm = CONNECTIONS.remove(id);
+ if (realm != null)
+ realm.close();
// if node support has been created remove it as well
- SUPPORTS.remove(id);
+ NodeSupport<String> support = SUPPORTS.remove(id);
+ if (support != null)
+ support.dispose();
}
}
selectColumn :: Integer -> TableCell -> Boolean
setSCLLine :: Resource -> Integer -> String -> <WriteGraph> ()
sheetRun :: Resource -> Variable -> <ReadGraph> Variable
-
+
+importJava "org.simantics.spreadsheet.graph.SpreadsheetSessionManager" where
+ removeSpreadsheetSession :: Variable -> <Proc, WriteGraph> ()
+
importJava "org.simantics.spreadsheet.graph.ExcelImport" where
importBook :: Resource -> File -> <Proc> ()
String contextURI = context.getURI(graph);
String sessionName = context.getParent(graph).getURI(graph);
- SpreadsheetSessionManager.getInstance().removeRealm(sessionName);
+ SpreadsheetSessionManager.getInstance().removeRealm(graph, sessionName);
SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
}
import org.simantics.db.layer0.StandardNodeManager;
import org.simantics.db.layer0.StandardRealm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class SpreadsheetRealm extends StandardRealm<SheetNode,SpreadsheetBook> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetRealm.class);
+
SpreadsheetRealm(SpreadsheetBook book, String id) {
- super(SpreadsheetSessionManager.getInstance(), book, id);
+ super(book, id);
}
@Override
protected StandardNodeManager<SheetNode, SpreadsheetBook> createManager() {
return new SpreadsheetNodeManager(this);
}
+
+ @Override
+ public Logger getLogger() {
+ return LOGGER;
+ }
}
import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.StandardRealm;
import org.simantics.db.layer0.StandardSessionManager;
import org.simantics.db.layer0.variable.ProxyVariables;
import org.simantics.db.layer0.variable.Variable;
import org.simantics.db.layer0.variable.Variables;
+import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler;
import org.simantics.spreadsheet.resource.SpreadsheetResource;
import org.simantics.structural.synchronization.Synchronizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class SpreadsheetSessionManager extends StandardSessionManager<SheetNode, SpreadsheetBook> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetSessionManager.class);
+
private static SpreadsheetSessionManager INSTANCE;
public static SpreadsheetSessionManager getInstance() {
protected StandardRealm<SheetNode, SpreadsheetBook> createRealm(SpreadsheetBook engine, String id) {
return new SpreadsheetRealm(engine, id);
}
-
-// static ConcurrentHashMap<String, SpreadsheetRealm> REALMS =
-// new ConcurrentHashMap<String, SpreadsheetRealm>();
-//
-// static ConcurrentHashMap<String, NodeSupport<String>> SUPPORTS =
-// new ConcurrentHashMap<String, NodeSupport<String>>();
-//
-// public static SpreadsheetRealm sclRealmById(String id) {
-// // CONNECTIONS is ConcurrentHashMap so no synchronization is needed here
-// return REALMS.get(id);
-// }
-//
-// public static NodeSupport<String> getOrCreateNodeSupport(String id) {
-// synchronized(SUPPORTS) {
-// NodeSupport<String> result = SUPPORTS.get(id);
-// if(result == null) {
-// SpreadsheetRealm realm = getOrCreateSCLRealm(id);
-// result = new NodeSupport<String>(realm.getNodeManager());
-// SUPPORTS.put(id, result);
-// }
-// return result;
-// }
-// }
-//
-// public static SpreadsheetRealm createRealm() {
-// synchronized(REALMS) {
-// String id = UUID.randomUUID().toString();
-// return createRealm(id);
-// }
-// }
-//
-// public static SpreadsheetRealm getOrCreateSCLRealm(String id) {
-// synchronized(REALMS) {
-// SpreadsheetRealm session = sclRealmById(id);
-// if(session == null)
-// return createRealm(id);
-// else
-// return session;
-// }
-// }
-//
-// private static SpreadsheetRealm createRealm(String id) {
-// SpreadsheetBook book = new SpreadsheetBook();
-// SpreadsheetRealm realm = new SpreadsheetRealm(book, id);
-// REALMS.put(id, realm);
-// return realm;
-// }
-//
-// public static void removeRealm(String id) {
-// REALMS.remove(id);
-// }
-
+
+ @Override
+ public void removeRealm(WriteGraph graph, String id) throws DatabaseException {
+ StandardRealm<SheetNode, SpreadsheetBook> realm = getOrCreateRealm(graph, id);
+ SpreadsheetEvaluationEnvironment.removeInstance(realm.getEngine());
+ super.removeRealm(graph, id);
+ }
+
+ // Utility function for SCL, this should maybe be replaced with something better in the future
+ public static void removeSpreadsheetSession(WriteGraph graph, Variable runVariable) throws DatabaseException {
+ String uri = runVariable.getParent(graph).getURI(graph);
+ getInstance().removeRealm(graph, uri);
+ }
}
+
if (bookURI != null) {
for (String realmId : SpreadsheetSessionManager.getInstance().getRealms()) {
if (realmId.startsWith(bookURI)) {
- SpreadsheetSessionManager.getInstance().removeRealm(realmId);
+ SpreadsheetSessionManager.getInstance().removeRealm(graph, realmId);
}
}
}
return book;
}
- public static Map<SpreadsheetBook, SpreadsheetEvaluationEnvironment> INSTANCES = new HashMap<>();
+ private static Map<SpreadsheetBook, SpreadsheetEvaluationEnvironment> INSTANCES = new HashMap<>();
public static SpreadsheetEvaluationEnvironment getInstance(SpreadsheetBook book) {
SpreadsheetEvaluationEnvironment env = INSTANCES.get(book);
return env;
}
+ public static boolean removeInstance(SpreadsheetBook book) {
+ return INSTANCES.remove(book) != null;
+ }
}