X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Fvariable%2FNodeValueRequest.java;h=b44f16b30eeedc3ca7ee15fd9d023e0505703a9b;hp=dcc5a6f9c3d862acb67ca45dcee79651b43724aa;hb=ccb253462b54a0e036f0906ec8ac11a9021a968c;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java index dcc5a6f9c..b44f16b30 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java @@ -1,233 +1,240 @@ -package org.simantics.db.layer0.variable; - -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.error.BindingException; -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.databoard.util.ObjectUtils; -import org.simantics.db.ReadGraph; -import org.simantics.db.common.request.ParametrizedPrimitiveRead; -import org.simantics.db.common.utils.Logger; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.procedure.Listener; -import org.simantics.simulator.variable.exceptions.NodeIsNotValidAnymoreException; -import org.simantics.simulator.variable.exceptions.NodeManagerException; -import org.simantics.utils.datastructures.Pair; - -@SuppressWarnings("rawtypes") -class NodeValueRequest extends ParametrizedPrimitiveRead, Variant> implements VariableNodeReadRunnable { - - private Listener listener = null; - private Variant value = Variables.PENDING_NODE_VALUE; - private boolean wasRun = false; - - static class Probe implements Runnable { - - private Pair parameter; - public Variant result; - - public Probe(Pair parameter) { - this.parameter = parameter; - } - - @SuppressWarnings("unchecked") - @Override - public void run() { - try { - result = NodeValueRequest.get(parameter); - parameter.first.support.valueCache.put(parameter.first.node, result, 1000000000L); - } catch (NodeManagerException e) { - e.printStackTrace(); - } catch (BindingException e) { - e.printStackTrace(); - } - } - - } - - public NodeValueRequest(VariableNode node) { - super(Pair.make(node, null)); - } - - public NodeValueRequest(VariableNode node, Binding binding) { - super(Pair.make(node, binding)); - } - - @SuppressWarnings("unchecked") - @Override - public void register(ReadGraph graph, final Listener procedure) { - - VariableNode node = parameter.first; - - if(procedure.isDisposed()) { - - // We are not listening - Variant result = (Variant)node.support.valueCache.get(node.node); - - if(result != null) { - // Return cached value immediately - procedure.execute(result); - } else { - -// -// listener = procedure; -// -// if(graph.getSynchronous()) { -// try { -// parameter.support.manager.getRealm().syncExec(this); -// } catch (InterruptedException e) { -// if (!wasRun) procedure.exception(e); -// } catch (Throwable e) { -// if (!wasRun) procedure.exception(e); -// } -// } else { -// parameter.support.manager.getRealm().asyncExec(this); -// -// if(value == Variables.PENDING_NODE_VALUE) { -// procedure.execute(Variables.PENDING_NODE_VALUE); -// } -// } -// return; - - NodeValueRequest.Probe probe = new Probe(parameter); - node.support.manager.getRealm().asyncExec(probe); - if(probe.result != null) { - procedure.execute(probe.result); - } else { - procedure.execute(Variables.PENDING_NODE_VALUE); - } - - } - - return; - } - - // We need to listen - listener = procedure; - // Register listening - node.support.manager.addNodeListener(node.node, this); - synchronized(this) { - if(wasRun) { - procedure.execute(value); - } else { - Variant result = (Variant)node.support.valueCache.get(node.node); - if(result != null) { - procedure.execute(result); - } else { - procedure.execute(Variables.PENDING_NODE_VALUE); - } - } - } - -// if(listener != null) { -// throw new UnsupportedOperationException(); -// } -// listener = procedure; -// if(graph.getSynchronous()) { -// try { -// parameter.support.manager.getRealm().syncExec(new VariableNodeReadRunnable() { -// @Override -// public void run() { -// parameter.support.manager.addNodeListener(parameter.node, NodeValueRequest.this); -// } -// @Override -// public String toString() { -// return "NodeValueRequest.register.sync.addNodeListener @ " + System.identityHashCode(NodeValueRequest.this); -// } -// }); -// -// if (!wasRun) procedure.exception(new InternalException("No invocation of listener from node manager " + parameter.support.manager.getClass().getName())); -// } catch (InterruptedException e) { -// if (!wasRun) procedure.exception(e); -// } catch (Throwable e) { -// if (!wasRun) procedure.exception(e); -// } -// } else { -// parameter.support.manager.addNodeListener(parameter.node, this); -// if(value == Variables.PENDING_NODE_VALUE) procedure.execute(Variables.PENDING_NODE_VALUE); -// } - - } - - static class NodeListener implements VariableNodeReadRunnable { - - private VariableNode node; - private NodeValueRequest request; - - public NodeListener(VariableNode node, NodeValueRequest request) { - this.node = node; - this.request = request; - } - - @SuppressWarnings("unchecked") - @Override - public void run() { - node.support.manager.addNodeListener(node.node, request); - } - - } - - - @SuppressWarnings("unchecked") - @Override - public void unregistered() { - VariableNode node = parameter.first; - node.support.manager.removeNodeListener(node.node, this); - node.support.valueCache.removeListening(node.node); - listener = null; - } - - @SuppressWarnings("unchecked") - public static Variant get(Pair parameter) throws NodeManagerException, BindingException { - - VariableNode node = parameter.first; - Binding binding = parameter.second; - - if (binding != null) { - Object raw = node.support.manager.getValue(node.node, binding); - if(raw == null) return null; - else return new Variant(binding, raw); - } else { - return node.support.manager.getValue(node.node); - } - - } - - @SuppressWarnings("unchecked") - @Override - public synchronized void run() { - - VariableNode node = parameter.first; - - try { - Variant newValue = get(parameter); - if (wasRun && ObjectUtils.objectEquals(value, newValue)) { - //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node); - return; - } - value = newValue; - node.support.valueCache.put(node.node, value); - } catch (Throwable e) { - // Must catch everything to prevent DB client from getting stuck. - if(!(e instanceof NodeIsNotValidAnymoreException)) - Logger.defaultLogError(e); - // Invoke the exception method of the listener - Listener listener = this.listener; - if (listener != null) listener.exception(new DatabaseException("External data access error", e)); - wasRun = true; - return; - } - // Must always invoke an existing listener, regardless of earlier errors. - Listener listener = this.listener; - if (listener != null) { - //System.out.println("LISTENER " + listener + " invoked with value " + value); - listener.execute(value); - } - wasRun = true; - } - - @Override - public String toString() { - return "NodeValueRequest.run " + parameter.first.node + " " + parameter.first.support.manager + " " + System.identityHashCode(this); - } - +package org.simantics.db.layer0.variable; + +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.databoard.util.ObjectUtils; +import org.simantics.db.ReadGraph; +import org.simantics.db.common.request.ParametrizedPrimitiveRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.procedure.Listener; +import org.simantics.simulator.variable.NodeManager; +import org.simantics.simulator.variable.exceptions.NodeIsNotValidAnymoreException; +import org.simantics.simulator.variable.exceptions.NodeManagerException; +import org.simantics.utils.datastructures.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("rawtypes") +class NodeValueRequest extends ParametrizedPrimitiveRead, Variant> implements VariableNodeReadRunnable { + + private static final Logger LOGGER = LoggerFactory.getLogger(NodeValueRequest.class); + + private Listener listener = null; + private Variant value = Variables.PENDING_NODE_VALUE; + private boolean wasRun = false; + + static class Probe implements Runnable { + + private Pair parameter; + public Variant result; + + public Probe(Pair parameter) { + this.parameter = parameter; + } + + @SuppressWarnings("unchecked") + @Override + public void run() { + try { + result = NodeValueRequest.get(parameter); + parameter.first.support.valueCache.put(parameter.first.node, result, 1000000000L); + } catch (NodeManagerException e) { + e.printStackTrace(); + } catch (BindingException e) { + e.printStackTrace(); + } + } + + } + + public NodeValueRequest(VariableNode node) { + super(Pair.make(node, null)); + } + + public NodeValueRequest(VariableNode node, Binding binding) { + super(Pair.make(node, binding)); + } + + @SuppressWarnings("unchecked") + @Override + public void register(ReadGraph graph, final Listener procedure) { + + VariableNode node = parameter.first; + + if(procedure.isDisposed()) { + + // We are not listening + Variant result = (Variant)node.support.valueCache.get(node.node); + + if(result != null) { + // Return cached value immediately + procedure.execute(result); + } else { + +// +// listener = procedure; +// +// if(graph.getSynchronous()) { +// try { +// parameter.support.manager.getRealm().syncExec(this); +// } catch (InterruptedException e) { +// if (!wasRun) procedure.exception(e); +// } catch (Throwable e) { +// if (!wasRun) procedure.exception(e); +// } +// } else { +// parameter.support.manager.getRealm().asyncExec(this); +// +// if(value == Variables.PENDING_NODE_VALUE) { +// procedure.execute(Variables.PENDING_NODE_VALUE); +// } +// } +// return; + + NodeValueRequest.Probe probe = new Probe(parameter); + node.support.manager.getRealm().asyncExec(probe); + if(probe.result != null) { + procedure.execute(probe.result); + } else { + procedure.execute(Variables.PENDING_NODE_VALUE); + } + + } + + return; + } + + // We need to listen + listener = procedure; + // Register listening + node.support.manager.addNodeListener(node.node, this); + synchronized(this) { + if(!wasRun) { + Variant result = (Variant)node.support.valueCache.get(node.node); + if(result != null) { + procedure.execute(result); + } else { + procedure.execute(Variables.PENDING_NODE_VALUE); + } + } + } + +// if(listener != null) { +// throw new UnsupportedOperationException(); +// } +// listener = procedure; +// if(graph.getSynchronous()) { +// try { +// parameter.support.manager.getRealm().syncExec(new VariableNodeReadRunnable() { +// @Override +// public void run() { +// parameter.support.manager.addNodeListener(parameter.node, NodeValueRequest.this); +// } +// @Override +// public String toString() { +// return "NodeValueRequest.register.sync.addNodeListener @ " + System.identityHashCode(NodeValueRequest.this); +// } +// }); +// +// if (!wasRun) procedure.exception(new InternalException("No invocation of listener from node manager " + parameter.support.manager.getClass().getName())); +// } catch (InterruptedException e) { +// if (!wasRun) procedure.exception(e); +// } catch (Throwable e) { +// if (!wasRun) procedure.exception(e); +// } +// } else { +// parameter.support.manager.addNodeListener(parameter.node, this); +// if(value == Variables.PENDING_NODE_VALUE) procedure.execute(Variables.PENDING_NODE_VALUE); +// } + + } + + static class NodeListener implements VariableNodeReadRunnable { + + private VariableNode node; + private NodeValueRequest request; + + public NodeListener(VariableNode node, NodeValueRequest request) { + this.node = node; + this.request = request; + } + + @SuppressWarnings("unchecked") + @Override + public void run() { + node.support.manager.addNodeListener(node.node, request); + } + + } + + + @SuppressWarnings("unchecked") + @Override + public void unregistered() { + VariableNode node = parameter.first; + node.support.manager.removeNodeListener(node.node, this); + node.support.valueCache.removeListening(node.node); + listener = null; + } + + @SuppressWarnings("unchecked") + public static Variant get(Pair parameter) throws NodeManagerException, BindingException { + + VariableNode node = parameter.first; + Binding binding = parameter.second; + + if (binding != null) { + Object raw = node.support.manager.getValue(node.node, binding); + if(raw == null) + return null; + else if(NodeManager.PENDING_NODE_VALUE == raw) + return NodeManager.PENDING_NODE_VALUE; + else return new Variant(binding, raw); + } else { + return node.support.manager.getValue(node.node); + } + + } + + @SuppressWarnings("unchecked") + @Override + public synchronized void run() { + + VariableNode node = parameter.first; + + try { + Variant newValue = get(parameter); + if (wasRun && ObjectUtils.objectEquals(value, newValue)) { + //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node); + return; + } + value = newValue; + node.support.valueCache.put(node.node, value); + } catch (Throwable e) { + // Must catch everything to prevent DB client from getting stuck. + if(!(e instanceof NodeIsNotValidAnymoreException)) + LOGGER.error("Error while computing node value", e); + // Invoke the exception method of the listener + Listener listener = this.listener; + if (listener != null) { + listener.exception(new DatabaseException("External data access error", e)); + wasRun = true; + } + return; + } + // Must always invoke an existing listener, regardless of earlier errors. + Listener listener = this.listener; + if (listener != null) { + //System.out.println("LISTENER " + listener + " invoked with value " + value); + listener.execute(value); + wasRun = true; + } + } + + @Override + public String toString() { + return "NodeValueRequest.run " + parameter.first.node + " " + parameter.first.support.manager + " " + System.identityHashCode(this); + } + } \ No newline at end of file