]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AsyncReadEntry.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / AsyncReadEntry.java
index 00abbebf65859e76d0e8dad481d01097cab04621..2fdb43d113332e4f33b6b131685fd8c80c112b22 100644 (file)
  *******************************************************************************/
 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.exception.RuntimeDatabaseException;
 import org.simantics.db.impl.BlockingAsyncProcedure;
-import org.simantics.db.impl.DebugPolicy;
 import org.simantics.db.impl.graph.ReadGraphImpl;
+import org.simantics.db.impl.query.QueryProcessor.SessionTask;
 import org.simantics.db.procedure.AsyncProcedure;
 import org.simantics.db.request.AsyncRead;
+import org.simantics.utils.Development;
 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> request;
+    protected AsyncRead<T> id;
+    protected PendingTaskSupport pendingTaskSupport;
 
     AsyncReadEntry(AsyncRead<T> request) {
-        this.request = request;
-        if (DebugPolicy.QUERY_STATE)
-            System.out.println("[QUERY STATE]: created " + this);
+        this.id = request;
+               if (Development.DEVELOPMENT) {
+                       if(Development.<Boolean>getProperty(DevelopmentKeys.CACHE_ENTRY_STATE, Bindings.BOOLEAN)) {
+                       System.err.println("[QUERY STATE]: created " + this);
+                       }
+               }
     }
 
     @Override
     int makeHash() {
-        return request.hashCode();
+        return id.hashCode();
     }
 
     @Override
     public Object getOriginalRequest() {
-        return request;
+        return id;
     }
 
     @Override
@@ -70,7 +78,7 @@ final public class AsyncReadEntry<T> extends CacheEntryBase<AsyncProcedure<T>> i
 
                 try {
 
-                    BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure<>(graph, new AsyncProcedure<T>() {
+                    BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure(graph, AsyncReadEntry.this, new AsyncProcedure<T>() {
 
                         @Override
                         public void execute(AsyncReadGraph graph, T result) {
@@ -83,11 +91,9 @@ final public class AsyncReadEntry<T> extends CacheEntryBase<AsyncProcedure<T>> i
                             except(t);
                         }
 
-                    }, request);
-
-                    request.perform(graph, proc);
-
-                    proc.get();
+                    }, id, true);
+                    
+                    proc.performSync(id);
 
                 } catch (Throwable t) {
                     except(t);
@@ -102,17 +108,17 @@ final public class AsyncReadEntry<T> extends CacheEntryBase<AsyncProcedure<T>> i
 
             @Override
             public int type() {
-                return request.getFlags();
+                return id.getFlags();
             }
 
             @Override
             public String toString() {
-                if (request == null)
+                if (id == null)
                     return "DISCARDED";
                 else if (isExcepted())
-                    return request.toString() + " " + getResult();
+                    return id.toString() + " " + getResult();
                 else
-                    return request.toString() + " " + statusOrException;
+                    return id.toString() + " " + statusOrException;
             }
 
         };
@@ -133,7 +139,8 @@ final public class AsyncReadEntry<T> extends CacheEntryBase<AsyncProcedure<T>> i
         } else {
 
             try {
-                proc.execute(graph, (T) getResult());
+                T result = (T) getResult();
+                proc.execute(graph, result);
             } catch (Throwable t) {
                 LOGGER.error("performFromCache proc.execute failed", t);
             }
@@ -144,68 +151,71 @@ final public class AsyncReadEntry<T> extends CacheEntryBase<AsyncProcedure<T>> i
 
     }
 
-    public static <T> void computeForEach(ReadGraphImpl parentGraph, AsyncRead<T> request, AsyncReadEntry<T> entry,
-            AsyncProcedure<T> procedure_) throws DatabaseException {
-
-        AsyncProcedure<T> procedure = entry != null ? entry : procedure_;
-
-        ReadGraphImpl queryGraph = parentGraph.withParent(entry);
-        
-        BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure<>(queryGraph, new AsyncProcedure<T>() {
+    public static <T> T computeForEach(ReadGraphImpl callerGraph, AsyncRead<T> request, AsyncReadEntry<T> entry,
+            AsyncProcedure<T> procedure_, boolean needsToBlock) throws DatabaseException {
 
-            @Override
-            public void execute(AsyncReadGraph returnGraph, T result) {
-                try {
-                    procedure.execute(parentGraph, result);
-                } catch (Throwable t) {
-                    LOGGER.error("computeForEach procedure.execute failed", t);
-                }
-            }
-
-            @Override
-            public void exception(AsyncReadGraph returnGraph, Throwable t) {
-                try {
-                    procedure.exception(parentGraph, t);
-                } catch (Throwable t2) {
-                    LOGGER.error("computeForEach procedure.exception failed", t2);
-                }
-            }
-
-            @Override
-            public String toString() {
-                return procedure.toString();
-            }
-
-        }, request);
-
-        request.perform(queryGraph, proc);
-        
-        proc.get();
-
-        if (entry != null)
-            entry.performFromCache(parentGraph, procedure_);
+        BlockingAsyncProcedure<T> proc = new BlockingAsyncProcedure(callerGraph, entry, procedure_, request, needsToBlock);
+        if(needsToBlock) {
+            return proc.performSync(request);
+        } else {
+            proc.performAsync(request);
+            return null;
+        }
 
     }
 
     @Override
     public String toString() {
         if (isDiscarded())
-            return "DISCARDED " + request.toString();
+            return "DISCARDED " + id.toString();
         else if (isExcepted())
-            return request.toString() + " " + getResult();
+            return id.toString() + " " + getResult();
         else
-            return request.toString() + " " + statusOrException;
+            return id.toString() + " " + statusOrException;
     }
 
     @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 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);
+        }
     }
 
     @Override
-    public void exception(AsyncReadGraph graph, Throwable throwable) {
-        except(throwable);
+    public String classId() {
+        return null;
     }
 
 }