]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/BlockingAsyncProcedure.java
Wrong graph was used when performing async query from session
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / BlockingAsyncProcedure.java
index ad9f1643829fe506ac57125edaf2bc724a249d05..8f96bb9e6d3a51a48c7b98baa40f962fc83f5617 100644 (file)
 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.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;
-
+import org.simantics.db.request.AsyncRead;
 public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
 
     private static final Object NO_RESULT = new Object();
 
     private final Object key;
-    private final ReadGraphImpl graph;
+    private final ReadGraphImpl queryGraph;
+    private final ReadGraphImpl callerGraph;
     private final AsyncProcedure<Result> procedure;
-
+    private PendingTaskSupport pendingTaskSupport;
+    private final boolean needsToBlock;
     private Object result = NO_RESULT;
     private Throwable exception = null;
 
-    public BlockingAsyncProcedure(ReadGraphImpl graph, AsyncProcedure<Result> procedure, Object key) {
+    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);
+            
+        }, needsToBlock);
+        
+        queryGraph.asyncBarrier.inc();
+
         this.procedure = procedure;
         this.key = key;
-        this.graph = graph;
-        this.graph.asyncBarrier.inc();
+        this.queryGraph.asyncBarrier.inc();
+        this.callerGraph = callerGraph;
+        this.needsToBlock = needsToBlock;
+        if (BarrierTracing.BOOKKEEPING) {
+            BarrierTracing.registerBAP(this);
+        }
     }
 
     @Override
-    public void execute(AsyncReadGraph graph, Result result) {
+    public void execute(AsyncReadGraph graph_, Result result) {
+        
         this.result = result;
-        this.graph.asyncBarrier.dec();
-        try {
-            if(procedure != null) procedure.execute(graph, result);
-        } catch (Throwable throwable) {
-            Logger.defaultLogError("AsyncProcedure.execute threw for " + procedure, throwable);
-        }
+        queryGraph.asyncBarrier.dec();
+        
     }
 
     @Override
-    public void exception(AsyncReadGraph graph, Throwable t) {
+    public void exception(AsyncReadGraph graph_, Throwable t) {
+
         this.exception = t;
-        try {
-            if(procedure != null) procedure.exception(graph, t);
-        } catch (Throwable throwable) {
-            Logger.defaultLogError("AsyncProcedure.exception threw for " + procedure, throwable);
-        } finally {
-            this.graph.asyncBarrier.dec();
-        }
+        queryGraph.asyncBarrier.dec();
+        
     }
-
+    
     public void waitBarrier() {
-        graph.asyncBarrier.waitBarrier(key, graph);
+        queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
+    }
+    
+    public void dec() {
+
+        queryGraph.asyncBarrier.dec();
+        
     }
 
     @SuppressWarnings("unchecked")
     public Result get() throws DatabaseException {
 
-        graph.asyncBarrier.waitBarrier(key, graph);
+        if(needsToBlock)
+            queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
 
         if(exception != null) {
             if(exception instanceof DatabaseException) throw (DatabaseException)exception;
@@ -76,10 +98,6 @@ public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
 
     }
 
-    public boolean isDone() {
-        return graph.asyncBarrier.get() == 0;
-    }
-
     @SuppressWarnings("unchecked")
     public Result getResult() {
         return (Result)result;
@@ -93,5 +111,69 @@ public class BlockingAsyncProcedure<Result> implements AsyncProcedure<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, null, needsToBlock);
+        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);
+        }
+
+    }
+    
+    public void print() {
+        System.err.println("BlockingAsyncProcedure");
+        System.err.println("-key: " + key);
+        System.err.println("-queryGraph: " + queryGraph);
+        System.err.println("-callerGraph: " + callerGraph);
+        System.err.println("-procedure: " + procedure);
+        System.err.println("-pendingTaskSupport: " + pendingTaskSupport);
+        System.err.println("-result: " + result);
+        System.err.println("-exception: " + exception);
+    }
+    
+    public Result performSync(AsyncRead<Result> request) throws DatabaseException {
+        try {
+            request.perform(queryGraph, this);
+        } finally {
+            dec();
+        }
+        return get();
+    }
+
+    public void performAsync(AsyncRead<Result> request) throws DatabaseException {
+        try {
+            request.perform(queryGraph, this);
+        } finally {
+            dec();
+        }
+    }
 
 }