]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge branch 'private/db-threads' into private/threads-testing
authorAntti Villberg <antti.villberg@semantum.fi>
Mon, 9 Jul 2018 07:10:36 +0000 (10:10 +0300)
committerAntti Villberg <antti.villberg@semantum.fi>
Mon, 9 Jul 2018 07:10:36 +0000 (10:10 +0300)
Change-Id: I84918b6db56d8c53a8d91ed6886741009e8b7c1b

1  2 
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionRequestManager.java
bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java
tests/org.simantics.db.tests/src/org/simantics/db/tests/api/request/misc/RequestParentTest3.java

index 614a96df3c47d29ea45e249dfb10df9653aaedf4,fe0e3fcee535b983e119730e00e7d239e789474d..6998ee55e127afa761b7aad2499264bc816588d8
@@@ -26,6 -26,7 +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;
  
@@@ -45,6 -46,7 +46,6 @@@ import org.simantics.databoard.util.bin
  import org.simantics.databoard.util.binary.RandomAccessBinary;
  import org.simantics.db.AsyncReadGraph;
  import org.simantics.db.DevelopmentKeys;
 -import org.simantics.db.ExternalValue;
  import org.simantics.db.ExternalValueSupport;
  import org.simantics.db.ReadGraph;
  import org.simantics.db.RelationContext;
@@@ -87,6 -89,7 +88,7 @@@ import org.simantics.db.common.primitiv
  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 -114,7 +113,7 @@@ import org.simantics.db.common.procedur
  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 -138,16 +137,16 @@@ import org.simantics.db.impl.ResourceIm
  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 -185,7 +184,7 @@@ import org.simantics.scl.compiler.types
  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,8 -287,17 +286,17 @@@ public class ReadGraphImpl implements R
  
                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) {
  
  
                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) {
                        
                }
  
        }
+       
+       @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();
  
                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);
+ //
+ //                    }
+ //
+ //            }
                
        }
  
  
                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);
+ //
+ //                    }
+ //
+ //            }
  
        }
  
                                        throw (DatabaseException) exception;
                                else
                                        throw new DatabaseException(
-                                                       "Unexpected exception in ReadGraph.syncRequest(AsyncMultiRead)",
+                                                       "Unexpected exception in ReadGraph.syncRequest(AsyncRead)",
                                                        exception);
                        }
                }
                        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>());
  
  
                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();
+ //
+ //            }
  
        }
  
  
                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();
  
        }
  
        final public <T> T syncRequest(final ExternalRead<T> request,
                        final Procedure<T> procedure) throws DatabaseException {
  
-               assert (request != null);
-               ListenerBase listener = getListenerBase(procedure);
-               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>() {
-                               @Override
-                               public void exception(Throwable throwable) {
-                                       exception.set(throwable);
-                                       procedure.exception(throwable);
-                               }
-                               @Override
-                               public void execute(T t) {
-                                       result.set(t);
-                                       procedure.execute(t);
-                               }
+         assert (request != null);
  
-                       }, listener);
- //                    newGraph.waitAsync(request);
-               } else {
-                       try {
-                               T t = processor.tryQuery(this, request);
-                               result.set(t);
-                               procedure.execute(t);
-                       } catch (Throwable t) {
+         ListenerBase listener = procedure != null ? getListenerBase(procedure) : null;
+         return QueryCache.resultExternalReadEntry(this, request, parent, listener, procedure);
  
-                           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();            
  
        }
  
  
                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 {
                        }
-               }
+                       
+               });
  
        }
  
                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);
+                               }
                        }
-               }
+                       
+               });
  
        }
  
        final public <T> void asyncRequest(final ExternalRead<T> request,
                        final Procedure<T> procedure) {
  
-               assert (request != null);
-               assert (procedure != null);
-               ListenerBase listener = getListenerBase(procedure);
-               if (parent != null || listener != null) {
+           
+         assert (request != null);
+         assert (procedure != null);
  
-                       processor.query(this, request, parent, procedure, listener);
-               } else {
-                       try {
+         final ListenerBase listener = getListenerBase(procedure);
  
-                               request.register(this, new Listener<T>() {
+         if (parent != null || listener != null) {
  
-                                       @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));
+ //
+ //                    }
+ //
+ //            }
  
        }
  
                        return getValue(r);
                }
        }
 -        else if(types.contains(L0.Function)) {
 -            return Functions.exec(this, r, this, r, context);
 -        }
        else if(types.contains(L0.ExternalValue)) {
                return (T)syncRequest(new AdaptValue(r), TransientCacheListener.<Object>instance());
        }
                  return getVariantValue(r);
              }
          }
 -        else if(types.contains(L0.Function)) {
 -            Object value = Functions.exec(this, r, this, r, context);
 -            try {
 -                return new Variant(Bindings.OBJECT.getContentBinding(value), value);
 -            } catch ( org.simantics.databoard.binding.error.BindingException e ) {
 -                throw new BindingException( "No binding found for class " + value.getClass().getName(), e );
 -            }
 -        }
          else if(types.contains(L0.ExternalValue)) {
              Object value = syncRequest(new AdaptValue(r), TransientCacheListener.<Object>instance());
              try {
              for(Resource converter : graph.getObjects(resource, L0.ConvertsToValueWith)) {
                  try {
                        if(L0.Functions_functionApplication.equals(converter)) {
 -                              return AdaptValue.functionApplication;
 -                              //return (Function3<ReadGraph,Resource,Object,T>)graph.syncRequest(new AdaptValue(resource));
 +                              return (Function3<ReadGraph,Resource,Object,T>)graph.syncRequest(new AdaptValue(resource));
                        } else {
                                return graph.getValue2(converter, resource);
                        }
                } else {
                        return getValue(r, binding);
                }
 -      } else if(types.contains(L0.Function)) {
 -            Object value = Functions.exec(this, r, this, r, context);
 -            if(binding.isInstance(value)) return (T)value;
 -            try {
 -                Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
 -                return (T)Bindings.adapt(value, srcBinding, binding);
 -            } catch(RuntimeException e) {
 -                DatabaseException dte = findPossibleRootException(e);
 -                if(dte != null) throw dte;
 -                else throw new DatabaseException(e);
 -            } catch (AdaptException e) {
 -                throw new DatabaseException(e);
 -            } catch (org.simantics.databoard.binding.error.BindingException e) {
 -                throw new DatabaseException(e);
 -            }
        } else if(types.contains(L0.ExternalValue)) {
                try {
 -                      ExternalValue ev = adapt(r, ExternalValue.class);
 -                      return ev.getValue(this, r);
 -                      //return (T)ReflectionUtils.getValue(getURI(r)).getValue();
 -//                    } catch(ValueNotFoundException e) {
 -//                            throw new DatabaseException(e);
 +                      return (T)ReflectionUtils.getValue(getURI(r)).getValue();
 +              } catch(ValueNotFoundException e) {
 +                      throw new DatabaseException(e);
                } catch(ClassCastException e) {
                        throw new DatabaseException(e);
                }
          }
      }
      
+     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) {
      public Object getModificationCounter() {
        return processor.getSession().getModificationCounter();
      }
+       @Override
+       public boolean performPending() {
+               return processor.performPending(processor.thread.get());
+       }
      
  }
index 9290ac99fdd98a5792a542a0b51b7309941f1704,4e37d7fc7b1577938dfc939f58b02954369fdd6a..d5d9445ca4fb230520769af6f7cb1e4d0ea0e8fc
@@@ -50,6 -50,7 +50,7 @@@ import org.simantics.db.authentication.
  import org.simantics.db.authentication.UserAuthenticator;
  import org.simantics.db.common.Indexing;
  import org.simantics.db.common.TransactionPolicyRelease;
+ 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.wrapper.NoneToAsyncListener;
@@@ -89,6 -90,8 +90,8 @@@ import org.simantics.db.impl.graph.Writ
  import org.simantics.db.impl.internal.RandomAccessValueSupport;
  import org.simantics.db.impl.procedure.ResultCallWrappedQueryProcedure4;
  import org.simantics.db.impl.procedure.ResultCallWrappedSingleQueryProcedure4;
+ 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.QueryProcessor.SessionRead;
  import org.simantics.db.impl.query.QueryProcessor.SessionTask;
@@@ -409,7 -412,7 +412,7 @@@ public abstract class SessionImplSocke
  
          int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleWrite(new SessionTask(request, thread, thread) {
+         requestManager.scheduleWrite(new SessionTask(true) {
  
              @Override
              public void run(int thread) {
                      }
  
  
-                     assert(!queryProvider2.dirty);
+                     assert(!queryProvider2.cache.dirty);
  
                  } catch (Throwable e) {
  
  
          int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleWrite(new SessionTask(request, thread) {
+         requestManager.scheduleWrite(new SessionTask(true) {
  
              @Override
              public void run(int thread) {
  
          int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleWrite(new SessionTask(request, thread) {
+         requestManager.scheduleWrite(new SessionTask(true) {
  
              @Override
              public void run(int thread) {
  
          int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleWrite(new SessionTask(request, thread, thread) {
+         requestManager.scheduleWrite(new SessionTask(true) {
  
              @Override
              public void run(int thread) {
  
          int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleWrite(new SessionTask(request, thread) {
+         requestManager.scheduleWrite(new SessionTask(true) {
  
              @Override
              public void run(int thread) {
          assert (request != null);
          assert (procedure != null);
  
-         int thread = request.hashCode() & queryProvider2.THREAD_MASK;
+         //int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleRead(new SessionRead(request, throwable, notify, thread, thread) {
+         requestManager.scheduleRead(new SessionRead(throwable, notify) {
  
              @Override
              public void run(int thread) {
                      if (listener != null) {
  
                        try {
-                               newGraph.processor.queryRead(newGraph, request, null, new AsyncProcedure<T>() {
+                               
+                               AsyncProcedure ap = new AsyncProcedure<T>() {
  
                                        @Override
                                        public void exception(AsyncReadGraph graph, Throwable t) {
                                                procedure.execute(graph, t);
                                        }
  
-                               }, listener);
+                               };
+                               
+                               QueryCache.runnerReadEntry(newGraph, request, null, listener, ap, true);
+                               
                        } catch (Throwable t) {
                            // This is handled by the AsyncProcedure
                                //Logger.defaultLogError("Internal error", t);
  
          int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleRead(new SessionRead(request, null, notify, thread) {
+         requestManager.scheduleRead(new SessionRead(null, notify) {
  
              @Override
              public void run(int thread) {
  
                      if (listener != null) {
  
-                         newGraph.processor.query(newGraph, request, null, procedure, listener);
- //                        newGraph.waitAsync(request);
+                         try {
+                               QueryCacheBase.resultAsyncReadEntry(newGraph, request, null, listener, procedure);
+                               //QueryCache.runnerAsyncReadEntry(newGraph, request, null, listener, procedure, true);
+                                                       //newGraph.processor.query(newGraph, request, null, procedure, listener);
+                                               } catch (DatabaseException e) {
+                                                       Logger.defaultLogError(e);
+                                               }
  
                      } else {
  
-                         final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
-                                 procedure, "request");
-                         try {
+ //                        final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
+ //                                procedure, "request");
  
//                            newGraph.state.barrier.inc();
                      BlockingAsyncProcedure<T> wrap = new BlockingAsyncProcedure<T>(newGraph, procedure, request);
  
-                             request.perform(newGraph, wrapper);
+                       try {
  
- //                            newGraph.waitAsync(request);
+                             request.perform(newGraph, wrap);
+                             wrap.get();
  
                          } catch (Throwable t) {
  
-                             wrapper.exception(newGraph, t);
+                               wrap.exception(newGraph, t);
+                               
+ //                            wrapper.exception(newGraph, t);
  //                            newGraph.waitAsync(request);
  
  
  
          int sync = notify != null ? thread : -1;
  
-         requestManager.scheduleRead(new SessionRead(request, null, notify, thread, sync) {
+         requestManager.scheduleRead(new SessionRead(null, notify) {
  
              @Override
              public void run(int thread) {
  
          int thread = request.hashCode() & queryProvider2.THREAD_MASK;
  
-         requestManager.scheduleRead(new SessionRead(request, throwable, notify, thread, thread) {
+         requestManager.scheduleRead(new SessionRead(throwable, notify) {
  
              @Override
              public void run(int thread) {
  
                      if (listener != null) {
  
-                         newGraph.processor.query(newGraph, request, null, new Procedure<T>() {
-                             @Override
-                             public void exception(Throwable t) {
-                                 procedure.exception(t);
-                                 if(throwable != null) {
-                                     throwable.set(t);
-                                 }
-                             }
-                             @Override
-                             public void execute(T t) {
-                                 if(result != null) result.set(t);
-                                 procedure.execute(t);
-                             }
-                         }, listener);
+                         try {
+                             QueryCacheBase.resultExternalReadEntry(newGraph, request, null, listener, procedure);
+                         } catch (DatabaseException e) {
+                             Logger.defaultLogError(e);
+                         }
+                         
+                         
+ //                        newGraph.processor.query(newGraph, request, null, new Procedure<T>() {
+ //
+ //                            @Override
+ //                            public void exception(Throwable t) {
+ //                                procedure.exception(t);
+ //                                if(throwable != null) {
+ //                                    throwable.set(t);
+ //                                }
+ //                            }
+ //
+ //                            @Override
+ //                            public void execute(T t) {
+ //                                if(result != null) result.set(t);
+ //                                procedure.execute(t);
+ //                            }
+ //
+ //                        }, listener);
  
  //                        newGraph.waitAsync(request);
  
  
      public int getAmountOfQueryThreads() {
          // This must be a power of two
--        return 1;
++        return 8;
  //        return Integer.highestOneBit(Runtime.getRuntime().availableProcessors());
      }
  
index a29d6ce045bc619ceae803dfe7bf6d48cb03241a,3209961ed61519ac4e22ba100f20ff9882cbd1be..2902274b94202c9c79610f006f5acbf91365338b
@@@ -6,6 -6,7 +6,6 @@@ import java.util.LinkedList
  
  import org.simantics.db.Disposable;
  import org.simantics.db.Resource;
 -import org.simantics.db.common.utils.Logger;
  import org.simantics.db.exception.CancelTransactionException;
  import org.simantics.db.exception.DatabaseException;
  import org.simantics.db.impl.graph.WriteGraphImpl;
@@@ -15,13 -16,9 +15,13 @@@ import org.simantics.db.impl.query.Quer
  import org.simantics.db.impl.query.QueryProcessor.SessionTask;
  import org.simantics.db.request.WriteTraits;
  import org.simantics.utils.datastructures.Pair;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
  
  public class SessionRequestManager {
  
 +      private static final Logger LOGGER = LoggerFactory.getLogger(SessionRequestManager.class);
 +
        private static boolean DEBUG = false;
        
        enum State {
        
        public synchronized void startRead(int thread, final SessionRead task) {
                
-               session.queryProvider2.scheduleAlways(thread, new SessionTask(task.object, task.thread, task.syncCaller) {
+               session.queryProvider2.schedule(new SessionTask(true) {
  
                        @Override
              public void run(int thread) {
                      transactionState.startReadTransaction(thread);
                      task.run(thread);
                  } catch (Throwable t) {
 -                    Logger.defaultLogError(new DatabaseException("Read transaction could not be started", t));
 +                    LOGGER.error("Read transaction could not be started", t);
                      if(task.throwable != null)
                          task.throwable.set(t);
                      state = State.ERROR;
        
        public synchronized void startReadUpdate(int thread) {
                
-               session.queryProvider2.scheduleAlways(thread, new SessionTask(null, thread) {
+               session.queryProvider2.schedule(new SessionTask(true) {
  
                        @Override
                        public void run(int thread) {
                                try {
                                        transactionState.stopReadTransaction();
                                } catch (DatabaseException e) {
 -                                      e.printStackTrace();
 +                                      LOGGER.error("Read transaction could not be stopped", e);
                                }
                                
                        }
                
        }
  
 -//    public synchronized void stopRead(int thread) {
 -//            
 -//            try {
 -//                    transactionState.stopReadTransaction();
 -//            } catch (DatabaseException e) {
 -//                    e.printStackTrace();
 -//            }
 -//            
 -//    }
 -
        public synchronized void startWrite(int thread, final SessionTask task) {
                
-               session.queryProvider2.scheduleAlways(thread, new SessionTask((WriteTraits)task.object, task.thread) {
+               session.queryProvider2.schedule(new SessionTask(true) {
  
                        @Override
                        public void run(int thread) {
                        try {
                                transactionState.startWriteTransaction(thread);
                        } catch (Throwable t) {
 -                          DatabaseException e = new DatabaseException("Write transaction could not be started", t);
 -                          Logger.defaultLogError(e);
 +                          LOGGER.error("Write transaction could not be started", t);
                            return;
                        }
                                task.run(thread);
  
        public synchronized void startWriteUpdate(int thread) {
                
-               session.queryProvider2.scheduleAlways(thread, new SessionTask(null, thread) {
+               session.queryProvider2.schedule(new SessionTask(true) {
  
                        @Override
                        public void run(int thread) {
                                if(!session.state.isAlive()) return;
  
                                WriteState<?> writeState = session.writeState;
+                               
+                               assert(writeState != null);
+                               
                                WriteGraphImpl graph = writeState.getGraph();
  
                                if(writeState.isExcepted()) {
 -                                  
 +
                                    if(!(writeState.exception instanceof CancelTransactionException))
 -                                      writeState.exception.printStackTrace();
 -                                  
 +                                      LOGGER.error("Write request failed", writeState.exception);
 +
                                    transactionState.cancelWriteTransaction(graph);
  
                                } else {
  
        }
  
 -//    public synchronized void stopWrite(int thread) {
 -//            
 -//        session.clientChanges = new ClientChangesImpl(session);
 -//
 -//        WriteState<?> state = session.writeState;
 -//
 -//        System.err.println("D");
 -//        state.finish();
 -//        System.err.println("E");
 -//        
 -//        session.writeState = null;
 -//        
 -//    }
 -
        public synchronized void ceased(int thread) {
  
                if(State.WRITE == state) {
                        if (!reads.isEmpty()) {
  
                                final SessionRead read = reads.poll();
-                               session.queryProvider2.scheduleAlways(thread, new SessionTask(read.object, read.thread, read.syncCaller) {
+                               session.queryProvider2.schedule(new SessionTask(true) {
  
                                        @Override
                                        public void run(int thread) {
                        
                } else {
  
-                   throw new IllegalStateException("State in ceased should be WRITE or READ or INIT (was " + state + ")"); 
+                       // Spurious wakeup
+                       
+                   //throw new IllegalStateException("State in ceased should be WRITE or READ or INIT (was " + state + ")"); 
                        
                }
                
                assert(State.INIT != state);
                
                if(State.READ == state) {
-                       session.queryProvider2.schedule(Integer.MIN_VALUE, new SessionTask(task.object, task.thread, task.syncCaller) {
+                       session.queryProvider2.schedule(new SessionTask(true) {
  
                                @Override
                                public void run(int thread) {
  
                boolean inUpdate = state == State.WRITE_UPDATE;
  
+               //System.err.println("schedule write " + task);
+               
                assert(State.INIT != state);
                //task.combine = combine != null ? combine : inUpdate;
                if(State.IDLE == state) {
                        try {
                                value.second.binaryFile.close();
                        } catch (IOException e) {
 -                              Logger.defaultLogError("I/O exception while closing random access value file " + value.second.binaryFile.file() + " for resource " + value.first , e);
 +                              LOGGER.error("I/O exception while closing random access value file " + value.second.binaryFile.file() + " for resource " + value.first , e);
                        }
                }
        }
index 47a14ddbcbccc7424bec9fe1ea059c588dffc24d,859481727bfe9f701f53cbe462dc5ecb6219b83b..1690505a0b4ba6e0c6c304583e4d447b58f3b6d2
@@@ -20,6 -20,7 +20,7 @@@ import org.simantics.db.ReadGraph
  import org.simantics.db.Resource;
  import org.simantics.db.adaption.Adapter;
  import org.simantics.db.adaption.AdaptionService;
+ import org.simantics.db.common.procedure.BlockingAsyncProcedure;
  import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
  import org.simantics.db.common.procedure.single.SyncReadProcedure;
  import org.simantics.db.common.request.BinaryRead;
@@@ -38,6 -39,8 +39,6 @@@ import org.simantics.layer0.Layer0
  import org.simantics.utils.datastructures.Pair;
  
  public class AdaptionService2 implements AdaptionService {
 -      
 -      int foobaz;
  
      THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>> adapters =
          new THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>>();
      public <T, C> T adapt(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {
  
        Adapter<T,C> adapter = getAdapter(g, r, context, contextClass, targetClass, possible);
+       if(adapter == null) return null;
        
-               SyncReadProcedure<T> procedure = new SyncReadProcedure<T>();
-       adapter.adapt(g, r, context, procedure);
-               procedure.checkAndThrow();
-               return procedure.result;
+       BlockingAsyncProcedure<T> ap = new BlockingAsyncProcedure<T>(g, null, adapter);
 -      
 -//            SyncReadProcedure<T> procedure = new SyncReadProcedure<T>();
+       adapter.adapt(g, r, context, ap);
 -      
+       return ap.get();
 -//            procedure.checkAndThrow();
 -//            return procedure.result;
        
      }
      
index 2bec7c21eb3666dedbf9a68a573daee4c77354c6,8181e08fb9d2bf1a4a9fc4646e099f30f9e54fdf..e990a06b2bda11ebec210dfbc84794e14fa4c8b4
@@@ -33,11 -33,6 +33,11 @@@ public class RequestParentTest3 extend
                QueryDebug debug = session.getService(QueryDebug.class);
                
                class Request implements AsyncMultiRead<Object> {
-                       @Override
-                       public int threadHash() {
-                               return hashCode();
-                       }
 +
++//                    @Override
++//                    public int threadHash() {
++//                            return hashCode();
++//                    }
                        
              @Override
              public void perform(AsyncReadGraph graph, AsyncMultiProcedure<Object> callback) {