NodeStructureRequest and NodeValueRequest fire ExternalRead twice 24/4524/2
authorAntti Villberg <antti.villberg@semantum.fi>
Tue, 6 Oct 2020 14:05:24 +0000 (17:05 +0300)
committerAntti Villberg <antti.villberg@semantum.fi>
Tue, 6 Oct 2020 17:49:59 +0000 (20:49 +0300)
gitlab #617

Change-Id: Id424c9254e1d80fdd26665fcbbbc9080d0878d71

bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeStructureRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java

index 5d21ca56bdf5ab3a0d0ba9aa7cd7a11542379920..707fdbd0ee46463a586eda41827beb5b9118085f 100644 (file)
@@ -7,174 +7,177 @@ import java.util.Map;
 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.layer0.variable.Variables.NodeStructure;
 import org.simantics.db.procedure.Listener;
 import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.THashMap;
 
 @SuppressWarnings("rawtypes")
 class NodeStructureRequest extends ParametrizedPrimitiveRead<VariableNode, NodeStructure> implements VariableNodeReadRunnable {
 
-       private Listener<NodeStructure> listener = null;
-       private NodeStructure value = Variables.PENDING_NODE_STRUCTURE;
-       private boolean wasRun = false;
-
-       static class Probe implements Runnable {
-
-               private VariableNode node;
-               public NodeStructure result;
-
-               public Probe(VariableNode node) {
-                       this.node = node;
-               }
-
-               @SuppressWarnings("unchecked")
-               @Override
-               public void run() {
-                       try {
-                               result = NodeStructureRequest.get(node);
-                               node.support.structureCache.put(node.node, result, 1000000000L);
-                       } catch (NodeManagerException e) {
-                               e.printStackTrace();
-                       }
-               }
-
-       }
-
-       public NodeStructureRequest(VariableNode node) {
-               super(node);
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public void register(ReadGraph graph, final Listener<NodeStructure> procedure) {
-
-               if(procedure.isDisposed()) {
-
-                       // We are not listening
-                       NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);
-
-                       if(result != null) {
-                               // Return cached value immediately
-                               procedure.execute(result);
-                       } else {
-                               NodeStructureRequest.Probe probe = new Probe(parameter);
-                               parameter.support.manager.getRealm().asyncExec(probe);
-                               if(probe.result != null) {
-                                       procedure.execute(probe.result);
-                               } else {
-                                       procedure.execute(Variables.PENDING_NODE_STRUCTURE);
-                               }
-                       }
-
-                       return;
-
-               }
-
-               // We need to listen
-               listener = procedure;
-               // Register listening
-               parameter.support.manager.addNodeListener(parameter.node, this);
-               synchronized(this) {
-                       if(wasRun) {
-                               procedure.execute(value);
-                       } else {
-                               NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);
-                               if(result != null) {
-                                       procedure.execute(result);
-                               } else {
-                                       procedure.execute(Variables.PENDING_NODE_STRUCTURE);
-                               }
-                       }
-               }
-
-       }
-
-       static class NodeListener implements VariableNodeReadRunnable {
-
-               private VariableNode node;
-               private NodeStructureRequest request;
-
-               public NodeListener(VariableNode node, NodeStructureRequest 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() {
-               parameter.support.manager.removeNodeListener(parameter.node, this);
-               parameter.support.structureCache.removeListening(parameter.node);
-               listener = null;
-       }
-
-       @SuppressWarnings("unchecked")
-       public static NodeStructure get(VariableNode parameter) throws NodeManagerException {
-               List<?> children = parameter.support.manager.getChildren(parameter.node);
-               List<?> properties = parameter.support.manager.getProperties(parameter.node);
-               Map<String, Object> childMap = Collections.emptyMap();
-               Map<String, Object> propertyMap = childMap;
-               if(!children.isEmpty()) {
-                       childMap = new THashMap<>(children.size());
-                       for(Object o : children) {
-                               String name = parameter.support.manager.getName(o);
-                               childMap.put(name, o);
-                       }
-               }
-               if(!properties.isEmpty()) {
-                       propertyMap = new THashMap<>(properties.size());
-                       for(Object o : properties) {
-                               String name = parameter.support.manager.getName(o);
-                               propertyMap.put(name, o);
-                       }
-               }
-               return new NodeStructure(childMap, propertyMap);
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public synchronized void run() {
-               try {
-                       // Cache this value with infinite cache time since we are listening
-                       NodeStructure newValue = get(parameter);
-                       if (wasRun && ObjectUtils.objectEquals(value, newValue)) {
-                               //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node);
-                               return;
-                       }
-                       value = newValue;
-                       parameter.support.structureCache.put(parameter.node, value);
-               } catch (Throwable e) {
-                       // Must catch everything to prevent DB client from getting stuck.
-                       Logger.defaultLogError(e);
-                       // Invoke the exception method of the listener
-                       Listener<NodeStructure> 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<NodeStructure> listener = this.listener;
-               if (listener != null) {
-                       listener.execute(value);
-               }
-               wasRun = true;
-       }
-
-       @Override
-       public String toString() {
-               return "NodeStructureRequest.run @ " + System.identityHashCode(this);
-       }
+    private static final Logger LOGGER = LoggerFactory.getLogger(NodeStructureRequest.class);
+
+    private Listener<NodeStructure> listener = null;
+    private NodeStructure value = Variables.PENDING_NODE_STRUCTURE;
+    private boolean wasRun = false;
+
+    static class Probe implements Runnable {
+
+        private VariableNode node;
+        public NodeStructure result;
+
+        public Probe(VariableNode node) {
+            this.node = node;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public void run() {
+            try {
+                result = NodeStructureRequest.get(node);
+                node.support.structureCache.put(node.node, result, 1000000000L);
+            } catch (NodeManagerException e) {
+                e.printStackTrace();
+            }
+        }
+
+    }
+
+    public NodeStructureRequest(VariableNode node) {
+        super(node);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void register(ReadGraph graph, final Listener<NodeStructure> procedure) {
+
+        if(procedure.isDisposed()) {
+
+            // We are not listening
+            NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);
+
+            if(result != null) {
+                // Return cached value immediately
+                procedure.execute(result);
+            } else {
+                NodeStructureRequest.Probe probe = new Probe(parameter);
+                parameter.support.manager.getRealm().asyncExec(probe);
+                if(probe.result != null) {
+                    procedure.execute(probe.result);
+                } else {
+                    procedure.execute(Variables.PENDING_NODE_STRUCTURE);
+                }
+            }
+
+            return;
+
+        }
+
+        // We need to listen
+        listener = procedure;
+        // Register listening
+        parameter.support.manager.addNodeListener(parameter.node, this);
+        synchronized(this) {
+            if(!wasRun) {
+                NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);
+                if(result != null) {
+                    procedure.execute(result);
+                } else {
+                    procedure.execute(Variables.PENDING_NODE_STRUCTURE);
+                }
+            }
+        }
+
+    }
+
+    static class NodeListener implements VariableNodeReadRunnable {
+
+        private VariableNode node;
+        private NodeStructureRequest request;
+
+        public NodeListener(VariableNode node, NodeStructureRequest 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() {
+        parameter.support.manager.removeNodeListener(parameter.node, this);
+        parameter.support.structureCache.removeListening(parameter.node);
+        listener = null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static NodeStructure get(VariableNode parameter) throws NodeManagerException {
+        List<?> children = parameter.support.manager.getChildren(parameter.node);
+        List<?> properties = parameter.support.manager.getProperties(parameter.node);
+        Map<String, Object> childMap = Collections.emptyMap();
+        Map<String, Object> propertyMap = childMap;
+        if(!children.isEmpty()) {
+            childMap = new THashMap<>(children.size());
+            for(Object o : children) {
+                String name = parameter.support.manager.getName(o);
+                childMap.put(name, o);
+            }
+        }
+        if(!properties.isEmpty()) {
+            propertyMap = new THashMap<>(properties.size());
+            for(Object o : properties) {
+                String name = parameter.support.manager.getName(o);
+                propertyMap.put(name, o);
+            }
+        }
+        return new NodeStructure(childMap, propertyMap);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public synchronized void run() {
+        try {
+            // Cache this value with infinite cache time since we are listening
+            NodeStructure newValue = get(parameter);
+            if (wasRun && ObjectUtils.objectEquals(value, newValue)) {
+                //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node);
+                return;
+            }
+            value = newValue;
+            parameter.support.structureCache.put(parameter.node, value);
+        } catch (Throwable e) {
+            // Must catch everything to prevent DB client from getting stuck.
+            LOGGER.error("Error while computing node structure", e);
+            // Invoke the exception method of the listener
+            Listener<NodeStructure> 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<NodeStructure> listener = this.listener;
+        if (listener != null) {
+            listener.execute(value);
+            wasRun = true;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "NodeStructureRequest.run @ " + System.identityHashCode(this);
+    }
 
 }
\ No newline at end of file
index 140ee8fa0841648805803c027686ac2b6efb2441..b44f16b30eeedc3ca7ee15fd9d023e0505703a9b 100644 (file)
@@ -110,9 +110,7 @@ class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Bindi
         // Register listening
         node.support.manager.addNodeListener(node.node, this);
         synchronized(this) {
-            if(wasRun) {
-                procedure.execute(value);
-            } else {
+            if(!wasRun) {
                 Variant result = (Variant)node.support.valueCache.get(node.node);
                 if(result != null) {
                     procedure.execute(result);
@@ -219,8 +217,10 @@ class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Bindi
                 LOGGER.error("Error while computing node value", e);
             // Invoke the exception method of the listener
             Listener<Variant> listener = this.listener;
-            if (listener != null) listener.exception(new DatabaseException("External data access error", e));
-            wasRun = true;
+            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.
@@ -228,8 +228,8 @@ class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Bindi
         if (listener != null) {
             //System.out.println("LISTENER " + listener + " invoked with value " + value);
             listener.execute(value);
+            wasRun = true;
         }
-        wasRun = true;
     }
 
     @Override