]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java
Merge branch 'private/db-threads' into private/threads-testing
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / graph / ReadGraphImpl.java
index b853ed5191e3654f5cfbddea240b33c48b77bff1..6998ee55e127afa761b7aad2499264bc816588d8 100644 (file)
@@ -26,6 +26,7 @@ import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Map;
 import java.util.Set;
 import java.util.function.Consumer;
 
@@ -87,6 +88,7 @@ import org.simantics.db.common.primitiverequest.UniqueAdapter;
 import org.simantics.db.common.primitiverequest.Value;
 import org.simantics.db.common.primitiverequest.ValueImplied;
 import org.simantics.db.common.primitiverequest.VariantValueImplied;
+import org.simantics.db.common.procedure.BlockingAsyncProcedure;
 import org.simantics.db.common.procedure.adapter.AsyncMultiProcedureAdapter;
 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
@@ -111,6 +113,7 @@ import org.simantics.db.common.procedure.wrapper.SyncToAsyncProcedure;
 import org.simantics.db.common.procedure.wrapper.SyncToAsyncSetProcedure;
 import org.simantics.db.common.request.AdaptValue;
 import org.simantics.db.common.request.ResourceRead;
+import org.simantics.db.common.utils.Functions;
 import org.simantics.db.common.utils.Logger;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.common.validation.L0Validations;
@@ -134,12 +137,16 @@ import org.simantics.db.impl.ResourceImpl;
 import org.simantics.db.impl.internal.RandomAccessValueSupport;
 import org.simantics.db.impl.internal.ResourceData;
 import org.simantics.db.impl.procedure.CallWrappedSingleQueryProcedure4;
+import org.simantics.db.impl.procedure.InternalProcedure;
 import org.simantics.db.impl.procedure.ResultCallWrappedQueryProcedure4;
 import org.simantics.db.impl.procedure.ResultCallWrappedSingleQueryProcedure4;
 import org.simantics.db.impl.query.CacheEntry;
+import org.simantics.db.impl.query.QueryCache;
+import org.simantics.db.impl.query.QueryCacheBase;
 import org.simantics.db.impl.query.QueryProcessor;
 import org.simantics.db.impl.query.QuerySupport;
 import org.simantics.db.impl.query.TripleIntProcedure;
+import org.simantics.db.impl.query.QueryProcessor.SessionTask;
 import org.simantics.db.impl.support.ResourceSupport;
 import org.simantics.db.procedure.AsyncListener;
 import org.simantics.db.procedure.AsyncMultiListener;
@@ -177,6 +184,7 @@ import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.compiler.types.exceptions.SCLTypeParseException;
 import org.simantics.scl.reflection.ReflectionUtils;
 import org.simantics.scl.reflection.ValueNotFoundException;
+import org.simantics.scl.runtime.function.Function1;
 import org.simantics.scl.runtime.function.Function3;
 import org.simantics.utils.DataContainer;
 import org.simantics.utils.Development;
@@ -278,12 +286,21 @@ public class ReadGraphImpl implements ReadGraph {
 
                try {
 
-                       return syncRequest(new org.simantics.db.common.primitiverequest.Resource(
-                                       id));
+//                     assert (id != null);
+//                     assert (procedure != null);
+//
+//                     processor.forResource(this, id, procedure);
+//
+////                   return syncRequest(new org.simantics.db.common.primitiverequest.Resource(
+////                                   id));
+                       
+                       Integer rid = QueryCache.resultURIToResource(this, id, parent, null);
+                       if(rid == 0) throw new ResourceNotFoundException(id);
+                       return processor.querySupport.getResource(rid);
 
                } catch (ResourceNotFoundException e) {
 
-                       throw new ResourceNotFoundException(e);
+                       throw new ResourceNotFoundException(id, e);
 
                } catch (ValidationException e) {
 
@@ -309,8 +326,10 @@ public class ReadGraphImpl implements ReadGraph {
 
                try {
 
-                       return syncRequest(new org.simantics.db.common.primitiverequest.Resource(
-                                       id));
+                       return getResource(id);
+                       
+//                     return syncRequest(new org.simantics.db.common.primitiverequest.Resource(
+//                                     id));
 
                } catch (ResourceNotFoundException e) {
                        
@@ -331,6 +350,32 @@ public class ReadGraphImpl implements ReadGraph {
                }
 
        }
+       
+       @Override
+       public Map<String, Resource> getChildren(Resource resource) throws ValidationException, ServiceException {
+               
+               assert (resource != null);
+
+               try {
+
+                       int rId = processor.querySupport.getId(resource);
+                       return QueryCache.resultChildMap(this, rId, parent, null);
+
+               } catch (ValidationException e) {
+
+                       throw new ValidationException(e);
+
+               } catch (ServiceException e) {
+
+                       throw new ServiceException(e);
+
+               } catch (DatabaseException e) {
+
+                       throw new ServiceException(INTERNAL_ERROR_STRING, e);
+
+               }
+               
+       }
 
        final public Resource getRootLibrary() {
                return processor.getRootLibraryResource();
@@ -347,7 +392,7 @@ public class ReadGraphImpl implements ReadGraph {
 
                } catch (ResourceNotFoundException e) {
 
-                       throw new ResourceNotFoundException(e);
+                       throw new ResourceNotFoundException(id, e);
 
                } catch (ServiceException e) {
 
@@ -900,83 +945,57 @@ public class ReadGraphImpl implements ReadGraph {
                if( relation == null) throw new IllegalArgumentException("relation can not be null");
 
                try {
-
                        int single = processor.getSingleObject(this, subject, relation);
-                       if(single == 0) throw new NoSingleResultException("subject=" + subject + " relation="+relation);
+                       if (single == 0) {
+                               if (EMPTY_RESOURCE_CHECK) {
+                                       if (!hasStatement(subject)) {
+                                               throw new EmptyResourceException("Resource " + debugString(subject));
+                                       }
+                               }
+                               throw new NoSingleResultException("No single object for subject " + debugString(subject)
+                                               + " and relation " + debugString(relation), single);
+                       }
                        return processor.querySupport.getResource(single);
-
                } catch (NoSingleResultException e) {
-                   
-                   if(EMPTY_RESOURCE_CHECK) {
-                       if(!hasStatement(subject)) throw new EmptyResourceException("Resource " + debugString(subject));
-                   }
-                   
-                       throw new NoSingleResultException("No single object for subject "
-                                       + debugString(subject) + " and relation "
-                                       + debugString(relation), e);
-            
+                       throw e;
                } catch (DatabaseException e) {
-                   
                        throw new ServiceException(e);
-                       
                } 
-               
        }
 
        @Override
-       final public Statement getSingleStatement(final Resource subject,
-                       final Resource relation) throws NoSingleResultException,
-                       ManyObjectsForFunctionalRelationException, ServiceException {
-
+       final public Statement getSingleStatement(final Resource subject, final Resource relation) throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
                assert (subject != null);
                assert (relation != null);
-
                try {
-
                        Collection<Statement> statements = getStatements(subject, relation);
-                       if(statements.size() == 1) return statements.iterator().next();
-                       else throw new NoSingleResultException("");
-
-        } catch (NoSingleResultException e) {
-            
-            if(EMPTY_RESOURCE_CHECK) {
-                if(!hasStatement(subject)) throw new EmptyResourceException("Resource " + debugString(subject));
-            }
-            
-            throw new NoSingleResultException("No single statement for subject "
-                    + debugString(subject) + " and relation "
-                    + debugString(relation), e);
-            
-        } catch (DatabaseException e) {
-            
-            throw new ServiceException(e);
-            
-        } 
-
+                       if (statements.size() == 1) {
+                               return statements.iterator().next();
+                       } else {
+                               if (EMPTY_RESOURCE_CHECK)
+                                       if (!hasStatement(subject))
+                                               throw new EmptyResourceException("Resource " + debugString(subject));
+                               throw new NoSingleResultException("No single statement for subject " + debugString(subject)
+                                               + " and relation " + debugString(relation), statements.size());
+                       }
+               } catch (ServiceException e) {
+                       throw new ServiceException(e);
+               } 
        }
 
        @Override
-       final public Resource getSingleType(final Resource subject) throws NoSingleResultException,
-                       ServiceException {
-
+       final public Resource getSingleType(final Resource subject) throws NoSingleResultException, ServiceException {
                assert (subject != null);
-
                try {
-
                        ArrayList<Resource> principalTypes = (ArrayList<Resource>)getPrincipalTypes(subject);
-                       if(principalTypes.size() == 1) return principalTypes.get(0);
-                       else throw new NoSingleResultException("");
-
-               } catch (NoSingleResultException e) {
-
-                       throw new NoSingleResultException(e);
-
+                       if (principalTypes.size() == 1) {
+                           return principalTypes.get(0);
+                       } else {
+                           throw new NoSingleResultException("No single type for subject " + debugString(subject), principalTypes.size());
+                       }
                } catch (ServiceException e) {
-
                        throw new ServiceException(e);
-
                } 
-
        }
 
        @Override
@@ -988,23 +1007,10 @@ public class ReadGraphImpl implements ReadGraph {
                assert (baseType != null);
 
                try {
-
                        return syncRequest(new SingleType(subject, baseType));
-
-               } catch (NoSingleResultException e) {
-
-                       throw new NoSingleResultException(new NoSingleResultException("subject=" + subject + ", baseType=" + baseType, e));
-
-               } catch (ServiceException e) {
-
-                       throw new ServiceException(e);
-
                } catch (DatabaseException e) {
-
-                       throw new ServiceException(INTERNAL_ERROR_STRING, e);
-
+                   throw new NoSingleResultException("subject=" + subject + ", baseType=" + baseType, 0, e);
                }
-
        }
 
        @Override
@@ -1142,16 +1148,11 @@ public class ReadGraphImpl implements ReadGraph {
                assert (relation != null);
 
                try {
-
                        Resource object = getSingleObject(subject, relation);
                        return getValue(object);
-                       
                } catch (NoSingleResultException e) {
-
-                       throw new NoSingleResultException(e);
-
+                       throw new NoSingleResultException("No single value found for subject " + debugString(subject) + " and relation " + debugString(relation), e.getResultCount(), e);
                } catch (DoesNotContainValueException e) {
-
                        try {
                                Layer0 L0 = processor.getL0(this);
                                Resource object = getPossibleObject(subject, relation);
@@ -1159,23 +1160,19 @@ public class ReadGraphImpl implements ReadGraph {
                                        if(isInstanceOf(object, L0.Literal)) {
                                                throw new DoesNotContainValueException(e);
                                        } else {
-                                               throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)");
+                                               throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)", e);
                                        }
                                } else {
-                                       throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value");
+                                       throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value", e);
                                }
                        } catch (DoesNotContainValueException e2) {
                                throw e2;
                        } catch (DatabaseException e2) {
                                throw new InternalException("The client failed to analyse the cause of the following exception", e);
                        }
-
                } catch (ServiceException e) {
-
                        throw new ServiceException(e);
-
-               } 
-               
+               }
        }
 
     @Override
@@ -1186,16 +1183,11 @@ public class ReadGraphImpl implements ReadGraph {
         assert (relation != null);
 
         try {
-
             Resource object = getSingleObject(subject, relation);
             return getVariantValue(object);
-            
         } catch (NoSingleResultException e) {
-
-            throw new NoSingleResultException(e);
-
+            throw new NoSingleResultException("No single object for subject " + debugString(subject) + " and relation " + debugString(relation), e.getResultCount(), e);
         } catch (DoesNotContainValueException e) {
-
             try {
                 Layer0 L0 = processor.getL0(this);
                 Resource object = getPossibleObject(subject, relation);
@@ -1203,23 +1195,19 @@ public class ReadGraphImpl implements ReadGraph {
                     if(isInstanceOf(object, L0.Literal)) {
                         throw new DoesNotContainValueException(e);
                     } else {
-                        throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)");
+                        throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)", e);
                     }
                 } else {
-                    throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value");
+                    throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value", e);
                 }
             } catch (DoesNotContainValueException e2) {
                 throw e2;
             } catch (DatabaseException e2) {
                 throw new InternalException("The client failed to analyse the cause of the following exception", e);
             }
-
         } catch (ServiceException e) {
-
             throw new ServiceException(e);
-
         } 
-        
     }
     
        @Override
@@ -1230,40 +1218,23 @@ public class ReadGraphImpl implements ReadGraph {
                assert (relation != null);
 
                try {
-
                        Resource object = getSingleObject(subject, relation);
                        return getValue(object, binding);
-
                } catch (NoSingleResultException e) {
-
                    String message = "";
-                   
                    try {
-                   
                    String subjectName = NameUtils.getSafeName(this, subject, true);
                    String relationName = NameUtils.getSafeName(this, relation, true);
                    message = "Subject: " + subjectName + ", Relation: " + relationName;
-
                    } catch (DatabaseException e2) {
                        
                    }
-
-            throw new NoSingleResultException(message);
-                   
+            throw new NoSingleResultException(message, e.getResultCount(), e);
                } catch (DoesNotContainValueException e) {
-
                        throw new DoesNotContainValueException(e);
-
                } catch (ServiceException e) {
-
                        throw new ServiceException(e);
-
-               } catch (DatabaseException e) {
-
-                       throw new ServiceException(INTERNAL_ERROR_STRING, e);
-
                }
-
        }
 
        @Override
@@ -1949,7 +1920,7 @@ public class ReadGraphImpl implements ReadGraph {
 
        }
 
-       final AsyncProcedure NONE = new AsyncProcedure() {
+       final AsyncProcedure<?> NONE = new AsyncProcedure<Object>() {
 
                @Override
                public void execute(AsyncReadGraph graph, Object result) {
@@ -1970,35 +1941,38 @@ public class ReadGraphImpl implements ReadGraph {
 
                assert (request != null);
 
-               if (parent != null) {
-
-                       try {
-                               return processor.queryRead(this, request, parent, null, null);
-                       } catch (Throwable e) {
-                               if(e instanceof DatabaseException) throw (DatabaseException)e;
-                               else throw new DatabaseException(e);
-                       }
-
-               } else {
-
-                       try {
-
-                               return processor.tryQuery(this, request);
-
-                       } catch (Throwable throwable) {
-
-                               //Logger.defaultLogError("Internal read request failure", throwable);
-
-                               if (throwable instanceof DatabaseException)
-                                       throw (DatabaseException) throwable;
-                               else
-                                       throw new DatabaseException(
-                                                       "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)",
-                                                       throwable);
-
-                       }
+               return QueryCache.resultReadEntry(this, request, parent, null, null);
+               
+               //return processor.query(this, request, parent, null, null);
 
-               }
+//             if (parent != null) {
+//
+//                     try {
+//                     } catch (Throwable e) {
+//                             if(e instanceof DatabaseException) throw (DatabaseException)e;
+//                             else throw new DatabaseException(e);
+//                     }
+//
+//             } else {
+//
+//                     try {
+//
+//                             return processor.tryQuery(this, request);
+//
+//                     } catch (Throwable throwable) {
+//
+//                             //Logger.defaultLogError("Internal read request failure", throwable);
+//
+//                             if (throwable instanceof DatabaseException)
+//                                     throw (DatabaseException) throwable;
+//                             else
+//                                     throw new DatabaseException(
+//                                                     "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)",
+//                                                     throwable);
+//
+//                     }
+//
+//             }
                
        }
 
@@ -2021,42 +1995,46 @@ public class ReadGraphImpl implements ReadGraph {
 
                ListenerBase listener = procedure != null ? getListenerBase(procedure) : null;
 
-               if (parent != null || listener != null) {
-                       
-                       try {
-                return processor.queryRead(this, request, parent, procedure, listener);
-            } catch (Throwable e) {
-                if(e instanceof DatabaseException) throw (DatabaseException)e;
-                else throw new DatabaseException(e);
-            }
-
-               } else {
-
-                       try {
-
-                               T t = processor.tryQuery(this, request);
-                               if(procedure != null)
-                                       procedure.execute(this, t);
-
-                               return t;
-
-                       } catch (Throwable throwable) {
-
-                               Logger.defaultLogError("Internal read request failure", throwable);
-
-                               if(procedure != null)
-                                       procedure.exception(this, throwable);
-                               
-                               if (throwable instanceof DatabaseException)
-                                       throw (DatabaseException) throwable;
-                               else
-                                       throw new DatabaseException(
-                                                       "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)",
-                                                       throwable);
-
-                       }
+               return QueryCache.resultReadEntry(this, request, parent, listener, procedure);
+               
+//        return processor.query(this, request, parent, procedure, listener);
+        
 
-               }
+//             if (parent != null || listener != null) {
+//                     
+//                     try {
+//            } catch (Throwable e) {
+//                if(e instanceof DatabaseException) throw (DatabaseException)e;
+//                else throw new DatabaseException(e);
+//            }
+//
+//             } else {
+//
+//                     try {
+//
+//                             T t = processor.tryQuery(this, request);
+//                             if(procedure != null)
+//                                     procedure.execute(this, t);
+//
+//                             return t;
+//
+//                     } catch (Throwable throwable) {
+//
+//                             Logger.defaultLogError("Internal read request failure", throwable);
+//
+//                             if(procedure != null)
+//                                     procedure.exception(this, throwable);
+//                             
+//                             if (throwable instanceof DatabaseException)
+//                                     throw (DatabaseException) throwable;
+//                             else
+//                                     throw new DatabaseException(
+//                                                     "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)",
+//                                                     throwable);
+//
+//                     }
+//
+//             }
 
        }
 
@@ -2096,7 +2074,7 @@ public class ReadGraphImpl implements ReadGraph {
                                        throw (DatabaseException) exception;
                                else
                                        throw new DatabaseException(
-                                                       "Unexpected exception in ReadGraph.syncRequest(AsyncMultiRead)",
+                                                       "Unexpected exception in ReadGraph.syncRequest(AsyncRead)",
                                                        exception);
                        }
                }
@@ -2112,10 +2090,12 @@ public class ReadGraphImpl implements ReadGraph {
                        throws DatabaseException {
 
                assert (request != null);
-               AsyncReadProcedure<T> procedure = new AsyncReadProcedure<T>();
-               syncRequest(request, procedure);
-               procedure.checkAndThrow();
-               return procedure.result;
+//             AsyncReadProcedure<T> procedure = new AsyncReadProcedure<T>();
+               BlockingAsyncProcedure<T> ap = new BlockingAsyncProcedure<>(this, null, request);
+               syncRequest(request, ap);
+               return ap.get();
+//             procedure.checkAndThrow();
+//             return procedure.result;
                
 //             return syncRequest(request, new AsyncProcedureAdapter<T>());
 
@@ -2145,71 +2125,77 @@ public class ReadGraphImpl implements ReadGraph {
 
                assert (request != null);
 
-               // System.out.println("syncRequest " + request + " syncParent=" +
-               // syncParent);
-
                ListenerBase listener = getListenerBase(procedure);
 
-               if (parent != null || listener != null || ((request.getFlags() & RequestFlags.SCHEDULE) > 0)) {
-
-                       Object syncParent = request;
-
-//                     final ReadGraphImpl newGraph = newSync();
-
-                       final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
-                                       procedure, request);
-                       
-                       processor.query(this, request, parent, wrapper, listener);
-
-//                     newGraph.waitAsync(syncParent);
-                       
-                       Throwable e = wrapper.getException();
-                       if (e != null) {
-                               // The request was async - produce meaningful stack trace by
-                               // wrapping
-                               if (e instanceof DatabaseException)
-                                       throw (DatabaseException) e;
-                               else
-                                       throw new DatabaseException(e);
-                       }
-                       
-                       return wrapper.getResult();
-
-               } else {
-
-                       // System.out.println("direct call " + request );
-
-                       // Do not set the sync state.parent for external threads
-                       Object syncParent = request;
-
-//                     final ReadGraphImpl newGraph = newSync();
-
-                       final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
-                                       procedure, request);
-
-                       try {
-
-                               processor.tryQuery(this, request, wrapper);
-
-                       } catch (Throwable t) {
-
-                               wrapper.exception(this, t);
-
-                       }
-
-                       Throwable e = wrapper.getException();
-                       if (e != null) {
-                               // The request was async - produce meaningful stack trace by
-                               // wrapping
-                               if (e instanceof DatabaseException)
-                                       throw (DatabaseException) e;
-                               else
-                                       throw new DatabaseException(e);
-                       }
-                       
-                       return wrapper.getResult();
+               BlockingAsyncProcedure<T> ap = new BlockingAsyncProcedure<>(this, procedure, request);
+               
+//             final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
+//                             procedure, request);
+               
+               QueryCache.runnerAsyncReadEntry(this, request, parent, listener, ap, true);
+               
+               //processor.query(this, request, parent, wrapper, listener);
+               
+               return ap.get();
+               
+//             return wrapper.getResult();
 
-               }
+//             if (parent != null || listener != null || ((request.getFlags() & RequestFlags.SCHEDULE) > 0)) {
+//
+////                   Object syncParent = request;
+//
+////                   final ReadGraphImpl newGraph = newSync();
+//
+//
+////                   newGraph.waitAsync(syncParent);
+//                     
+//                     Throwable e = wrapper.getException();
+//                     if (e != null) {
+//                             // The request was async - produce meaningful stack trace by
+//                             // wrapping
+//                             if (e instanceof DatabaseException)
+//                                     throw (DatabaseException) e;
+//                             else
+//                                     throw new DatabaseException(e);
+//                     }
+//                     
+//                     return wrapper.getResult();
+//
+//             } else {
+//
+//                     // System.out.println("direct call " + request );
+//
+//                     // Do not set the sync state.parent for external threads
+////                   Object syncParent = request;
+//
+////                   final ReadGraphImpl newGraph = newSync();
+//
+//                     final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
+//                                     procedure, request);
+//
+//                     try {
+//
+//                             processor.tryQuery(this, request, wrapper);
+//
+//                     } catch (Throwable t) {
+//
+//                             wrapper.exception(this, t);
+//
+//                     }
+//
+//                     Throwable e = wrapper.getException();
+//                     if (e != null) {
+//                             // The request was async - produce meaningful stack trace by
+//                             // wrapping
+//                             if (e instanceof DatabaseException)
+//                                     throw (DatabaseException) e;
+//                             else
+//                                     throw new DatabaseException(e);
+//                     }
+//                     
+//                     return wrapper.getResult();
+//
+//             }
 
        }
 
@@ -2217,40 +2203,17 @@ public class ReadGraphImpl implements ReadGraph {
 
                assert (request != null);
 
-               // System.out.println("syncRequest " + request + " syncParent=" +
-               // syncParent);
-
                ListenerBase listener = getListenerBase(procedure);
+               assert(listener == null);
 
-               if (parent != null || listener != null || ((request.getFlags() & RequestFlags.SCHEDULE) > 0)) {
-
-//                     final ReadGraphImpl newGraph = newSync();
-
-                       final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
-                                       procedure, request);
-
-                       processor.query(this, request, parent, wrapper, listener);
-
-               } else {
-
-                       try {
-
-//                             final ReadGraphImpl newGraph = newSync();
-                               processor.tryQuery(this, request, procedure);
-//                             newGraph.waitAsync(null);
-                               waitAsyncProcedure(procedure);
-
-                       } catch (Throwable t) {
-                               if(Development.DEVELOPMENT) {
-                                       if(Development.<Boolean>getProperty(DevelopmentKeys.WRITEGRAPH_EXCEPTION_STACKTRACES, Bindings.BOOLEAN)) {
-                                       t.printStackTrace();
-                                       }
-                               }
-                               procedure.exception(this, t);
-                               waitAsyncProcedure(procedure);
-                       }
+               BlockingAsyncProcedure<T> ap = new BlockingAsyncProcedure<>(this, procedure, request);
+               
+//             final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
+//                             procedure, request);
 
-               }
+               QueryCache.runnerAsyncReadEntry(this, request, parent, listener, ap, true);
+               
+               ap.get();
 
        }
 
@@ -2342,7 +2305,7 @@ public class ReadGraphImpl implements ReadGraph {
 
                if (parent != null || listener != null) {
 
-                       Object syncParent = request;
+//                     Object syncParent = request;
 
 //                     final ReadGraphImpl newGraph = newSync();
 
@@ -2352,7 +2315,7 @@ public class ReadGraphImpl implements ReadGraph {
 
                } else {
 
-                       Object syncParent = request;
+//                     Object syncParent = request;
 
 //                     final ReadGraphImpl newGraph = newSync();
 
@@ -2471,7 +2434,7 @@ public class ReadGraphImpl implements ReadGraph {
 
                if (parent != null || listener != null) {
 
-                       Object syncParent = request;
+//                     Object syncParent = request;
 
 //                     final ReadGraphImpl newGraph = newSync();
 
@@ -2519,7 +2482,7 @@ public class ReadGraphImpl implements ReadGraph {
 
                if (parent != null || listener != null) {
 
-                       Object syncParent = request;
+//                     Object syncParent = request;
 
 //                     final ReadGraphImpl newGraph = newSync();
 
@@ -2529,7 +2492,7 @@ public class ReadGraphImpl implements ReadGraph {
 
                } else {
 
-                       Object syncParent = request;
+//                     Object syncParent = request;
 
 //                     final ReadGraphImpl newGraph = newSync();
 
@@ -2616,70 +2579,83 @@ public class ReadGraphImpl implements ReadGraph {
        final public <T> T syncRequest(final ExternalRead<T> request,
                        final Procedure<T> procedure) throws DatabaseException {
 
-               assert (request != null);
-
-               ListenerBase listener = getListenerBase(procedure);
+        assert (request != null);
 
-               final DataContainer<Throwable> exception = new DataContainer<Throwable>();
-               final DataContainer<T> result = new DataContainer<T>();
-
-               if (parent != null || listener != null) {
-
-//                     final ReadGraphImpl newGraph = newSync();
-                       
-                       processor.query(this, request, parent, new Procedure<T>() {
+        ListenerBase listener = procedure != null ? getListenerBase(procedure) : null;
+        return QueryCache.resultExternalReadEntry(this, request, parent, listener, procedure);
 
-                               @Override
-                               public void exception(Throwable throwable) {
-                                       exception.set(throwable);
-                                       procedure.exception(throwable);
-                               }
-
-                               @Override
-                               public void execute(T t) {
-                                       result.set(t);
-                                       procedure.execute(t);
-                               }
-
-                       }, listener);
-
-//                     newGraph.waitAsync(request);
-
-               } else {
-
-                       try {
-
-                               T t = processor.tryQuery(this, request);
-                               result.set(t);
-                               procedure.execute(t);
-
-                       } catch (Throwable t) {
-
-                           if (t instanceof DatabaseException) {
-                               exception.set((DatabaseException)t);
-                               procedure.exception(exception.get());
-                           } else {
-                               exception.set(new DatabaseException(
-                                       "Unexpected exception in ReadGraph.syncRequest(Read)",
-                                       t));
-                               procedure.exception(exception.get());
-                           }
-
-                       }
-
-               }
+//         
+//         ListenerBase listener = getListenerBase(procedure);
+//         
+//         return QueryCache.resultExternalReadEntry(this, request, parent, listener, procedure);
+           
+//             assert (request != null);
+//
+//             ListenerBase listener = getListenerBase(procedure);
+//             
+//             final DataContainer<Throwable> exception = new DataContainer<Throwable>();
+//             final DataContainer<T> result = new DataContainer<T>();
+//
+//             processor.query(this, request, parent, new Procedure<T>() {
+//
+//                     @Override
+//                     public void exception(Throwable throwable) {
+//                             exception.set(throwable);
+//                             procedure.exception(throwable);
+//                     }
+//
+//                     @Override
+//                     public void execute(T t) {
+//                             result.set(t);
+//                             procedure.execute(t);
+//                     }
+//
+//             }, listener);
+               
 
-               Throwable t = exception.get();
-               if (t != null) {
-                       if (t instanceof DatabaseException)
-                               throw (DatabaseException) t;
-                       else
-                               throw new DatabaseException(
-                                               "Unexpected exception in ReadGraph.syncRequest(Read)",
-                                               t);
-               }
 
-               return result.get();            
+//             if (parent != null || listener != null) {
+//
+////                   final ReadGraphImpl newGraph = newSync();
+//                     
+//
+////                   newGraph.waitAsync(request);
+//
+//             } else {
+//
+//                     try {
+//
+//                             T t = processor.tryQuery(this, request);
+//                             result.set(t);
+//                             procedure.execute(t);
+//
+//                     } catch (Throwable t) {
+//
+//                         if (t instanceof DatabaseException) {
+//                             exception.set((DatabaseException)t);
+//                             procedure.exception(exception.get());
+//                         } else {
+//                             exception.set(new DatabaseException(
+//                                     "Unexpected exception in ReadGraph.syncRequest(Read)",
+//                                     t));
+//                             procedure.exception(exception.get());
+//                         }
+//
+//                     }
+//
+//             }
+//
+//             Throwable t = exception.get();
+//             if (t != null) {
+//                     if (t instanceof DatabaseException)
+//                             throw (DatabaseException) t;
+//                     else
+//                             throw new DatabaseException(
+//                                             "Unexpected exception in ReadGraph.syncRequest(Read)",
+//                                             t);
+//             }
+//
+//             return result.get();            
 
        }
 
@@ -5474,46 +5450,20 @@ public class ReadGraphImpl implements ReadGraph {
 
                assert (request != null);
                assert (procedure != null);
+       
+               processor.schedule(new SessionTask(false) {
 
-               final ListenerBase listener = getListenerBase(procedure);
-
-               if (parent != null || listener != null) {
-
-                       try {
-                               processor.queryRead(this, request, parent, procedure,
-                                               listener);
-                       } catch (Throwable e) {
-                               // This throwable has already been transferred to procedure at this point - do nothing about it
-                               //Logger.defaultLogError("Internal error ", e);
-                       }
-                       
-               } else {
-
-//                     final ReadGraphImpl newGraph = newSync();
-
-                       try {
-
-                               T result = request.perform(this);
-                               
-                               try {
-                                       procedure.execute(this, result);
-                               } catch (Throwable t) {
-                                       Logger.defaultLogError(t);
-                               }
-
-                       } catch (Throwable t) {
-
+                       @Override
+                       public void run(int thread) {
                                try {
-                                       procedure.exception(this, t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
+                                       final ListenerBase listener = getListenerBase(procedure);
+                                       QueryCache.runnerReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false);
+                               } catch (DatabaseException e) {
+                                       Logger.defaultLogError(e);
                                }
-
-                       } finally {
-
                        }
-
-               }
+                       
+               });
 
        }
 
@@ -5585,33 +5535,19 @@ public class ReadGraphImpl implements ReadGraph {
                assert (request != null);
                assert (procedure != null);
 
-               final ListenerBase listener = getListenerBase(procedure);
-
-               if (parent != null || listener != null) {
-
-                       processor.query(this, request, parent, procedure, listener);
-
-               } else {
-
-                       try {
-                               
-                               request.perform(this, new CallWrappedSingleQueryProcedure4<T>(procedure, request));
-
-                       } catch (Throwable t) {
-
-                               if (t instanceof DatabaseException)
-                                       procedure.exception(this, t);
-                               else
-                                       procedure
-                                                       .exception(
-                                                                       this,
-                                                                       new DatabaseException(
-                                                                                       "Unexpected exception in ReadGraph.asyncRequest(SingleAsyncRead, SingleProcedure)",
-                                                                                       t));
+               processor.schedule(new SessionTask(false) {
 
+                       @Override
+                       public void run(int thread) {
+                               try {
+                                       final ListenerBase listener = getListenerBase(procedure);
+                                       QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false);
+                               } catch (DatabaseException e) {
+                                       Logger.defaultLogError(e);
+                               }
                        }
-
-               }
+                       
+               });
 
        }
 
@@ -5842,56 +5778,125 @@ public class ReadGraphImpl implements ReadGraph {
        final public <T> void asyncRequest(final ExternalRead<T> request,
                        final Procedure<T> procedure) {
 
-               assert (request != null);
-               assert (procedure != null);
+           
+        assert (request != null);
+        assert (procedure != null);
 
-               ListenerBase listener = getListenerBase(procedure);
+        final ListenerBase listener = getListenerBase(procedure);
 
-               if (parent != null || listener != null) {
-
-                       processor.query(this, request, parent, procedure, listener);
-
-               } else {
-
-                       try {
+        if (parent != null || listener != null) {
 
-                               request.register(this, new Listener<T>() {
-
-                                       @Override
-                                       public void execute(T result) {
-                                               procedure.execute(result);
-                                       }
-
-                                       @Override
-                                       public void exception(Throwable t) {
-                                               procedure.exception(t);
-                                       }
+            try {
+                QueryCacheBase.resultExternalReadEntry(this, request, parent, listener, procedure);
+                //processor.query(this, request, parent, procedure,listener);
+            } catch (DatabaseException e) {
+                Logger.defaultLogError(e);
+                // This throwable has already been transferred to procedure at this point - do nothing about it
+                //
+            }
+            
+        } else {
 
-                                       @Override
-                                       public String toString() {
-                                               return "asyncRequest(PrimitiveRead) -> " + request;
-                                       }
+            request.register(this, new Listener<T>() {
+                //
+                @Override
+                public void execute(T result) {
+                    procedure.execute(result);
+                }
 
-                                       @Override
-                                       public boolean isDisposed() {
-                                               return true;
-                                       }
+                @Override
+                public void exception(Throwable t) {
+                    procedure.exception(t);
+                }
 
-                               });
+                @Override
+                public String toString() {
+                    return "asyncRequest(PrimitiveRead) -> " + request;
+                }
 
-                       } catch (Throwable t) {
+                @Override
+                public boolean isDisposed() {
+                    return true;
+                }
 
-                               if (t instanceof DatabaseException)
-                                       procedure.exception(t);
-                               else
-                                       procedure
-                                                       .exception(new DatabaseException(
-                                                                       "Unexpected exception in ReadGraph.asyncRequest(SingleAsyncRead, SingleProcedure)",
-                                                                       t));
+            });            
+            
+//          final ReadGraphImpl newGraph = newSync();
 
-                       }
+//            try {
+//
+//                T result = request.perform(this);
+//                
+//                try {
+//                    procedure.execute(this, result);
+//                } catch (Throwable t) {
+//                    Logger.defaultLogError(t);
+//                }
+//
+//            } catch (Throwable t) {
+//
+//                try {
+//                    procedure.exception(this, t);
+//                } catch (Throwable t2) {
+//                    Logger.defaultLogError(t2);
+//                }
+//
+//            } finally {
+//
+//            }
 
-               }
+        }
+           
+//             assert (request != null);
+//             assert (procedure != null);
+//
+//             ListenerBase listener = getListenerBase(procedure);
+//
+//             if (parent != null || listener != null) {
+//
+//                     processor.query(this, request, parent, procedure, listener);
+//
+//             } else {
+//
+//                     try {
+//
+//                             request.register(this, new Listener<T>() {
+//
+//                                     @Override
+//                                     public void execute(T result) {
+//                                             procedure.execute(result);
+//                                     }
+//
+//                                     @Override
+//                                     public void exception(Throwable t) {
+//                                             procedure.exception(t);
+//                                     }
+//
+//                                     @Override
+//                                     public String toString() {
+//                                             return "asyncRequest(PrimitiveRead) -> " + request;
+//                                     }
+//
+//                                     @Override
+//                                     public boolean isDisposed() {
+//                                             return true;
+//                                     }
+//
+//                             });
+//
+//                     } catch (Throwable t) {
+//
+//                             if (t instanceof DatabaseException)
+//                                     procedure.exception(t);
+//                             else
+//                                     procedure
+//                                                     .exception(new DatabaseException(
+//                                                                     "Unexpected exception in ReadGraph.asyncRequest(SingleAsyncRead, SingleProcedure)",
+//                                                                     t));
+//
+//                     }
+//
+//             }
 
        }
 
@@ -6470,7 +6475,6 @@ public class ReadGraphImpl implements ReadGraph {
        }
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     public Variant getVariantValue2(Resource r, Object context) throws DatabaseException {
         Layer0 L0 = processor.getL0(this);
@@ -6741,16 +6745,22 @@ public class ReadGraphImpl implements ReadGraph {
         }
     }
     
+    private static ThreadLocal<Boolean> syncGraph = new ThreadLocal<Boolean>() {
+        protected Boolean initialValue() {
+            return true;
+        }
+    };
+
     @Override
     public boolean setSynchronous(boolean value) {
-        boolean old = processor.synch;
-        processor.synch = value;
+        boolean old = getSynchronous();
+        syncGraph.set(value);
         return old;
     }
     
     @Override
     public boolean getSynchronous() {
-        return processor.synch;
+        return syncGraph.get();
     }
     
     public void ensureLoaded(int resource) {
@@ -6781,5 +6791,10 @@ public class ReadGraphImpl implements ReadGraph {
     public Object getModificationCounter() {
        return processor.getSession().getModificationCounter();
     }
+
+       @Override
+       public boolean performPending() {
+               return processor.performPending(processor.thread.get());
+       }
     
 }