]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java
DB request scheduling scheme fails with district diagrams
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / QueryProcessor.java
index ff15d301b58214a25d20bb663889d11430008ae2..a46bc0e8dd4e1b024dea3b0dd8d7269b10a19192 100644 (file)
@@ -31,8 +31,6 @@ import java.util.Set;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.db.AsyncReadGraph;
@@ -46,17 +44,14 @@ import org.simantics.db.Statement;
 import org.simantics.db.VirtualGraph;
 import org.simantics.db.common.procedure.adapter.AsyncMultiProcedureAdapter;
 import org.simantics.db.common.utils.Logger;
-import org.simantics.db.debug.ListenerReport;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
 import org.simantics.db.exception.NoInverseException;
 import org.simantics.db.exception.ResourceNotFoundException;
-import org.simantics.db.impl.DebugPolicy;
 import org.simantics.db.impl.ResourceImpl;
-import org.simantics.db.impl.graph.MultiIntProcedure;
+import org.simantics.db.impl.graph.BarrierTracing;
 import org.simantics.db.impl.graph.ReadGraphImpl;
 import org.simantics.db.impl.graph.ReadGraphSupport;
-import org.simantics.db.impl.graph.WriteGraphImpl;
 import org.simantics.db.impl.procedure.IntProcedureAdapter;
 import org.simantics.db.impl.procedure.InternalProcedure;
 import org.simantics.db.impl.procedure.TripleIntProcedureAdapter;
@@ -65,18 +60,14 @@ import org.simantics.db.procedure.AsyncMultiListener;
 import org.simantics.db.procedure.AsyncMultiProcedure;
 import org.simantics.db.procedure.AsyncProcedure;
 import org.simantics.db.procedure.AsyncSetListener;
-import org.simantics.db.procedure.Listener;
 import org.simantics.db.procedure.ListenerBase;
 import org.simantics.db.procedure.MultiProcedure;
-import org.simantics.db.procedure.Procedure;
 import org.simantics.db.procedure.StatementProcedure;
+import org.simantics.db.procedure.SyncMultiProcedure;
 import org.simantics.db.request.AsyncMultiRead;
-import org.simantics.db.request.AsyncRead;
 import org.simantics.db.request.ExternalRead;
 import org.simantics.db.request.MultiRead;
-import org.simantics.db.request.Read;
 import org.simantics.db.request.RequestFlags;
-import org.simantics.db.request.WriteTraits;
 import org.simantics.layer0.Layer0;
 import org.simantics.utils.DataContainer;
 import org.simantics.utils.Development;
@@ -84,7 +75,6 @@ import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.collections.CollectionUtils;
 import org.simantics.utils.datastructures.disposable.AbstractDisposable;
 
-import gnu.trove.map.hash.THashMap;
 import gnu.trove.procedure.TIntProcedure;
 import gnu.trove.procedure.TLongProcedure;
 import gnu.trove.procedure.TObjectProcedure;
@@ -94,47 +84,13 @@ import gnu.trove.set.hash.TIntHashSet;
 @SuppressWarnings({"rawtypes", "unchecked"})
 final public class QueryProcessor extends AbstractDisposable implements ReadGraphSupport {
 
-       final public UnaryQueryHashMap<IntProcedure>                      directPredicatesMap;
-       final public UnaryQueryHashMap<IntProcedure>                      principalTypesMap;
-       final public THashMap<String, URIToResource>                      uriToResourceMap;
-       final public THashMap<String, NamespaceIndex>                     namespaceIndexMap22;
-       final public UnaryQueryHashMap<IntProcedure>                      projectsMap;
-       final public UnaryQueryHashMap<InternalProcedure<RelationInfo>>   relationInfoMap;
-       final public UnaryQueryHashMap<InternalProcedure<IntSet>>         superTypesMap;
-       final public UnaryQueryHashMap<InternalProcedure<IntSet>>         typeHierarchyMap;
-       final public UnaryQueryHashMap<InternalProcedure<IntSet>>         superRelationsMap;
-       final public UnaryQueryHashMap<InternalProcedure<IntSet>>         typesMap;
-       final public UnaryQueryHashMap<InternalProcedure<byte[]>>         valueMap;
-       final public DoubleKeyQueryHashMap<IntProcedure>                     directObjectsMap;
-       final public DoubleKeyQueryHashMap<IntProcedure>                     objectsMap;
-       final public UnaryQueryHashMap<IntProcedure>                      orderedSetMap;
-       final public UnaryQueryHashMap<IntProcedure>                      predicatesMap;
-       final public DoubleKeyQueryHashMap<TripleIntProcedure>               statementsMap;
-       final public UnaryQueryHashMap<IntProcedure>                      assertedPredicatesMap;
-       final public BinaryQueryHashMap<TripleIntProcedure>               assertedStatementsMap;
-       final public StableHashMap<ExternalRead, ExternalReadEntry>            externalReadMap; 
-       final public StableHashMap<AsyncRead, AsyncReadEntry>                  asyncReadMap; 
-       final public StableHashMap<Read, ReadEntry>                            readMap;
-       final public StableHashMap<AsyncMultiRead, AsyncMultiReadEntry>        asyncMultiReadMap; 
-       final public StableHashMap<MultiRead, MultiReadEntry>                  multiReadMap; 
-
-       final private THashMap<CacheEntry, ArrayList<ListenerEntry>>       listeners;
-
        public static int                                       indent                = 0;
 
-       public int                                              size                  = 0;
-       
        
        // Garbage collection
        
        public int                                              boundQueries          = 0;
 
-       // Statistics
-       private int                                             hits                  = 0;
-
-       private int                                             misses                = 0;
-
-       private int                                             updates               = 0;
 
        final private int                                       functionalRelation;
 
@@ -172,40 +128,30 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        AtomicInteger                                       sleepers = new AtomicInteger(0);
 
-       private boolean                                         updating              = false;
+       boolean                                         updating              = false;
 
-       static public boolean                                         collecting            = false;
-
-       private boolean                                         firingListeners       = false;
 
+       final public QueryCache                                 cache;
        final public QuerySupport                               querySupport;
        final public Session                                    session;
        final public ResourceSupport                            resourceSupport;
-
-       private THashSet<ListenerEntry>                         scheduledListeners    = new THashSet<ListenerEntry>();
+       
+       final public Semaphore                                  requests = new Semaphore(1);
+       
+       final public QueryListening                            listening = new QueryListening(this);
 
        QueryThread[]                                   executors;
 
-       public ArrayList<SessionTask>[]                           queues;
-
        enum ThreadState {
 
                INIT, RUN, SLEEP, DISPOSED
 
        }
 
+       final Scheduling scheduling;
+       
        public ThreadState[]                                                                    threadStates;
-       public ReentrantLock[]                                                                  threadLocks;
-       public Condition[]                                                                          threadConditions;
-
-       public ArrayList<SessionTask>[]                           ownTasks;
-
-       public ArrayList<SessionTask>[]                           ownSyncTasks;
-
-       ArrayList<SessionTask>[]                           delayQueues;
        
-       public boolean synch = true;
-
        final Object querySupportLock;
        
        public Long modificationCounter = 0L;
@@ -213,77 +159,83 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        public void close() {
        }
 
-       final public void scheduleOwn(int caller, SessionTask request) {
-               ownTasks[caller].add(request);
-       }
-
-       final public void scheduleAlways(int caller, SessionTask request) {
 
-               int performer = request.thread;
-               if(caller == performer) {
-                       ownTasks[caller].add(request);
-               } else {
-                       schedule(caller, request);
+    /*
+     * We are running errands while waiting for requests to complete.
+     * We can only run work that is part of the current root request to avoid any deadlocks
+     */
+    public boolean performPending(ReadGraphImpl under) {
+        SessionTask task = scheduling.getSubTask(under);
+               if(task != null) {
+                       task.run(thread.get());
+                       return true;
                }
-
+               return false;
        }
+    
+    final public void scheduleNow(SessionTask request) {
+        SessionTask toExecute = scheduleOrReturnForExecution(request);
+        if(toExecute != null)
+            toExecute.run(thread.get());
+    }
 
-       final public void schedule(int caller, SessionTask request) {
-
-               int performer = request.thread;
-
-               if(DebugPolicy.SCHEDULE)
-                       System.out.println("schedule " + request + " " + caller + " -> " + performer);
-
-               assert(performer >= 0);
-
-               assert(request != null);
-
-               if(caller == performer) {
-                       request.run(caller);
-               } else {
-                       ReentrantLock queueLock = threadLocks[performer];
-                       queueLock.lock();
-                       queues[performer].add(request);
-                       // This thread could have been sleeping
-                       if(queues[performer].size() == 1) {
-                               if(ThreadState.SLEEP == threadStates[performer]) sleepers.decrementAndGet();
-                               threadConditions[performer].signalAll();
-                       }
-                       queueLock.unlock();
-               }
+    final public SessionTask scheduleOrReturnForExecution(SessionTask request) {
+        
+        return scheduling.scheduleOrReturnForExecution(request);
 
-       }
+    }
 
 
        final int THREADS;
-
        final public int  THREAD_MASK;
-       final public static ThreadGroup QueryThreadGroup = new ThreadGroup("Query Thread Group"); 
+
+       final public static ThreadGroup QueryThreadGroup = new ThreadGroup("Query Thread Group");
 
        public static abstract class SessionTask {
 
-               final public int thread;
-               final public int syncCaller;
-               final public Object object;
+           final protected ReadGraphImpl rootGraph;
+               private int counter = 0;
+               protected int position = 1;
+               private Exception trace;
 
-               public SessionTask(WriteTraits object, int thread) {
-                       this.thread = thread;
-                       this.syncCaller = -1;
-                       this.object = object;
+               public SessionTask() {
+                   this(null);
                }
+               
+        public SessionTask(ReadGraphImpl rootGraph) {
+            this.rootGraph = rootGraph;
+        }
+        
+        public boolean isSubtask(ReadGraphImpl graph) {
+            return graph.isParent(rootGraph);
+        }
 
-               public SessionTask(Object object, int thread, int syncCaller) {
-                       this.thread = thread;
-                       this.syncCaller = syncCaller;
-                       this.object = object;
+        public abstract void run0(int thread);
+
+               public final void run(int thread) {
+                   if(counter++ > 0) {
+                       if(BarrierTracing.BOOKKEEPING) {
+                           trace.printStackTrace();
+                           new Exception().printStackTrace();
+                       }
+                       throw new IllegalStateException("Multiple invocations of SessionTask!");
+                   }
+                   if(BarrierTracing.BOOKKEEPING) {
+                       trace = new Exception();
+                   }
+                   run0(thread);
+               }
+               
+               public boolean maybeReady() {
+                       return true;
                }
-
-               public abstract void run(int thread);
 
                @Override
                public String toString() {
-                       return "SessionTask[" + object + "]";
+                       if(rootGraph == null)
+                               return "SessionTask[no graph]";
+                       else
+                               return "SessionTask[" + rootGraph.parent + "]";
                }
 
        }
@@ -293,25 +245,14 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                final public Semaphore notify;
                final public DataContainer<Throwable> throwable; 
 
-               public SessionRead(Object object, DataContainer<Throwable> throwable, Semaphore notify, int thread) {
-                       super(object, thread, thread);
-                       this.throwable = throwable;
-                       this.notify = notify;
-               }
-
-               public SessionRead(Object object, DataContainer<Throwable> throwable, Semaphore notify, int thread, int syncThread) {
-                       super(object, thread, syncThread);
+               public SessionRead(DataContainer<Throwable> throwable, Semaphore notify) {
+                       super(null);
                        this.throwable = throwable;
                        this.notify = notify;
                }
 
        }
 
-       long waitingTime = 0;
-
-       static int koss = 0;
-       static int koss2 = 0;
-
        public boolean resume(ReadGraphImpl graph) {
                return executors[0].runSynchronized();
        }
@@ -322,37 +263,19 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                THREADS = threads;
                THREAD_MASK = threads - 1;
 
+               scheduling = new Scheduling(requests);
+               
                querySupport = core;
+               cache = new QueryCache(core, threads);
                session = querySupport.getSession();
                resourceSupport = querySupport.getSupport();
                querySupportLock = core.getLock();
 
                executors = new QueryThread[THREADS];
-               queues = new ArrayList[THREADS];
-               threadLocks = new ReentrantLock[THREADS];
-               threadConditions = new Condition[THREADS];
                threadStates = new ThreadState[THREADS];
-               ownTasks = new ArrayList[THREADS];
-               ownSyncTasks = new ArrayList[THREADS];
-               delayQueues = new ArrayList[THREADS * THREADS];
-
-               //        freeSchedule = new AtomicInteger(0);
-
-               for (int i = 0; i < THREADS * THREADS; i++) {
-                       delayQueues[i] = new ArrayList<SessionTask>();
-               }
 
                for (int i = 0; i < THREADS; i++) {
-
-                       //            tasks[i] = new ArrayList<Runnable>();
-                       ownTasks[i] = new ArrayList<SessionTask>();
-                       ownSyncTasks[i] = new ArrayList<SessionTask>();
-                       queues[i] = new ArrayList<SessionTask>();
-                       threadLocks[i] = new ReentrantLock();
-                       threadConditions[i] = threadLocks[i].newCondition();
-                       //            limits[i] = false;
                        threadStates[i] = ThreadState.INIT;
-
                }
 
                for (int i = 0; i < THREADS; i++) {
@@ -365,31 +288,6 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                }
 
-               directPredicatesMap = new UnaryQueryHashMap();
-               valueMap = new UnaryQueryHashMap();
-               principalTypesMap = new UnaryQueryHashMap();
-               uriToResourceMap = new THashMap<String, URIToResource>();
-               namespaceIndexMap22 = new THashMap<String, NamespaceIndex>();
-               projectsMap = new UnaryQueryHashMap();
-               relationInfoMap = new UnaryQueryHashMap();
-               typeHierarchyMap = new UnaryQueryHashMap();
-               superTypesMap = new UnaryQueryHashMap();
-               superRelationsMap = new UnaryQueryHashMap();
-               typesMap = new UnaryQueryHashMap();
-               objectsMap = new DoubleKeyQueryHashMap();
-               orderedSetMap = new UnaryQueryHashMap();
-               predicatesMap = new UnaryQueryHashMap();
-               statementsMap = new DoubleKeyQueryHashMap();
-               directObjectsMap = new DoubleKeyQueryHashMap();
-               assertedPredicatesMap = new UnaryQueryHashMap();
-               assertedStatementsMap = new BinaryQueryHashMap();
-               asyncReadMap = new StableHashMap<AsyncRead, AsyncReadEntry>(); 
-               readMap = new StableHashMap<Read, ReadEntry>();
-               asyncMultiReadMap = new StableHashMap<AsyncMultiRead, AsyncMultiReadEntry>(); 
-               multiReadMap = new StableHashMap<MultiRead, MultiReadEntry>(); 
-               externalReadMap = new StableHashMap<ExternalRead, ExternalReadEntry>(); 
-               listeners = new THashMap<CacheEntry, ArrayList<ListenerEntry>>(10, 0.75f);
-
                // Now start threads
                for (int i = 0; i < THREADS; i++) {
                        executors[i].start();
@@ -489,7 +387,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        }
 
        final public void releaseWrite(ReadGraphImpl graph) {
-               performDirtyUpdates(graph);
+               propagateChangesInQueryCache(graph);
                modificationCounter++;
        }
 
@@ -571,48 +469,63 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        public void forResource(ReadGraphImpl graph, final String id, CacheEntry parent, final InternalProcedure<Integer> procedure) {
 
-               URIToResource.queryEach(graph, id, parent, null, new InternalProcedure<Integer>() {
+               try {
+                       
+                       QueryCache.runnerURIToResource(graph, id, parent, null, new InternalProcedure<Integer>() {
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, Integer result) {
+                               @Override
+                               public void execute(ReadGraphImpl graph, Integer result) throws DatabaseException {
 
-                               if (result != null && result != 0) {
-                                       procedure.execute(graph, result);
-                                       return;
-                               }
+                                       if (result != null && result != 0) {
+                                               procedure.execute(graph, result);
+                                               return;
+                                       }
 
-                               // Fall back to using the fixed builtins.
-                               result = querySupport.getBuiltin(id);
-                               if (result != 0) {
-                                       procedure.execute(graph, result);
-                                       return;
-                               } 
+                                       // Fall back to using the fixed builtins.
+//                                     result = querySupport.getBuiltin(id);
+//                                     if (result != 0) {
+//                                             procedure.execute(graph, result);
+//                                             return;
+//                                     } 
 
-                               try {
-                                       result = querySupport.getRandomAccessReference(id);
-                               } catch (ResourceNotFoundException e) {
-                                       procedure.exception(graph, e);
-                                       return;
-                               }
+//                                     try {
+//                                             result = querySupport.getRandomAccessReference(id);
+//                                     } catch (ResourceNotFoundException e) {
+//                                             procedure.exception(graph, e);
+//                                             return;
+//                                     }
 
-                               if (result != 0) {
-                                       procedure.execute(graph, result);
-                               } else {
-                                       procedure.exception(graph, new ResourceNotFoundException(id));
-                               }
+                                       if (result != 0) {
+                                               procedure.execute(graph, result);
+                                       } else {
+                                               procedure.exception(graph, new ResourceNotFoundException(id));
+                                       }
 
-                       }
+                               }
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               procedure.exception(graph, t);
-                       }
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                       procedure.exception(graph, t);
+                               }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                   
+                   try {
+                       
+                procedure.exception(graph, e);
+                
+            } catch (DatabaseException e1) {
+                
+                Logger.defaultLogError(e1);
+                
+            }
+                   
+               }
 
        }
 
-       public void forBuiltin(ReadGraphImpl graph, final String id, CacheEntry parent, final InternalProcedure<Integer> procedure) {
+       public void forBuiltin(ReadGraphImpl graph, final String id, CacheEntry parent, final InternalProcedure<Integer> procedure) throws DatabaseException {
 
                Integer result = querySupport.getBuiltin(id);
                if (result != 0) {
@@ -623,1010 +536,165 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        }
 
-       public final <T> void runAsyncRead(final ReadGraphImpl graph, final AsyncRead<T> query, final CacheEntry parent, final ListenerBase listener, final AsyncProcedure<T> procedure) {
-
-               int hash = requestHash(query);
-
-               AsyncReadEntry<T> entry = asyncReadMap.get(query, hash); 
+       final <T> void runMultiRead(final ReadGraphImpl graph, MultiReadEntry cached, final MultiRead<T> query, final CacheEntry parent, final QueryProcessor provider, final ListenerBase listener, final SyncMultiProcedure<T> procedure) {
 
-               if(parent == null && listener == null) {
-                       if(entry != null && (entry.isReady() || entry.isExcepted())) {
-                               System.out.println("ready " + query);
-                               entry.performFromCache(graph, this, procedure);
-//                             graph.state.barrier.dec(query);
-                               return;
-                       } else {
-                               query.perform(graph, procedure);
-//                             graph.state.barrier.dec(query);
-                               return;
-                       }
+               try {
+                       QueryCache.runnerMultiReadEntry(graph, query, parent, listener, procedure);
+               } catch (DatabaseException e) {
+                       throw new IllegalStateException(e);
                }
 
-               if(entry == null) {
-
-                       entry = new AsyncReadEntry<T>(query);
-                       entry.setPending();
-                       entry.clearResult(querySupport);
-                       asyncReadMap.put(query, entry, hash);
-
-                       performForEach(graph, query, entry, parent, listener, procedure, false);
-
-               } else {
-
-                       if(entry.isPending()) {
-                               synchronized(entry) {
-                                       if(entry.isPending()) {
-                                           throw new IllegalStateException();
-                                               //                      final AsyncBarrierImpl parentBarrier = graph.state.barrier;
-                                               //                      if(entry.procs == null) entry.procs = new ArrayList<AsyncProcedure<T>>();
-                                               //                        entry.procs.add(new AsyncProcedure<T>() {
-                                               //
-                                               //                                                      @Override
-                                               //                                                      public void execute(AsyncReadGraph graph, T result) {
-                                               //                                                              procedure.execute(graph, result);
-                                               //                                                              parentBarrier.dec(query);
-                                               //                                                      }
-                                               //
-                                               //                                                      @Override
-                                               //                                                      public void exception(AsyncReadGraph graph, Throwable throwable) {
-                                               //                                                              procedure.exception(graph, throwable);
-                                               //                                                              parentBarrier.dec(query);
-                                               //                                                      }
-                                               //                              
-                                               //                        });
-//                                             if(graph.parent != null || listener != null) {
-//                                                     registerDependencies(graph, entry, parent, listener, procedure, false);
-//                                             }
-//
-//                                             query.perform(graph, procedure);
-//
-//                                             return;
-
-                                       }
-                               }
-                       }
+       }
 
-                       if(entry.isReady()) { 
-                               entry.performFromCache(graph, this, procedure);
-                               registerDependencies(graph, entry, parent, listener, procedure, false);
-                       } else {
-                               performForEach(graph, query, entry, parent, listener, procedure, false);
-                       }
+       public final <T> void runAsyncMultiRead(final ReadGraphImpl graph, final AsyncMultiRead<T> query, final CacheEntry parent, final ListenerBase listener, final AsyncMultiProcedure<T> procedure) {
 
+               
+               try {
+                       QueryCache.runnerAsyncMultiReadEntry(graph, query, parent, listener, procedure);
+               } catch (DatabaseException e) {
+                       throw new IllegalStateException(e);
                }
 
        }
 
+       final <T> void runPrimitiveRead(ReadGraphImpl graph, ExternalReadEntry cached, final ExternalRead<T> query, final CacheEntry parent, final QueryProcessor provider, final ListenerBase listener, final AsyncProcedure<T> procedure) throws DatabaseException {
+               QueryCache.runnerExternalReadEntry(graph, query, parent, listener, procedure);
+       }
 
-       final static <T> void runMultiRead(final ReadGraphImpl graph, MultiReadEntry cached, final MultiRead<T> query, final CacheEntry parent, final QueryProcessor provider, final ListenerBase listener, final AsyncMultiProcedure<T> procedure) {
-
-               MultiReadEntry entry = cached != null ? cached : provider.multiReadMap.get(query); 
-               if(entry == null) {
-
-                       entry = new MultiReadEntry(query);
-                       entry.setPending();
-                       entry.clearResult(provider.querySupport);
-
-                       provider.multiReadMap.put(query, entry);
-
-                       provider.performForEach(graph, query, entry, parent, listener, procedure, false);
-
-               } else {
-
-                       if(entry.isPending()) {
-
-                               synchronized(entry) {
-
-                                       if(entry.isPending()) {
-                                           throw new IllegalStateException();
-
-//                                             if(entry.procs == null) entry.procs = new ArrayList<Pair<AsyncMultiProcedure<T>, AsyncBarrier>>();
-//                                             entry.procs.add(new Pair(procedure, parentBarrier));
-//                                             if(graph.parent != null || listener != null) {
-//                                                     provider.registerDependencies(graph, entry, parent, listener, procedure, false);
-//                                             }
-
-                                               // If this was synchronized we must wait here until completion
-                                               //                        if(graph.state.synchronizedExecution) {
-                                               //                            while(entry.isPending()) {
-                                               //                              graph.resumeTasks(graph.callerThread, null, null);
-                                               //                            }
-                                               //                        }
+//    @Override
+//     public <T> T query(final ReadGraphImpl graph, final Read<T> query, final CacheEntry parent, final AsyncProcedure<T> procedure, final ListenerBase listener) throws DatabaseException {
+//     
+//     return QueryCache.resultReadEntry(graph, query, parent, listener, procedure);
 //
-//                                             return;
-
-                                       }
-                               }
+//     }
 
-                               entry.performFromCache(graph, provider, procedure);
-//                             graph.state.barrier.dec(query);
-                               return;
+       public <T> void queryMultiRead(final ReadGraphImpl graph, final MultiRead<T> query, final CacheEntry parent, final ListenerBase listener, final SyncMultiProcedure<T> procedure) throws DatabaseException {
 
-                       } else {
+               QueryCache.runnerMultiReadEntry(graph, query, parent, listener, procedure);
 
-                               provider.performForEach(graph, query, entry, parent, listener, procedure, false);
+       }
 
-                       }
+       public <T> void queryPrimitiveRead(final ReadGraphImpl graph, final ExternalRead<T> query, final CacheEntry parent, final ListenerBase listener, final AsyncProcedure<T> procedure) throws DatabaseException {
 
-               }
+               QueryCache.runnerExternalReadEntry(graph, query, parent, listener, procedure);
 
        }
 
-       public final <T> void runAsyncMultiRead(final ReadGraphImpl graph, final AsyncMultiRead<T> query, final CacheEntry parent, final ListenerBase listener, final AsyncMultiProcedure<T> procedure) {
-
-               int hash = requestHash(query);
+       boolean isBound(ExternalReadEntry<?> entry) {
+               if(entry.hasParents()) return true;
+               else if(listening.hasListener(entry)) return true;
+               else return false;
+       }
 
-               AsyncMultiReadEntry entry = asyncMultiReadMap.get(query, hash);
+       static class Dummy implements InternalProcedure<Object>, IntProcedure {
 
-               if(parent == null && listener == null) {
-                       if(entry != null && (entry.isReady() || entry.isExcepted())) {
-                               System.out.println("ready " + query);
-                               entry.performFromCache(graph, this, procedure);
-                               return;
-                       } else {
-                               query.perform(graph, procedure);
-                               return;
-                       }
+               @Override
+               public void execute(ReadGraphImpl graph, int i) {
                }
 
-               if(entry == null) {
-
-                       entry = new AsyncMultiReadEntry<T>(query); 
-                       entry.setPending();
-                       entry.clearResult(querySupport);
-
-                       asyncMultiReadMap.put(query, entry, hash);
-
-                       performForEach(graph, query, entry, parent, listener, procedure, false);
-
-               } else {
-
-                       if(entry.isPending()) {
-                           
-                               synchronized(entry) {
-                                       if(entry.isPending()) {
-                                           throw new IllegalStateException();
-//                                             if(entry.procs == null) entry.procs = new ArrayList<AsyncMultiProcedure<T>>();
-//                                             entry.procs.add(procedure);
-//                                             if(graph.parent != null || listener != null) {
-//                                                     registerDependencies(graph, entry, parent, listener, procedure, false);
-//                                             }
-//                                             return;
-                                       }
-                               }
-                       }
-
-                       performForEach(graph, query, entry, parent, listener, procedure, false);
-
+               @Override
+               public void finished(ReadGraphImpl graph) {
                }
 
-       }
-
-       final static <T> void runPrimitiveRead(ReadGraphImpl graph, ExternalReadEntry cached, final ExternalRead<T> query, final CacheEntry parent, final QueryProcessor provider, final ListenerBase listener, final Procedure<T> procedure) {
-
-               final ExternalReadEntry<T> entry = cached != null ? cached : provider.externalReadMap.get(query); 
-               if(entry == null) {
-                       provider.performForEach(graph, query, new ExternalReadEntry<T>(query), parent, listener, procedure, false);
-               } else {
-                       if(entry.isPending()) {
-                               synchronized(entry) {
-                                       if(entry.isPending()) {
-                                           throw new IllegalStateException();
-//                                             if(entry.procs == null) entry.procs = new ArrayList<Procedure<T>>();
-//                                             entry.procs.add(procedure);
-//                                             return;
-                                       }
-                               }
-                       }
-                       provider.performForEach(graph, query, entry, parent, listener, procedure, false);
+               @Override
+               public void execute(ReadGraphImpl graph, Object result) {
                }
 
-       }
-
-       public int requestHash(Object object) {
-               try {
-                       return object.hashCode();
-               } catch (Throwable t) {
-                       Logger.defaultLogError(t);
-                       return 0;
+               @Override
+               public void exception(ReadGraphImpl graph, Throwable throwable) {
                }
+               
        }
        
-    @Override
-       public <T> T queryRead(final ReadGraphImpl graph, final Read<T> query, final CacheEntry parent, final AsyncProcedure<T> procedure, final ListenerBase listener) throws Throwable {
+       private static final Dummy dummy = new Dummy();
 
-               assert(query != null);
+       /*
+    public <Procedure> Object performForEach2(ReadGraphImpl graph, UnaryQuery<Procedure> query, CacheEntry parent, ListenerBase listener, Procedure procedure) throws Throwable {
 
-               ReadEntry entry = readMap.get(query);
+        if (DebugPolicy.PERFORM)
+            System.out.println("PE[ " + (query.hashCode() &  THREAD_MASK) + "] " + query);
 
-               if(entry != null) {
-                       if(parent == null && (listener == null || listener.isDisposed()) && entry.isReady()) {
-                               return (T)entry.get(graph, this, procedure);
-                       } else if (entry.isPending()) {
-                           throw new IllegalStateException();
-                       }
-               }
+        assert (!dirty);
+        assert (!collecting);
 
-               if(entry == null) {
+        assert(query.assertNotDiscarded());
 
-                       entry = new ReadEntry(query);
-                       entry.setPending();
-                       entry.clearResult(querySupport);
+        registerDependencies(graph, query, parent, listener, procedure, false);
 
-                       readMap.put(query, entry);
+        // FRESH, REFUTED, EXCEPTED go here 
+        if (!query.isReady()) {
 
-                       return (T)performForEach(graph, query, entry, parent, listener, procedure, false);
+            size++;
+            misses++;
 
-               } else {
+            query.computeForEach(graph, this, (Procedure)dummy, true);
+            return query.get(graph, this, null);
 
-                       if(entry.isPending()) {
-                throw new IllegalStateException();
-                       } else {
-                               return (T)performForEach(graph, query, entry, parent, listener, procedure, false);
-                       }
+        } else {
 
-               }
+            hits++;
 
-       }
+            return query.get(graph, this, procedure);
 
-       public <T> void queryMultiRead(final ReadGraphImpl graph, final MultiRead<T> query, final CacheEntry parent, final ListenerBase listener, final AsyncMultiProcedure<T> procedure) {
+        }
 
-               assert(query != null);
-               assert(procedure != null);
+    }
+       */
+       
 
-               final MultiReadEntry entry = multiReadMap.get(query);
+       interface QueryCollectorSupport {
+               public CacheCollectionResult allCaches();
+               public Collection<CacheEntry> getRootList();
+               public int getCurrentSize();
+               public int calculateCurrentSize();
+               public CacheEntryBase iterate(int level);
+               public void remove();
+               public void setLevel(CacheEntryBase entry, int level);
+               public boolean start(boolean flush);
+       }
 
-               if(parent == null && !(listener != null)) {
-                       if(entry != null && entry.isReady()) { 
-                               entry.performFromCache(graph, this, procedure);
-                               return;
-                       }
-               }
+       interface QueryCollector {
 
-               runMultiRead(graph, entry, query, parent, this, listener, procedure);
+               public void collect(int youngTarget, int allowedTimeInMs);
 
        }
 
-       public <T> void queryPrimitiveRead(final ReadGraphImpl graph, final ExternalRead<T> query, final CacheEntry parent, final ListenerBase listener, final Procedure<T> procedure) {
-
-               assert(query != null);
-               assert(procedure != null);
+       class QueryCollectorSupportImpl implements QueryCollectorSupport {
 
-               final ExternalReadEntry entry = externalReadMap.get(query);
+               private static final boolean DEBUG = false;
+               private static final double ITERATION_RATIO = 0.2;
+               
+               private CacheCollectionResult iteration = new CacheCollectionResult();
+               private boolean fresh = true;
+               private boolean needDataInStart = true;
+               
+               QueryCollectorSupportImpl() {
+                       iteration.restart();
+               }
 
-               if(parent == null && !(listener != null)) {
-                       if(entry != null && entry.isReady()) { 
-                               entry.performFromCache(procedure);
-                               return;
+               public CacheCollectionResult allCaches() {
+                       CacheCollectionResult result = new CacheCollectionResult();
+                       QueryProcessor.this.allCaches(result);
+                       result.restart();
+                       return result;
+               }
+               
+               public boolean start(boolean flush) {
+                       // We need new data from query maps
+                       fresh = true;
+                       if(needDataInStart || flush) {
+                               // Last run ended after processing all queries => refresh data
+                               restart(flush ? 0.0 : ITERATION_RATIO);
+                       } else {
+                               // continue with previous big data
                        }
+                       // Notify caller about iteration situation
+                       return iteration.isAtStart();
                }
 
-               runPrimitiveRead(graph, entry, query, parent, this, listener, procedure);
-
-       }
-
-       public <T> void performForEach(ReadGraphImpl parentGraph, final AsyncRead<T> query, final AsyncReadEntry<T> entry, final CacheEntry parent, final ListenerBase base, final AsyncProcedure<T> procedure,
-                       boolean inferredDependency) {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() & THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               assert(!entry.isDiscarded());
-
-               final ListenerEntry listenerEntry = registerDependencies(parentGraph, entry, parent, base, procedure, inferredDependency);
-
-               // FRESH, REFUTED, EXCEPTED go here 
-               if (!entry.isReady()) {
-
-                       entry.setPending();
-
-                       size++;
-
-                       try {
-
-                               final ReadGraphImpl finalParentGraph = parentGraph;
-
-                               query.perform(parentGraph.withParent(entry), new AsyncProcedure<T>() {
-
-                                       @Override
-                                       public void execute(AsyncReadGraph returnGraph, T result) {
-                                               ReadGraphImpl impl = (ReadGraphImpl)returnGraph;
-                                               //AsyncReadGraph resumeGraph = finalParentGraph.newAsync();
-                                               entry.addOrSet(finalParentGraph, result);
-                                               if(listenerEntry != null) {
-                                                       primeListenerEntry(listenerEntry, result);
-                                               }
-                                               try {
-                                                       procedure.execute(finalParentGraph, result);
-                                               } catch (Throwable t) {
-                                                       t.printStackTrace();
-                                               }
-//                                             parentBarrier.dec(query);
-                                       }
-
-                                       @Override
-                                       public void exception(AsyncReadGraph returnGraph, Throwable t) {
-                                               ReadGraphImpl impl = (ReadGraphImpl)returnGraph;
-//                                             AsyncReadGraph resumeGraph = finalParentGraph.newAsync();
-                                               entry.except(finalParentGraph, t);
-                                               try {
-                                                       procedure.exception(finalParentGraph, t);
-                                               } catch (Throwable t2) {
-                                                       t2.printStackTrace();
-                                               }
-//                                             parentBarrier.dec(query);
-                                       }
-
-                                       @Override
-                                       public String toString() {
-                                               return procedure.toString();
-                                       }
-
-                               });
-
-                       } catch (Throwable t) {
-
-                               entry.except(t);
-                               try {
-                                       procedure.exception(parentGraph, t);
-                               } catch (Throwable t2) {
-                                       t2.printStackTrace();
-                               }
-//                             parentBarrier.dec(query);
-
-                       }
-
-                       misses++;
-
-               } else {
-
-                       entry.performFromCache(parentGraph, this, new AsyncProcedure<T>() {
-
-                               @Override
-                               public void exception(AsyncReadGraph graph, Throwable throwable) {
-                                       procedure.exception(graph, throwable);
-                               }
-
-                               @Override
-                               public void execute(AsyncReadGraph graph, T result) {
-                                       procedure.execute(graph, result);
-                                       if(listenerEntry != null) {
-                                               primeListenerEntry(listenerEntry, result);
-                                       }
-                               }
-
-                       });
-
-//                     parentBarrier.dec(query);
-
-                       hits++;
-
-               }
-
-               assert (!entry.isDiscarded());
-
-       }
-
-       public <T> T performForEach(final ReadGraphImpl graph, final Read<T> query, final ReadEntry<T> entry, final CacheEntry parent, final ListenerBase listener, final AsyncProcedure<T> procedure,
-                       boolean inferredDependency) throws Throwable {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() & THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               entry.assertNotDiscarded();
-
-               if(entry.isReady()) {
-
-                       // EXCEPTED goes here
-
-//                     if(procedure != null) entry.performFromCache(graph, this, procedure);
-//                     parentBarrier.dec(query);
-                       hits++;
-
-                       ListenerEntry listenerEntry = registerDependencies(graph, entry, parent, listener, procedure, inferredDependency);
-                       
-                       T result = (T)entry.get(graph, this, procedure); 
-
-                       if(listenerEntry != null) primeListenerEntry(listenerEntry, result);
-
-                       return result;
-
-               } else {
-
-                       // FRESH, REFUTED, PENDING go here
-
-                       entry.setPending();
-
-                       size++;
-                       misses++;
-
-               ListenerEntry listenerEntry = registerDependencies(graph, entry, parent, listener, procedure, inferredDependency);
-
-                       final ReadGraphImpl performGraph = graph.newSync(entry);
-
-                       try {
-
-                               if(Development.DEVELOPMENT)
-                                       Development.recordHistogram("run " + query);
-
-                               T result = query.perform(performGraph);
-                               entry.addOrSet(performGraph, result);
-                               
-                               if(listenerEntry != null) primeListenerEntry(listenerEntry, result);
-
-                               return (T)entry.get(graph, this, procedure);
-
-                       }  catch (Throwable t) {
-
-                               entry.except(t);
-                               return (T)entry.get(graph, this, procedure);
-
-                       }
-
-               } 
-
-       }
-
-       public <T> void performForEach(final ReadGraphImpl graph, final MultiRead<T> query, final MultiReadEntry<T> entry, CacheEntry parent, final ListenerBase listener, final AsyncMultiProcedure<T> procedure,
-                       boolean inferredDependency) {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() & THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               assert(!entry.isPending());
-               assert(!entry.isDiscarded());
-
-               // FRESH, REFUTED, EXCEPTED go here 
-               if (!entry.isReady()) {
-
-                       entry.setPending();
-                       entry.clearResult(querySupport);
-
-                       multiReadMap.put(query, entry);
-                       size++;
-
-                       final ReadGraphImpl newGraph = graph.newSync(entry);
-//                     newGraph.state.barrier.inc();
-
-                       try {
-
-                               query.perform(newGraph, new AsyncMultiProcedure<T>() {
-
-                                       @Override
-                                       public void execute(AsyncReadGraph graph, T result) {
-                                               entry.addOrSet(result);
-                                               try {
-                                                       procedure.execute(graph, result);
-                                               } catch (Throwable t) {
-                                                       t.printStackTrace();
-                                               }
-                                       }
-
-                                       @Override
-                                       public void finished(AsyncReadGraph graph) {
-                                               entry.finish(graph);
-                                               try {
-                                                       procedure.finished(graph);
-                                               } catch (Throwable t) {
-                                                       t.printStackTrace();
-                                               }
-//                                             newGraph.state.barrier.dec();
-//                                             parentBarrier.dec();
-                                       }
-
-                                       @Override
-                                       public void exception(AsyncReadGraph graph, Throwable t) {
-                                               entry.except(t);
-                                               try {
-                                                       procedure.exception(graph, t);
-                                               } catch (Throwable t2) {
-                                                       t2.printStackTrace();
-                                               }
-//                                             newGraph.state.barrier.dec();
-//                                             parentBarrier.dec();
-                                       }
-
-                               });
-
-                       } catch (DatabaseException e) {
-
-                               entry.except(e);
-                               try {
-                                       procedure.exception(graph, e);
-                               } catch (Throwable t2) {
-                                       t2.printStackTrace();
-                               }
-//                             newGraph.state.barrier.dec();
-//                             parentBarrier.dec();
-
-                       } catch (Throwable t) {
-
-                               DatabaseException e = new DatabaseException(t);
-
-                               entry.except(e);
-                               try {
-                                       procedure.exception(graph, e);
-                               } catch (Throwable t2) {
-                                       t2.printStackTrace();
-                               }
-//                             newGraph.state.barrier.dec();
-//                             parentBarrier.dec();
-
-                       }
-
-                       misses++;
-
-               } else {
-
-                       entry.performFromCache(graph, this, procedure);
-                       hits++;
-
-
-               }
-
-               assert (!entry.isDiscarded());
-
-               registerDependencies(graph, entry, parent, listener, procedure, inferredDependency);
-
-       }
-
-
-       public <T> void performForEach(final ReadGraphImpl callerGraph, AsyncMultiRead<T> query, final AsyncMultiReadEntry<T> entry, final CacheEntry parent, final ListenerBase listener, final AsyncMultiProcedure<T> procedure,
-                       boolean inferredDependency) {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() & THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               try {
-
-                       assert(!entry.isDiscarded());
-
-                       // FRESH, REFUTED, EXCEPTED go here 
-                       if (!entry.isReady()) {
-
-                               size++;
-
-                               try {
-
-                                       ReadGraphImpl performGraph = callerGraph.withAsyncParent(entry);
-
-                                       query.perform(performGraph, new AsyncMultiProcedure<T>() {
-
-                                               @Override
-                                               public void execute(AsyncReadGraph graph, T result) {
-                                                       ReadGraphImpl impl = (ReadGraphImpl)graph;
-//                                                     ReadGraphImpl executeGraph = callerGraph.newAsync();
-                                                       entry.addOrSet(result);
-                                                       try {
-                                                               procedure.execute(callerGraph, result);
-                                                       } catch (Throwable t) {
-                                                               t.printStackTrace();
-                                                       }
-                                               }
-
-                                               @Override
-                                               public void finished(AsyncReadGraph graph) {
-                                                       ReadGraphImpl impl = (ReadGraphImpl)graph;
-//                                                     ReadGraphImpl executeGraph = callerGraph.newAsync();
-                                                       entry.finish(callerGraph);
-                                                       try {
-                                                               procedure.finished(callerGraph);
-                                                       } catch (Throwable t) {
-                                                               t.printStackTrace();
-                                                       }
-                                               }
-
-                                               @Override
-                                               public void exception(AsyncReadGraph graph, Throwable t) {
-                                                       ReadGraphImpl impl = (ReadGraphImpl)graph;
-//                                                     ReadGraphImpl executeGraph = callerGraph.newAsync();
-                                                       entry.except(callerGraph, t);
-                                                       try {
-                                                               procedure.exception(callerGraph, t);
-                                                       } catch (Throwable t2) {
-                                                               t2.printStackTrace();
-                                                       }
-                                               }
-
-                                       });
-
-                               } catch (Throwable t) {
-
-                                       entry.except(t);
-                                       try {
-                                               procedure.exception(callerGraph, t);
-                                       } catch (Throwable t2) {
-                                               t2.printStackTrace();
-                                       }
-
-                               }
-
-
-                               misses++;
-
-                       } else {
-
-                               entry.performFromCache(callerGraph, this, procedure);
-
-                               hits++;
-
-                       }
-
-                       assert (!entry.isDiscarded());
-
-                       registerDependencies(callerGraph, entry, parent, listener, procedure, inferredDependency);
-
-               } catch (Throwable t) {
-
-                       Logger.defaultLogError(t);
-
-               } finally {
-
-               }
-
-       }
-
-       public <T> void performForEach(ReadGraphImpl graph, final ExternalRead<T> query, final ExternalReadEntry<T> entry, final CacheEntry parent, final ListenerBase base, final Procedure<T> procedure,
-                       boolean inferredDependency) {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() & THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               assert(!entry.isPending());
-               assert(!entry.isDiscarded());
-
-               registerDependencies(graph, entry, parent, base, procedure, inferredDependency);
-
-               // FRESH, REFUTED, EXCEPTED go here 
-               if (!entry.isReady()) {
-
-                       entry.setPending();
-                       entry.clearResult(querySupport);
-
-                       externalReadMap.put(query, entry);
-                       size++;
-
-                       try {
-
-                               query.register(graph, new Listener<T>() {
-
-                                       AtomicBoolean used = new AtomicBoolean(false);
-
-                                       @Override
-                                       public void execute(T result) {
-                                               
-                                               // Just for safety
-                                               if(entry.isDiscarded()) return;
-                                               if(entry.isExcepted()) entry.setPending();
-                                               
-                                               if(used.compareAndSet(false, true)) {
-                                                       entry.addOrSet(QueryProcessor.this, result);
-                                                       procedure.execute(result);
-                                               } else {
-                                                       entry.queue(result);
-                                                       updatePrimitive(query);
-                                               }
-                                               
-                                       }
-
-                                       @Override
-                                       public void exception(Throwable t) {
-                                               
-                                               entry.except(t);
-
-                                               if(used.compareAndSet(false, true)) {
-                                                       procedure.exception(t);
-                                               } else {
-//                                                     entry.queue(result);
-                                                       updatePrimitive(query);
-                                               }
-                                               
-                                       }
-
-                                       @Override
-                                       public String toString() {
-                                               return procedure.toString();
-                                       }
-
-                                       @Override
-                                       public boolean isDisposed() {
-                                               return entry.isDiscarded() || !isBound(entry);
-                                       }
-
-                               });
-
-                       } catch (Throwable t) {
-
-                               entry.except(t);
-                               procedure.exception(t);
-
-                       }
-
-                       misses++;
-
-               } else {
-
-                       entry.performFromCache(procedure);
-
-                       hits++;
-
-               }
-
-               assert (!entry.isDiscarded());
-
-       }
-
-       private boolean isBound(ExternalReadEntry<?> entry) {
-               if(entry.hasParents()) return true;
-               else if(hasListener(entry)) return true;
-               else return false;
-       }
-
-       synchronized public ListenerEntry registerDependencies(ReadGraphImpl graph, CacheEntry child, CacheEntry parent, ListenerBase listener, Object procedure, boolean inferred) {
-
-               if (parent != null && !inferred) {
-                       try {
-                               if(!child.isImmutable(graph))
-                                       child.addParent(parent);
-                       } catch (DatabaseException e) {
-                               Logger.defaultLogError(e);
-                       }
-                       if(DebugPolicy.DEPENDENCIES) System.out.println(child + " -> " + parent);
-               }
-
-               if (listener != null) {
-                       return registerListener(child, listener, procedure);
-               } else {
-                       return null;
-               }
-
-       }
-
-       public <Procedure> void performForEach(ReadGraphImpl graph, BinaryQuery<Procedure> query, CacheEntry parent, ListenerBase listener, Procedure procedure) {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() & THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               try {
-
-                       registerDependencies(graph, query, parent, listener, procedure, false);
-
-                       // FRESH, REFUTED, EXCEPTED go here 
-                       if (!query.isReady()) {
-
-                               boolean fresh = query.isFresh();
-
-                               if(fresh) {
-                                       size++;
-                               }
-
-                               query.computeForEach(graph, this, procedure, true);
-
-                               misses++;
-
-                       } else {
-
-                               query.performFromCache(graph, this, procedure);
-
-                               hits++;
-
-                       }
-
-               } catch (Throwable t) {
-
-                       Logger.defaultLogError(t);
-
-               }
-       }
-
-       public <Procedure> Object performForEach(ReadGraphImpl graph, UnaryQuery<Procedure> query, CacheEntry parent, ListenerBase listener, Procedure procedure) {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() &  THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               try {
-
-                       assert(query.assertNotDiscarded());
-
-                       registerDependencies(graph, query, parent, listener, procedure, false);
-
-                       // FRESH, REFUTED, EXCEPTED go here 
-                       if (!query.isReady()) {
-
-                               size++;
-                               misses++;
-
-                               return query.computeForEach(graph, this, procedure, true);
-
-
-                       } else {
-
-                               hits++;
-
-                               return query.performFromCache(graph, this, procedure);
-
-                       }
-
-               } catch (Throwable t) {
-
-                       Logger.defaultLogError(t);
-                       return null;
-
-               } 
-
-       }
-       
-       static class Dummy implements InternalProcedure<Object>, IntProcedure {
-
-               @Override
-               public void execute(ReadGraphImpl graph, int i) {
-               }
-
-               @Override
-               public void finished(ReadGraphImpl graph) {
-               }
-
-               @Override
-               public void execute(ReadGraphImpl graph, Object result) {
-               }
-
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
-               
-       }
-       
-       private static final Dummy dummy = new Dummy();
-
-    public <Procedure> Object performForEach2(ReadGraphImpl graph, UnaryQuery<Procedure> query, CacheEntry parent, ListenerBase listener, Procedure procedure) throws Throwable {
-
-        if (DebugPolicy.PERFORM)
-            System.out.println("PE[ " + (query.hashCode() &  THREAD_MASK) + "] " + query);
-
-        assert (!dirty);
-        assert (!collecting);
-
-        assert(query.assertNotDiscarded());
-
-        registerDependencies(graph, query, parent, listener, procedure, false);
-
-        // FRESH, REFUTED, EXCEPTED go here 
-        if (!query.isReady()) {
-
-            size++;
-            misses++;
-
-            query.computeForEach(graph, this, (Procedure)dummy, true);
-            return query.get(graph, this, null);
-
-        } else {
-
-            hits++;
-
-            return query.get(graph, this, procedure);
-
-        }
-
-    }
-       
-       public <Procedure> void performForEach(ReadGraphImpl graph, StringQuery<Procedure> query, CacheEntry parent, final ListenerBase listener, Procedure procedure) {
-
-               if (DebugPolicy.PERFORM)
-                       System.out.println("PE[ " + (query.hashCode() & THREAD_MASK) + "] " + query);
-
-               assert (!dirty);
-               assert (!collecting);
-
-               try {
-
-                       if(query.isDiscarded()) {
-                               System.err.println("aff");
-                       }
-                       assert(!query.isDiscarded());
-
-                       // FRESH, REFUTED, EXCEPTED go here 
-                       if (!query.isReady()) {
-
-                               query.computeForEach(graph.withAsyncParent(query), this, procedure);
-
-                               size++;
-                               misses++;
-
-                       } else {
-
-                               query.performFromCache(graph, this, procedure);
-
-                               hits++;
-
-                       }
-
-                       assert (!query.isDiscarded());
-
-                       registerDependencies(graph, query, parent, listener, procedure, false);
-
-               } catch (Throwable t) {
-
-                       t.printStackTrace();
-                       Logger.defaultLogError(t);
-
-               }
-
-       }
-
-       interface QueryCollectorSupport {
-               public CacheCollectionResult allCaches();
-               public Collection<CacheEntry> getRootList();
-               public int getCurrentSize();
-               public int calculateCurrentSize();
-               public CacheEntryBase iterate(int level);
-               public void remove();
-               public void setLevel(CacheEntryBase entry, int level);
-               public boolean start(boolean flush);
-       }
-
-       interface QueryCollector {
-
-               public void collect(int youngTarget, int allowedTimeInMs);
-
-       }
-
-       class QueryCollectorSupportImpl implements QueryCollectorSupport {
-
-               private static final boolean DEBUG = false;
-               private static final double ITERATION_RATIO = 0.2;
-               
-               private CacheCollectionResult iteration = new CacheCollectionResult();
-               private boolean fresh = true;
-               private boolean needDataInStart = true;
-               
-               QueryCollectorSupportImpl() {
-                       iteration.restart();
-               }
-
-               public CacheCollectionResult allCaches() {
-                       CacheCollectionResult result = new CacheCollectionResult();
-                       QueryProcessor.this.allCaches(result);
-                       result.restart();
-                       return result;
-               }
-               
-               public boolean start(boolean flush) {
-                       // We need new data from query maps
-                       fresh = true;
-                       if(needDataInStart || flush) {
-                               // Last run ended after processing all queries => refresh data
-                               restart(flush ? 0.0 : ITERATION_RATIO);
-                       } else {
-                               // continue with previous big data
-                       }
-                       // Notify caller about iteration situation
-                       return iteration.isAtStart();
-               }
-
-               private void restart(double targetRatio) {
-                       
-                       needDataInStart = true;
+               private void restart(double targetRatio) {
+                       
+                       needDataInStart = true;
 
                        long start = System.nanoTime();
                        if(fresh) {
@@ -1685,299 +753,41 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                }
                
                @Override
-               public void setLevel(CacheEntryBase entry, int level) {
-                       iteration.setLevel(entry, level);
-               }
-
-               public Collection<CacheEntry> getRootList() {
-
-                       ArrayList<CacheEntry> result = new ArrayList<CacheEntry>();
-
-                       for (Object e : valueMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : directPredicatesMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : objectsMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : directObjectsMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : principalTypesMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : superRelationsMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : superTypesMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : typesMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : objectsMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : assertedStatementsMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : readMap.values()) {
-                               if(e instanceof CacheEntry) {
-                                       result.add((CacheEntry) e);
-                               } else {
-                                       System.err.println("e=" + e);
-                               }
-                       }
-                       for (Object e : asyncReadMap.values()) {
-                               if(e instanceof CacheEntry) {
-                                       result.add((CacheEntry) e);
-                               } else {
-                                       System.err.println("e=" + e);
-                               }
-                       }
-                       for (Object e : externalReadMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-                       for (Object e : orderedSetMap.values()) {
-                               result.add((CacheEntry) e);
-                       }
-
-                       return result;
-
-               }
-
-               @Override
-               public int calculateCurrentSize() {
-                       
-                       int realSize = 0;
-                       
-                       realSize += directPredicatesMap.size();
-                       realSize += principalTypesMap.size();
-                       realSize += uriToResourceMap.size();
-                       realSize += namespaceIndexMap22.size();
-                       realSize += projectsMap.size();
-                       
-                       realSize += relationInfoMap.size();
-                       realSize += superTypesMap.size();
-                       realSize += typeHierarchyMap.size();
-                       realSize += superRelationsMap.size();
-                       realSize += typesMap.size();
-                       
-                       realSize += valueMap.size();
-                       realSize += directObjectsMap.size();
-                       realSize += objectsMap.size();
-                       realSize += orderedSetMap.size();
-                       realSize += predicatesMap.size();
-                       
-                       realSize += statementsMap.size();
-                       realSize += assertedPredicatesMap.size();
-                       realSize += assertedStatementsMap.size();
-                       realSize += externalReadMap.size();
-                       realSize += asyncReadMap.size();
-                       
-                       realSize += readMap.size();
-                       realSize += asyncMultiReadMap.size();
-                       realSize += multiReadMap.size();
-                       
-                       size = realSize;
-                       
-                       return realSize;
-                       
-               }
-
-               @Override
-               public int getCurrentSize() {
-                       return size;
-               }
-
-       }
-       //    final private static int MINIMUM_SIZE = (int)(Runtime.getRuntime().maxMemory() / 600);
-
-       private QueryCollectorSupport collectorSupport = new QueryCollectorSupportImpl();
-       private QueryCollector collector = new QueryCollectorImpl(this, collectorSupport);
-
-    public int querySize() {
-        return size;
-    }
-
-       public void gc(int youngTarget, int allowedTimeInMs) {
-
-               collector.collect(youngTarget, allowedTimeInMs);
-
-       }
-
-       public ListenerEntry registerListener(final CacheEntry entry, final ListenerBase base, final Object procedure) {
-
-               assert (entry != null);
-
-               if (base.isDisposed())
-                       return null;
-
-               return addListener(entry, base, procedure);
-
-       }
-
-       private void primeListenerEntry(final ListenerEntry entry, final Object result) {
-               entry.setLastKnown(result);
-       }
-
-       private ListenerEntry addListener(CacheEntry entry, ListenerBase base, Object procedure) {
-
-               assert (entry != null);
-               assert (procedure != null);
-
-               ArrayList<ListenerEntry> list = listeners.get(entry);
-               if (list == null) {
-                       list = new ArrayList<ListenerEntry>(1);
-                       listeners.put(entry, list);
-               }
-
-               ListenerEntry result = new ListenerEntry(entry, base, procedure);
-               int currentIndex = list.indexOf(result);
-               // There was already a listener
-               if(currentIndex > -1) {
-                       ListenerEntry current = list.get(currentIndex);
-                       if(!current.base.isDisposed()) return null;
-                       list.set(currentIndex, result);
-               } else {
-                       list.add(result);
-               }
-
-               if(DebugPolicy.LISTENER) {
-                       new Exception().printStackTrace();
-                       System.out.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure);
-               }
-
-               return result;
-
-       }
-
-       private void scheduleListener(ListenerEntry entry) {
-               assert (entry != null);
-               if(DebugPolicy.LISTENER) System.out.println("Scheduled " + entry.procedure);
-               scheduledListeners.add(entry);
-       }
-
-       private void removeListener(ListenerEntry entry) {
-               assert (entry != null);
-               ArrayList<ListenerEntry> list = listeners.get(entry.entry);
-               if(list == null) return;
-               boolean success = list.remove(entry);
-               assert (success);
-               if (list.isEmpty())
-                       listeners.remove(entry.entry);
-       }
-
-       private boolean hasListener(CacheEntry entry) {
-               if(listeners.get(entry) != null) return true;
-               return false;
-       }
-
-       boolean hasListenerAfterDisposing(CacheEntry entry) {
-               if(listeners.get(entry) != null) {
-                       ArrayList<ListenerEntry> entries = listeners.get(entry);
-                       ArrayList<ListenerEntry> list = null;
-                       for (ListenerEntry e : entries) {
-                               if (e.base.isDisposed()) {
-                                       if(list == null) list = new ArrayList<ListenerEntry>();
-                                       list.add(e);
-                               }
-                       }
-                       if(list != null) {
-                               for (ListenerEntry e : list) {
-                                       entries.remove(e);
-                               }
-                       }
-                       if (entries.isEmpty()) {
-                               listeners.remove(entry);
-                               return false;
-                       }
-                       return true;
+               public void setLevel(CacheEntryBase entry, int level) {
+                       iteration.setLevel(entry, level);
                }
-               return false;
-       }
-
-       List<ListenerEntry> getListenerEntries(CacheEntry entry) {
-               hasListenerAfterDisposing(entry);
-               if(listeners.get(entry) != null)
-                       return listeners.get(entry);
-               else 
-                       return Collections.emptyList();
-       }
-
-       void processListenerReport(CacheEntry entry, Map<CacheEntry, Set<ListenerBase>> workarea) {
-
-               if(!workarea.containsKey(entry)) {
-
-                       HashSet<ListenerBase> ls = new HashSet<ListenerBase>();
-                       for(ListenerEntry e : getListenerEntries(entry))
-                               ls.add(e.base);
-
-                       workarea.put(entry, ls);
-
-                       for(CacheEntry parent : entry.getParents(this)) {
-                               processListenerReport(parent, workarea);
-                               ls.addAll(workarea.get(parent));
-                       }
 
+               public Collection<CacheEntry> getRootList() {
+                       return cache.getRootList();
                }
 
-       }
-
-       public synchronized ListenerReport getListenerReport() throws IOException {
-
-               class ListenerReportImpl implements ListenerReport {
-
-                       Map<CacheEntry, Set<ListenerBase>> workarea = new HashMap<CacheEntry, Set<ListenerBase>>();
-
-                       @Override
-                       public void print(PrintStream b) {
-                               Map<ListenerBase, Integer> hist = new HashMap<ListenerBase, Integer>();
-                               for(Map.Entry<CacheEntry, Set<ListenerBase>> e : workarea.entrySet()) {
-                                       for(ListenerBase l : e.getValue()) {
-                                               Integer i = hist.get(l);
-                                               hist.put(l, i != null ? i-1 : -1);
-                                       }
-                               }
-
-                               for(Pair<ListenerBase, Integer> p : CollectionUtils.valueSortedEntries(hist)) {
-                                       b.print("" + -p.second + " " + p.first + "\n");
-                               }
-
-                               b.flush();
-                       }
-
+               @Override
+               public int calculateCurrentSize() {
+                       return cache.calculateCurrentSize();
                }
 
-               ListenerReportImpl result = new ListenerReportImpl();
-
-               Collection<CacheEntryBase> all = allCaches(new CacheCollectionResult()).toCollection();
-               for(CacheEntryBase entry : all) {
-                       hasListenerAfterDisposing(entry);
-               }
-               for(CacheEntryBase entry : all) {
-                       processListenerReport(entry, result.workarea);
+               @Override
+               public int getCurrentSize() {
+                       return cache.size;
                }
 
-               return result;
-
        }
+       //    final private static int MINIMUM_SIZE = (int)(Runtime.getRuntime().maxMemory() / 600);
 
-       public synchronized String reportListeners(File file) throws IOException {
+       private QueryCollectorSupport collectorSupport = new QueryCollectorSupportImpl();
+       private QueryCollector collector = new QueryCollectorImpl(this, collectorSupport);
 
-               if (!isAlive())
-                       return "Disposed!";
+    public int querySize() {
+        return cache.size;
+    }
 
-               PrintStream b = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
-               ListenerReport report = getListenerReport();
-               report.print(b);
+       public void gc(int youngTarget, int allowedTimeInMs) {
 
-               return "Done reporting listeners.";
+               collector.collect(youngTarget, allowedTimeInMs);
 
        }
 
+
        void processParentReport(CacheEntry entry, Map<CacheEntry, Set<CacheEntry>> workarea) {
 
                if(entry.isDiscarded()) return;
@@ -2049,7 +859,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                int listeners = 0;
 
                for(CacheEntry entry : workarea.keySet()) {
-                       boolean listener = hasListenerAfterDisposing(entry);
+                       boolean listener = listening.hasListenerAfterDisposing(entry);
                        boolean hasParents = entry.getParents(this).iterator().hasNext();
                        if(listener) {
                                // Bound
@@ -2078,7 +888,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        int unboundCounter = 0;
                        int unknownCounter = 0;
 
-                       for(CacheEntry entry : workarea.keySet()) {
+                       for(CacheEntry<?> entry : workarea.keySet()) {
 
                                //System.err.println("process " + entry);
 
@@ -2139,11 +949,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                for(CacheEntry entry : workarea.keySet()) {
                        Class<?> clazz = entry.getClass();
-                       if(entry instanceof ReadEntry) clazz = ((ReadEntry)entry).request.getClass(); 
-                       else if(entry instanceof MultiReadEntry) clazz = ((MultiReadEntry)entry).request.getClass(); 
-                       else if(entry instanceof AsyncReadEntry) clazz = ((AsyncReadEntry)entry).request.getClass(); 
-                       else if(entry instanceof AsyncMultiReadEntry) clazz = ((AsyncMultiReadEntry)entry).request.getClass(); 
-                       else if(entry instanceof ExternalReadEntry) clazz = ((ExternalReadEntry)entry).request.getClass(); 
+                       if(entry instanceof ReadEntry) clazz = ((ReadEntry)entry).id.getClass(); 
+                       else if(entry instanceof MultiReadEntry) clazz = ((MultiReadEntry)entry).id.getClass(); 
+                       else if(entry instanceof AsyncReadEntry) clazz = ((AsyncReadEntry)entry).id.getClass(); 
+                       else if(entry instanceof AsyncMultiReadEntry) clazz = ((AsyncMultiReadEntry)entry).id.getClass(); 
+                       else if(entry instanceof ExternalReadEntry) clazz = ((ExternalReadEntry)entry).id.getClass(); 
                        Integer c = counts.get(clazz);
                        if(c == null) counts.put(clazz, -1);
                        else counts.put(clazz, c-1);
@@ -2213,7 +1023,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                b.print("// Entry parent listing\n");
                for(CacheEntry entry : workarea.keySet()) {
                        int status = flagMap.get(entry);
-                       boolean hasListener = hasListenerAfterDisposing(entry);
+                       boolean hasListener = listening.hasListenerAfterDisposing(entry);
                        b.print("Q " + entry.toString());
                        if(hasListener) {
                                b.print(" (L" + status + ")");
@@ -2259,22 +1069,6 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        }
 
-       class UpdateEntry {
-
-               public CacheEntry caller;
-
-               public CacheEntry entry;
-
-               public int         indent;
-
-               public UpdateEntry(CacheEntry caller, CacheEntry entry, int indent) {
-                       this.caller = caller;
-                       this.entry = entry;
-                       this.indent = indent;
-               }
-
-       };
-
        boolean removeQuery(CacheEntry entry) {
 
                // This entry has been removed before. No need to do anything here.
@@ -2286,8 +1080,8 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                query.removeEntry(this);
 
-               updates++;
-               size--;
+               cache.updates++;
+               cache.size--;
 
                if((entry.getGCStatus() & CacheEntry.HAS_BEEN_BOUND) != 0)
                        boundQueries--;
@@ -2308,8 +1102,6 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                CacheEntry entry = e.entry;
 
-//             System.err.println("updateQuery " + entry);
-               
                /*
                 * If the dependency graph forms a DAG, some entries are inserted in the
                 * todo list many times. They only need to be processed once though.
@@ -2317,32 +1109,32 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                if (entry.isDiscarded()) {
                        if (Development.DEVELOPMENT) {
                                if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
-                                       System.out.print("D");
+                                       System.err.print("D");
                                        for (int i = 0; i < e.indent; i++)
-                                               System.out.print(" ");
-                                       System.out.println(entry.getQuery());
+                                               System.err.print(" ");
+                                       System.err.println(entry.getQuery());
                                }
                        }
 //                     System.err.println(" => DISCARDED");
                        return false;
                }
 
-               if (entry.isRefuted()) {
-                       if (Development.DEVELOPMENT) {
-                               if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
-                                       System.out.print("R");
-                                       for (int i = 0; i < e.indent; i++)
-                                               System.out.print(" ");
-                                       System.out.println(entry.getQuery());
-                               }
-                       }
-                       return false;
-               }
+//             if (entry.isRefuted()) {
+//                     if (Development.DEVELOPMENT) {
+//                             if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
+//                                     System.err.print("R");
+//                                     for (int i = 0; i < e.indent; i++)
+//                                             System.err.print(" ");
+//                                     System.err.println(entry.getQuery());
+//                             }
+//                     }
+//                     return false;
+//             }
 
                if (entry.isExcepted()) {
                        if (Development.DEVELOPMENT) {
                                if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
-                                       System.out.print("E");
+                                       System.err.print("E");
                                }
                        }
                }
@@ -2350,33 +1142,33 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                if (entry.isPending()) {
                        if (Development.DEVELOPMENT) {
                                if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
-                                       System.out.print("P");
+                                       System.err.print("P");
                                }
                        }
                }
 
-               updates++;
+               cache.updates++;
 
                if (Development.DEVELOPMENT) {
                        if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
-                               System.out.print("U ");
+                               System.err.print("U ");
                                for (int i = 0; i < e.indent; i++)
-                                       System.out.print(" ");
-                               System.out.print(entry.getQuery());
+                                       System.err.print(" ");
+                               System.err.print(entry.getQuery());
                        }
                }
 
                Query query = entry.getQuery();
                int type = query.type();
 
-               boolean hasListener = hasListener(entry); 
+               boolean hasListener = listening.hasListener(entry); 
 
                if (Development.DEVELOPMENT) {
                        if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
-                               if(hasListener(entry)) {
-                                       System.out.println(" (L)");
+                               if(listening.hasListener(entry)) {
+                                       System.err.println(" (L)");
                                } else {
-                                       System.out.println("");
+                                       System.err.println("");
                                }
                        }
                }
@@ -2420,43 +1212,23 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             System.err.println(" => FOO " + type);
 
                if (hasListener) {
-                       ArrayList<ListenerEntry> entries = listeners.get(entry);
+                       ArrayList<ListenerEntry> entries = listening.listeners.get(entry);
                        if(entries != null) {
                                for (ListenerEntry le : entries) {
-                                       scheduleListener(le);
+                                       listening.scheduleListener(le);
                                }
                        }
                }
 
                // If invalid, update parents
                if (type == RequestFlags.INVALIDATE) {
-                       updateParents(e.indent, entry, todo);
+                       listening.updateParents(e.indent, entry, todo);
                }
 
                return hasListener;
 
        }
 
-       private void updateParents(int indent, CacheEntry entry, LinkedList<UpdateEntry> todo) {
-
-               Iterable<CacheEntry> oldParents = entry.getParents(this);
-               for (CacheEntry parent : oldParents) {
-//                     System.err.println("updateParents " + entry + " => " + parent);
-                       if(!parent.isDiscarded())
-                               todo.push(new UpdateEntry(entry, parent, indent + 2));
-               }
-
-       }
-
-       private boolean pruneListener(ListenerEntry entry) {
-               if (entry.base.isDisposed()) {
-                       removeListener(entry);
-                       return true;
-               } else {
-                       return false;
-               }
-       }
-
        /**
         * @param av1 an array (guaranteed)
         * @param av2 any object
@@ -2492,29 +1264,35 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
 
 
-       final private Object compareTo(ReadGraphImpl graph, final CacheEntry entry, final Object oldValue) {
+       final Object compareTo(ReadGraphImpl graph, final CacheEntry entry, final Object oldValue) {
 
                try {
 
                        Query query = entry.getQuery();
 
-                       if(DebugPolicy.RECOMPUTE) System.out.println("R " + query);
+                       if (Development.DEVELOPMENT) {
+                               if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_RECOMPUTE, Bindings.BOOLEAN)) {
+                                       System.err.println("R " + query);
+                               }
+                       }
 
                        entry.prepareRecompute(querySupport);
                        
-                       ReadGraphImpl parentGraph = graph.withParent(entry);
+                       ReadGraphImpl parentGraph = graph.forRecompute(entry);
 
-                       query.recompute(parentGraph, this, entry);
+                       query.recompute(parentGraph);
 
                        if(entry.isExcepted()) return ListenerEntry.NO_VALUE;
 
                        Object newValue = entry.getResult();
 
                        if (ListenerEntry.NO_VALUE == oldValue) {
-                               if(DebugPolicy.CHANGES) {
-                                       System.out.println("C " + query);
-                                       System.out.println("- " + oldValue);
-                                       System.out.println("- " + newValue);
+                               if (Development.DEVELOPMENT) {
+                                       if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_CHANGES, Bindings.BOOLEAN)) {
+                                               System.out.println("C " + query);
+                                               System.out.println("- " + oldValue);
+                                               System.out.println("- " + newValue);
+                                       }
                                }
                                return newValue;
                        }
@@ -2530,10 +1308,12 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        } else
                                changed = (oldValue != null);
 
-                       if(DebugPolicy.CHANGES && changed) {
-                               System.out.println("C " + query);
-                               System.out.println("- " + oldValue);
-                               System.out.println("- " + newValue);
+                       if (Development.DEVELOPMENT) {
+                               if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_CHANGES, Bindings.BOOLEAN)) {
+                                       System.err.println("C " + query);
+                                       System.err.println("- " + oldValue);
+                                       System.err.println("- " + newValue);
+                               }
                        }
 
                        return changed ? newValue : ListenerEntry.NOT_CHANGED;
@@ -2548,78 +1328,6 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        }
 
-       public boolean hasScheduledUpdates() {
-               return !scheduledListeners.isEmpty();
-       }
-
-       public void performScheduledUpdates(WriteGraphImpl graph) {
-
-               assert (!updating);
-               assert (!collecting);
-               assert (!firingListeners);
-
-               firingListeners = true;
-
-               try {
-
-                       // Performing may cause further events to be scheduled.
-                       while (!scheduledListeners.isEmpty()) {
-
-//                             graph.restart();
-//                             graph.state.barrier.inc();
-
-                               // Clone current events to make new entries possible during
-                               // firing.
-                               THashSet<ListenerEntry> entries = scheduledListeners;
-                               scheduledListeners = new THashSet<ListenerEntry>();
-
-                               ArrayList<ListenerEntry> schedule = new ArrayList<ListenerEntry>();
-
-                               for (ListenerEntry listenerEntry : entries) {
-
-                                       if (pruneListener(listenerEntry)) {
-                                               if(DebugPolicy.LISTENER) System.out.println("Pruned " + listenerEntry.procedure);
-                                               continue;
-                                       }
-
-                                       final CacheEntry entry = listenerEntry.entry;
-                                       assert (entry != null);
-
-                                       Object newValue = compareTo(graph, entry, listenerEntry.getLastKnown());
-
-                                       if (newValue != ListenerEntry.NOT_CHANGED) {
-                                               if(DebugPolicy.LISTENER)
-                                                       System.out.println("Add to schedule " + listenerEntry.procedure + " with " + newValue);
-                                               schedule.add(listenerEntry);
-                                               listenerEntry.setLastKnown(entry.getResult());
-                                       }
-
-                               }
-
-                               for(ListenerEntry listenerEntry : schedule) {
-                                       final CacheEntry entry = listenerEntry.entry;
-                                       if(DebugPolicy.LISTENER)
-                                               System.out.println("Firing " + listenerEntry.procedure);
-                                       try {
-                                               if(DebugPolicy.LISTENER)
-                                                       System.out.println("Firing " + listenerEntry.procedure + " for " + listenerEntry.entry);
-                                               entry.performFromCache(graph, this, listenerEntry.procedure);
-                                       } catch (Throwable t) {
-                                               t.printStackTrace();
-                                       }
-                               }
-
-//                             graph.state.barrier.dec();
-//                             graph.waitAsync(null);
-//                             graph.state.barrier.assertReady();
-
-                       }
-
-               } finally {
-                       firingListeners = false;
-               }
-
-       }
 
        /**
         * 
@@ -2627,7 +1335,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
         */
        public boolean update(final ReadGraphImpl graph, final CacheEntry entry) {
 
-               assert (!collecting);
+               assert (!cache.collecting);
                assert (!updating);
                updating = true;
 
@@ -2662,7 +1370,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                                                Object newValue = compareTo(graph, immediate, ListenerEntry.NO_VALUE);
                                                if (newValue != ListenerEntry.NOT_CHANGED)
-                                                       updateParents(0, immediate, todo);
+                                                       listening.updateParents(0, immediate, todo);
 
                                        } else {
 
@@ -2670,10 +1378,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                                                Object newValue = compareTo(graph, immediate, oldValue);
 
                                                if (newValue != ListenerEntry.NOT_CHANGED) {
-                                                       updateParents(0, immediate, todo);
+                                                       listening.updateParents(0, immediate, todo);
                                                } else {
                                                        // If not changed, keep the old value
                                                        immediate.setResult(oldValue);
+                                                       immediate.setReady();
                                                        listenersUnknown = true;
                                                }
 
@@ -2695,8 +1404,6 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        }
 
-       volatile public boolean dirty = false;
-
        private ObjectUpdateSet scheduledObjectUpdates = new ObjectUpdateSet();
        private ValueUpdateSet scheduledValueUpdates = new ValueUpdateSet();
        private ValueUpdateSet scheduledInvalidates = new ValueUpdateSet();
@@ -2704,9 +1411,28 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        private Object primitiveUpdateLock = new Object();
        private THashSet scheduledPrimitiveUpdates = new THashSet();
 
-       public void performDirtyUpdates(final ReadGraphImpl graph) {
+       private ArrayList<CacheEntry> refutations = new ArrayList<>();
+       
+       private void markForUpdate(ReadGraphImpl graph, CacheEntry e) {
+               e.refute();
+               refutations.add(e);
+       }
+
+       private void updateRefutations(ReadGraphImpl graph) {
+               
+               for(CacheEntry e : refutations)
+                       update(graph, e);
+               
+               refutations.clear();
+               
+       }
+       
+       public void propagateChangesInQueryCache(final ReadGraphImpl graph) {
+               
+               // Make sure that listening has performed its work
+               listening.sync();
 
-               dirty = false;
+               cache.dirty = false;
                lastInvalidate = 0;
 
                if (Development.DEVELOPMENT) {
@@ -2723,28 +1449,37 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        final int subject = (int)(arg0 >>> 32);
                        final int predicate = (int)(arg0 & 0xffffffff);
 
-                       for(Objects o : Objects.entries(QueryProcessor.this, subject)) update(graph, o);
-                       for(DirectObjects o : DirectObjects.entries(QueryProcessor.this, subject)) update(graph, o);
-                       for(Statements o : Statements.entries(QueryProcessor.this, subject)) update(graph, o);
+                       for(Objects o : QueryCache.entriesObjects(QueryProcessor.this, subject)) markForUpdate(graph, o);
+                       for(DirectObjects o : QueryCache.entriesDirectObjects(QueryProcessor.this, subject)) markForUpdate(graph, o);
+                       for(Statements o : QueryCache.entriesStatements(QueryProcessor.this, subject)) markForUpdate(graph, o);
 
                        if(predicate == instanceOf || predicate == inherits || predicate == subrelationOf) {
-                               PrincipalTypes principalTypes = PrincipalTypes.entry(QueryProcessor.this, subject);
-                               if(principalTypes != null) update(graph, principalTypes);
-                               Types types = Types.entry(QueryProcessor.this, subject);
-                               if(types != null) update(graph, types);
+                               PrincipalTypes principalTypes = QueryCache.entryPrincipalTypes(QueryProcessor.this, subject);
+                               if(principalTypes != null) markForUpdate(graph, principalTypes);
+                               Types types = QueryCache.entryTypes(QueryProcessor.this, subject);
+                               if(types != null) markForUpdate(graph, types);
                        }
 
                        if(predicate == subrelationOf) {
                                SuperRelations superRelations = SuperRelations.entry(QueryProcessor.this, subject);
-                               if(superRelations != null) update(graph, superRelations);
+                               if(superRelations != null) markForUpdate(graph, superRelations);
                        }
 
-                       DirectPredicates dp = DirectPredicates.entry(QueryProcessor.this, subject);
-                       if(dp != null) update(graph, dp);
-                       OrderedSet os = OrderedSet.entry(QueryProcessor.this, predicate);
-                       if(os != null) update(graph, os);
+                       DirectPredicates dp = QueryCache.entryDirectPredicates(QueryProcessor.this, subject);
+                       if(dp != null) markForUpdate(graph, dp);
+                       OrderedSet os = QueryCache.entryOrderedSet(QueryProcessor.this, predicate);
+                       if(os != null) markForUpdate(graph, os);
 
+                       updateRefutations(graph);
+                       
                        scheduledObjectUpdates.clear();
+
+                       if (Development.DEVELOPMENT) {
+                               if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
+                                       System.err.println("== Query update ends ==");
+                               }
+                       }
+
                        return;
 
                }
@@ -2754,10 +1489,19 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                        int arg0 = scheduledValueUpdates.getFirst();
 
-                       ValueQuery valueQuery = ValueQuery.entry(QueryProcessor.this, arg0);
-                       if(valueQuery != null) update(graph, valueQuery);
+                       ValueQuery valueQuery = QueryCache.entryValueQuery(QueryProcessor.this, arg0);
+                       if(valueQuery != null) markForUpdate(graph, valueQuery);
+
+                       updateRefutations(graph);
 
                        scheduledValueUpdates.clear();
+
+                       if (Development.DEVELOPMENT) {
+                               if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
+                                       System.err.println("== Query update ends ==");
+                               }
+                       }
+                       
                        return;
 
                }
@@ -2771,30 +1515,12 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        scheduledPrimitiveUpdates = new THashSet();
                }
 
-               primitiveUpdates.forEach(new TObjectProcedure() {
-
-                       @Override
-                       public boolean execute(Object arg0) {
-
-                               ExternalReadEntry query = (ExternalReadEntry)externalReadMap.get(arg0);
-                               if (query != null) {
-                                       boolean listening = update(graph, query);
-                                       if (!listening && !query.hasParents()) {
-                                               externalReadMap.remove(arg0);
-                                               query.discard();
-                                       }
-                               }
-                               return true;
-                       }
-
-               });
-
                scheduledValueUpdates.forEach(new TIntProcedure() {
 
                        @Override
                        public boolean execute(int arg0) {
-                               ValueQuery valueQuery = ValueQuery.entry(QueryProcessor.this, arg0);
-                               if(valueQuery != null) update(graph, valueQuery);
+                               ValueQuery valueQuery = QueryCache.entryValueQuery(QueryProcessor.this, arg0);
+                               if(valueQuery != null) markForUpdate(graph, valueQuery);
                                return true;
                        }
 
@@ -2805,16 +1531,16 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        @Override
                        public boolean execute(int resource) {
                                
-                               ValueQuery valueQuery = ValueQuery.entry(QueryProcessor.this, resource);
-                               if(valueQuery != null) update(graph, valueQuery);
+                               ValueQuery valueQuery = QueryCache.entryValueQuery(QueryProcessor.this, resource);
+                               if(valueQuery != null) markForUpdate(graph, valueQuery);
                                
-                               PrincipalTypes principalTypes = PrincipalTypes.entry(QueryProcessor.this, resource);
-                               if(principalTypes != null) update(graph, principalTypes);
-                               Types types = Types.entry(QueryProcessor.this, resource);
-                               if(types != null) update(graph, types);
+                               PrincipalTypes principalTypes = QueryCache.entryPrincipalTypes(QueryProcessor.this, resource);
+                               if(principalTypes != null) markForUpdate(graph, principalTypes);
+                               Types types = QueryCache.entryTypes(QueryProcessor.this, resource);
+                               if(types != null) markForUpdate(graph, types);
 
                                SuperRelations superRelations = SuperRelations.entry(QueryProcessor.this, resource);
-                               if(superRelations != null) update(graph, superRelations);
+                               if(superRelations != null) markForUpdate(graph, superRelations);
 
                                predicates.add(resource);
                                
@@ -2832,15 +1558,15 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                                final int predicate = (int)(arg0 & 0xffffffff);
 
                                if(predicate == instanceOf || predicate == inherits || predicate == subrelationOf) {
-                                       PrincipalTypes principalTypes = PrincipalTypes.entry(QueryProcessor.this, subject);
-                                       if(principalTypes != null) update(graph, principalTypes);
-                                       Types types = Types.entry(QueryProcessor.this, subject);
-                                       if(types != null) update(graph, types);
+                                       PrincipalTypes principalTypes = QueryCache.entryPrincipalTypes(QueryProcessor.this, subject);
+                                       if(principalTypes != null) markForUpdate(graph, principalTypes);
+                                       Types types = QueryCache.entryTypes(QueryProcessor.this, subject);
+                                       if(types != null) markForUpdate(graph, types);
                                }
 
                                if(predicate == subrelationOf) {
                                        SuperRelations superRelations = SuperRelations.entry(QueryProcessor.this, subject);
-                                       if(superRelations != null) update(graph, superRelations);
+                                       if(superRelations != null) markForUpdate(graph, superRelations);
                                }
 
                                predicates.add(subject);
@@ -2857,12 +1583,12 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        @Override
                        public boolean execute(final int subject) {
 
-                               for(Objects o : Objects.entries(QueryProcessor.this, subject)) update(graph, o);
-                               for(DirectObjects o : DirectObjects.entries(QueryProcessor.this, subject)) update(graph, o);
-                               for(Statements o : Statements.entries(QueryProcessor.this, subject)) update(graph, o);
+                               for(Objects o : QueryCache.entriesObjects(QueryProcessor.this, subject)) markForUpdate(graph, o);
+                               for(DirectObjects o : QueryCache.entriesDirectObjects(QueryProcessor.this, subject)) markForUpdate(graph, o);
+                               for(Statements o : QueryCache.entriesStatements(QueryProcessor.this, subject)) markForUpdate(graph, o);
 
-                               DirectPredicates entry = DirectPredicates.entry(QueryProcessor.this, subject);
-                               if(entry != null) update(graph, entry);
+                               DirectPredicates entry = QueryCache.entryDirectPredicates(QueryProcessor.this, subject);
+                               if(entry != null) markForUpdate(graph, entry);
 
                                return true;
 
@@ -2875,8 +1601,8 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        @Override
                        public boolean execute(int orderedSet) {
 
-                               OrderedSet entry = OrderedSet.entry(QueryProcessor.this, orderedSet);
-                               if(entry != null) update(graph, entry);
+                               OrderedSet entry = QueryCache.entryOrderedSet(QueryProcessor.this, orderedSet);
+                               if(entry != null) markForUpdate(graph, entry);
 
                                return true;
 
@@ -2884,32 +1610,46 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                });
 
-               //              for (Integer subject : predicates) {
-               //                      DirectPredicates entry = DirectPredicates.entry(QueryProcessor.this, subject);
-               //                      if(entry != null) update(graph, entry);
-               //              }
+               updateRefutations(graph);
 
+               primitiveUpdates.forEach(new TObjectProcedure() {
 
-               if (Development.DEVELOPMENT) {
-                       if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
-                               System.err.println("== Query update ends ==");
+                       @Override
+                       public boolean execute(Object arg0) {
+
+                               ExternalReadEntry query = (ExternalReadEntry)cache.externalReadEntryMap.get(arg0);
+                               if (query != null) {
+                                       boolean listening = update(graph, query);
+                                       if (!listening && !query.hasParents()) {
+                                               cache.externalReadEntryMap.remove(arg0);
+                                               query.discard();
+                                       }
+                               }
+                               return true;
                        }
-               }
 
+               });
+               
                scheduledValueUpdates.clear();
                scheduledObjectUpdates.clear();
                scheduledInvalidates.clear();
+               
+               if (Development.DEVELOPMENT) {
+                       if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_UPDATE, Bindings.BOOLEAN)) {
+                               System.err.println("== Query update ends ==");
+                       }
+               }
 
        }
 
        public void updateValue(final int resource) {
                scheduledValueUpdates.add(resource);
-               dirty = true;
+               cache.dirty = true;
        }
 
        public void updateStatements(final int resource, final int predicate) {
                scheduledObjectUpdates.add((((long)resource) << 32) + predicate);
-               dirty = true;
+               cache.dirty = true;
        }
        
        private int lastInvalidate = 0;
@@ -2918,7 +1658,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                if(lastInvalidate == resource) return;
                scheduledValueUpdates.add(resource);
                lastInvalidate = resource;
-               dirty = true;
+               cache.dirty = true;
        }
 
        public void updatePrimitive(final ExternalRead primitive) {
@@ -2934,12 +1674,14 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        @Override
        public synchronized String toString() {
-               return "QueryProvider [size = " + size + ", hits = " + hits + " misses = " + misses + ", updates = " + updates + "]";
+               return "QueryProvider [size = " + cache.size + ", hits = " + cache.hits + " misses = " + cache.misses + ", updates = " + cache.updates + "]";
        }
 
        @Override
        protected void doDispose() {
 
+               requests.release(Integer.MAX_VALUE / 2);
+               
                for(int index = 0; index < THREADS; index++) { 
                        executors[index].dispose();
                }
@@ -2990,28 +1732,28 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        }
 
        public int getHits() {
-               return hits;
+               return cache.hits;
        }
 
        public int getMisses() {
-               return misses;
+               return cache.misses;
        }
 
        public int getSize() {
-               return size;
+               return cache.size;
        }
 
        public Set<Long> getReferencedClusters() {
                HashSet<Long> result = new HashSet<Long>();
-               for (CacheEntry entry : objectsMap.values()) {
+               for (CacheEntry entry : QueryCache.entriesObjects(this)) {
                        Objects query = (Objects) entry.getQuery();
                        result.add(querySupport.getClusterId(query.r1()));
                }
-               for (CacheEntry entry : directPredicatesMap.values()) {
+               for (CacheEntry entry : QueryCache.entriesDirectPredicates(this)) {
                        DirectPredicates query = (DirectPredicates) entry.getQuery();
                        result.add(querySupport.getClusterId(query.id));
                }
-               for (CacheEntry entry : valueMap.values()) {
+               for (CacheEntry entry : cache.valueQueryMap.values()) {
                        ValueQuery query = (ValueQuery) entry.getQuery();
                        result.add(querySupport.getClusterId(query.id));
                }
@@ -3022,41 +1764,8 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        }
 
        CacheCollectionResult allCaches(CacheCollectionResult result) {
-
-               int level = Integer.MAX_VALUE;
-               directPredicatesMap.values(level, result);
-               principalTypesMap.values(level, result);
-               for(CacheEntryBase e : uriToResourceMap.values())
-                       if(e.getLevel() <= level)
-                               result.add(e);
-               for(CacheEntryBase e : namespaceIndexMap22.values())
-                       if(e.getLevel() <= level)
-                               result.add(e);
-               projectsMap.values(level, result);
-               
-               relationInfoMap.values(level, result);
-               superTypesMap.values(level, result);
-               typeHierarchyMap.values(level, result);
-               superRelationsMap.values(level, result);
-               typesMap.values(level, result);
-
-               valueMap.values(level, result);
-               directObjectsMap.values(level, result);
-               objectsMap.values(level, result);
-               orderedSetMap.values(level, result);
-               predicatesMap.values(level, result);
-
-               statementsMap.values(level, result);
-               assertedPredicatesMap.values(level, result);
-               assertedStatementsMap.values(level, result);
-               externalReadMap.values(level, result);
-               asyncReadMap.values(level, result);
                
-               readMap.values(level, result);
-               asyncMultiReadMap.values(level, result);
-               multiReadMap.values(level, result);
-
-               return result;
+               return cache.allCaches(result);
 
        }
 
@@ -3069,7 +1778,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        public int clean() {
                collector.collect(0, Integer.MAX_VALUE);
-               return size;
+               return cache.size;
        }
 
        public void clean(final Collection<ExternalRead<?>> requests) {
@@ -3083,7 +1792,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        public CacheEntryBase iterate(int level) {
                                if(iterator.hasNext()) {
                                        ExternalRead<?> request = iterator.next();
-                                       ExternalReadEntry entry = externalReadMap.get(request);
+                                       ExternalReadEntry entry = cache.externalReadEntryMap.get(request);
                                        if (entry != null) return entry;
                                        else return iterate(level);
                                } else {
@@ -3103,7 +1812,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        public Collection<CacheEntry> getRootList() {
                                ArrayList<CacheEntry> result = new ArrayList<CacheEntry>(requests.size());
                                for (ExternalRead<?> request : requests) {
-                                       ExternalReadEntry entry = externalReadMap.get(request);
+                                       ExternalReadEntry entry = cache.externalReadEntryMap.get(request);
                                        if (entry != null)
                                                result.add(entry);
                                }
@@ -3111,7 +1820,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        }
                        @Override
                        public int getCurrentSize() {
-                               return size;
+                               return cache.size;
                        }
                        @Override
                        public int calculateCurrentSize() {
@@ -3127,48 +1836,8 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        }
 
        public void scanPending() {
-
-               ArrayList<CacheEntry> entries = new ArrayList<CacheEntry>();
-
-               entries.addAll(directPredicatesMap.values());
-               entries.addAll(principalTypesMap.values());
-               entries.addAll(uriToResourceMap.values());
-               entries.addAll(namespaceIndexMap22.values());
-               entries.addAll(projectsMap.values());
-               entries.addAll(relationInfoMap.values());
-               entries.addAll(superTypesMap.values());
-               entries.addAll(superRelationsMap.values());
-               entries.addAll(typesMap.values());
-               entries.addAll(valueMap.values());
-               entries.addAll(directObjectsMap.values());
-               entries.addAll(objectsMap.values());
-               entries.addAll(orderedSetMap.values());
-               entries.addAll(predicatesMap.values());
-               entries.addAll(orderedSetMap.values());
-               entries.addAll(statementsMap.values());
-               //                      entries.addAll(assertedObjectsMap.values());
-               entries.addAll(assertedPredicatesMap.values());
-               entries.addAll(assertedStatementsMap.values());
-               entries.addAll(externalReadMap.values());
-               entries.addAll(asyncReadMap.values());
-               entries.addAll(externalReadMap.values());
-               entries.addAll(readMap.values());
-               entries.addAll(asyncMultiReadMap.values());
-               entries.addAll(multiReadMap.values());
-               entries.addAll(readMap.values());
-               System.out.println(entries.size() + " entries.");
-               for(Object e : entries) {
-                       if(e instanceof CacheEntry) {
-                               CacheEntry en = (CacheEntry)e;
-                               if(en.isPending()) System.out.println("pending " + e);
-                               if(en.isExcepted()) System.out.println("excepted " + e);
-                               if(en.isDiscarded()) System.out.println("discarded " + e);
-                               if(en.isRefuted()) System.out.println("refuted " + e);
-                               if(en.isFresh()) System.out.println("fresh " + e);
-                       } else {
-                               //System.out.println("Unknown object " + e);
-                       }
-               }
+               
+               cache.scanPending();
 
        }
 
@@ -3186,12 +1855,12 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        Exception callerException = null;
 
-       public interface AsyncBarrier {
-               public void inc(); 
-               public void dec();
-               //        public void inc(String debug); 
-               //        public void dec(String debug);
-       }
+    public interface AsyncBarrier {
+        public void inc(); 
+        public void dec();
+        public void waitBarrier(Object request, ReadGraphImpl impl);
+        public boolean isBlocking();
+    }
 
 //     final public QueryProcessor processor;
 //     final public QuerySupport support;
@@ -3234,140 +1903,90 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             support = provider2.getCore();
 //             initBuiltinValues();
 //
-//     }
-
-//     final static public ReadGraphSupportImpl basedOn(ReadGraphSupportImpl impl) {
-//             return new ReadGraphSupportImpl(impl.processor);
-//     }
-
-       @Override
-       final public Session getSession() {
-               return session;
-       }
-       
-       final public ResourceSupport getResourceSupport() {
-               return resourceSupport;
-       }
-
-       @Override
-       final public void forEachPredicate(final ReadGraphImpl impl, final Resource subject, final AsyncMultiProcedure<Resource> procedure) {
-
-               assert(subject != null);
-               assert(procedure != null);
-
-               final ListenerBase listener = getListenerBase(procedure);
-
-               IntProcedure ip = new IntProcedure() {
-
-                       AtomicBoolean first = new AtomicBoolean(true);
-
-                       @Override
-                       public void execute(ReadGraphImpl graph, int i) {
-                               try {
-                                       if(first.get()) {
-                                               procedure.execute(graph, querySupport.getResource(i));
-                                       } else {
-                                               procedure.execute(impl.newRestart(graph), querySupport.getResource(i));
-                                       }
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
-
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       if(first.compareAndSet(true, false)) {
-                                               procedure.finished(graph);
-//                                             impl.state.barrier.dec(this);
-                                       } else {
-                                               procedure.finished(impl.newRestart(graph));
-                                       }
-
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       if(first.compareAndSet(true, false)) {
-                                               procedure.exception(graph, t);
-//                                             impl.state.barrier.dec(this);
-                                       } else {
-                                               procedure.exception(impl.newRestart(graph), t);
-                                       }
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
-
-               };
-
-               int sId = querySupport.getId(subject);
-
-//             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#Predicates#" + sId);
-//             else impl.state.barrier.inc(null, null);
+//     }
 
-               Predicates.queryEach(impl, sId, this, impl.parent, listener, ip);
+//     final static public ReadGraphSupportImpl basedOn(ReadGraphSupportImpl impl) {
+//             return new ReadGraphSupportImpl(impl.processor);
+//     }
 
+       @Override
+       final public Session getSession() {
+               return session;
+       }
+       
+       final public ResourceSupport getResourceSupport() {
+               return resourceSupport;
        }
 
        @Override
-       final public void forEachPredicate(final ReadGraphImpl impl, final Resource subject, final MultiProcedure<Resource> procedure) {
-
-               assert(subject != null);
-               assert(procedure != null);
+       final public void forEachPredicate(final ReadGraphImpl impl, final Resource subject, final AsyncMultiProcedure<Resource> procedure) {
 
-               final ListenerBase listener = getListenerBase(procedure);
+        try {
 
-//             impl.state.barrier.inc();
+               for(Resource predicate : getPredicates(impl, subject))
+                   procedure.execute(impl, predicate);
 
-               Predicates.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, new IntProcedure() {
+               procedure.finished(impl);
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int i) {
-                               try {
-                                       procedure.execute(querySupport.getResource(i));
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
+           } catch (Throwable e) {
+               procedure.exception(impl, e);
+           }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       procedure.finished();
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-//                             impl.state.barrier.dec();
-                       }
+       }
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-//                             impl.state.barrier.dec();
-                       }
+       @Override
+       final public void forEachPredicate(final ReadGraphImpl impl, final Resource subject, final MultiProcedure<Resource> procedure) {
+               
+               throw new UnsupportedOperationException();
 
-               });
+//             assert(subject != null);
+//             assert(procedure != null);
+//
+//             final ListenerBase listener = getListenerBase(procedure);
+//
+//             try {
+//                     QueryCache.runnerPredicates(impl, querySupport.getId(subject), impl.parent, listener, new IntProcedure() {
+//
+//                             @Override
+//                             public void execute(ReadGraphImpl graph, int i) {
+//                                     try {
+//                                             procedure.execute(querySupport.getResource(i));
+//                                     } catch (Throwable t2) {
+//                                             Logger.defaultLogError(t2);
+//                                     }
+//                             }
+//
+//                             @Override
+//                             public void finished(ReadGraphImpl graph) {
+//                                     try {
+//                                             procedure.finished();
+//                                     } catch (Throwable t2) {
+//                                             Logger.defaultLogError(t2);
+//                                     }
+////                           impl.state.barrier.dec();
+//                             }
+//
+//                             @Override
+//                             public void exception(ReadGraphImpl graph, Throwable t) {
+//                                     try {
+//                                             procedure.exception(t);
+//                                     } catch (Throwable t2) {
+//                                             Logger.defaultLogError(t2);
+//                                     }
+////                           impl.state.barrier.dec();
+//                             }
+//
+//                     });
+//             } catch (DatabaseException e) {
+//                     Logger.defaultLogError(e);
+//             }
 
        }
        
        @Override
        final public IntSet getPredicates(final ReadGraphImpl impl, final Resource subject) throws Throwable {
-
-               assert(subject != null);
-               
-               return Predicates.queryEach2(impl, querySupport.getId(subject), this, impl.parent);
-
+               return QueryCacheBase.resultPredicates(impl, querySupport.getId(subject), impl.parent, null); 
        }
-       
 
        @Override
        final public void forEachStatement(final ReadGraphImpl impl, final Resource subject,
@@ -3381,38 +2000,42 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
 //             impl.state.barrier.inc();
 
-               Statements.queryEach(impl, querySupport.getId(subject), querySupport.getId(predicate), this, impl.parent, listener, new TripleIntProcedureAdapter() {
+               try {
+                       Statements.queryEach(impl, querySupport.getId(subject), querySupport.getId(predicate), this, impl.parent, listener, new TripleIntProcedureAdapter() {
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int s, int p, int o) {
-                               try {
-                                       procedure.execute(querySupport.getStatement(s, p, o));
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
+                               @Override
+                               public void execute(ReadGraphImpl graph, int s, int p, int o) {
+                                       try {
+                                               procedure.execute(querySupport.getStatement(s, p, o));
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
                                }
-                       }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       procedure.finished();
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void finished(ReadGraphImpl graph) {
+                                       try {
+                                               procedure.finished();
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
+
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               procedure.exception(t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
+                               }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -3485,7 +2108,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(proc, "#Statements" + sId + "#" + pId);
 //             else impl.state.barrier.inc(null, null);
 
-               Statements.queryEach(impl, sId, pId, this, impl.parent, listener, proc);
+               try {
+                       Statements.queryEach(impl, sId, pId, this, impl.parent, listener, proc);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -3558,7 +2185,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(proc, "#Statements" + sId + "#" + pId);
 //             else impl.state.barrier.inc(null, null);
 
-               Statements.queryEach(impl, sId, pId, this, impl.parent, listener, proc);
+               try {
+                       Statements.queryEach(impl, sId, pId, this, impl.parent, listener, proc);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
        
@@ -3630,38 +2261,42 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
 //             impl.state.barrier.inc();
 
-               AssertedStatements.queryEach(impl, querySupport.getId(subject), querySupport.getId(predicate), this, impl.parent, listener, new TripleIntProcedureAdapter() {
+               try {
+                       QueryCache.runnerAssertedStatements(impl, querySupport.getId(subject), querySupport.getId(predicate), impl.parent, listener, new TripleIntProcedureAdapter() {
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int s, int p, int o) {
-                               try {
-                                       procedure.execute(graph, querySupport.getStatement(s, p, o));
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
+                               @Override
+                               public void execute(ReadGraphImpl graph, int s, int p, int o) {
+                                       try {
+                                               procedure.execute(graph, querySupport.getStatement(s, p, o));
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
                                }
-                       }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       procedure.finished(graph);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void finished(ReadGraphImpl graph) {
+                                       try {
+                                               procedure.finished(graph);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(graph, t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
+
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               procedure.exception(graph, t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
+                               }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -3681,111 +2316,101 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
 //             impl.state.barrier.inc();
 
-               Objects.runner(impl, querySupport.getId(subject), querySupport.getId(predicate), impl.parent, listener, new IntProcedure() {
+               try {
+                       QueryCache.runnerObjects(impl, querySupport.getId(subject), querySupport.getId(predicate), impl.parent, listener, new IntProcedure() {
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int i) {
-                               try {
-                                       procedure.execute(querySupport.getResource(i));
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
+                               @Override
+                               public void execute(ReadGraphImpl graph, int i) {
+                                       try {
+                                               procedure.execute(querySupport.getResource(i));
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
                                }
-                       }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       procedure.finished();
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void finished(ReadGraphImpl graph) {
+                                       try {
+                                               procedure.finished();
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               System.out.println("forEachObject exception " + t);
-                               try {
-                                       procedure.exception(t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
+
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       System.out.println("forEachObject exception " + t);
+                                       try {
+                                               procedure.exception(t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
+                               }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
-
-//     @Override
-//     final public void forEachDirectObject(final ReadGraphImpl impl, final Resource subject, final Resource predicate, final AsyncMultiProcedure<Resource> procedure) {
-//
-//             assert(subject != null);
-//             assert(predicate != null);
-//             assert(procedure != null);
-//
-//             final ListenerBase listener = getListenerBase(procedure);
-//
-//             int sId = querySupport.getId(subject);
-//             int pId = querySupport.getId(predicate);
-//
-//             MultiIntProcedure proc = new MultiIntProcedure(procedure, impl, support);
-//
-//             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(proc, "#DirectObjects" + sId + "#" + pId);
-//             else impl.state.barrier.inc(null, null);
-//
-//             //        final Exception caller = new Exception();
-//
-//             //        final Pair<Exception, Exception> exceptions = Pair.make(callerException, new Exception());
-//
-//             DirectObjects.queryEach(impl, sId, pId, processor, impl.parent, listener, proc);
-//
-//     }
-
        @Override
-       final public void forEachDirectPredicate(final ReadGraphImpl impl, final Resource subject, final AsyncMultiProcedure<Resource> procedure) {
+       final public void forEachDirectPredicate(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<Set<Resource>> procedure) {
 
                assert(subject != null);
                assert(procedure != null);
 
                final ListenerBase listener = getListenerBase(procedure);
 
-               MultiIntProcedure proc = new MultiIntProcedure(procedure, impl, querySupport);
-
                int sId = querySupport.getId(subject);
 
-//             if(AsyncBarrierImpl.BOOKKEEPING)  impl.state.barrier.inc(proc, "#DirectPredicates" + sId);
-//             else impl.state.barrier.inc(null, null);
-
-               DirectPredicates.queryEach(impl, sId, this, impl.parent, listener, proc);
-
-       }
-
-       @Override
-       final public void forEachDirectStatement(final ReadGraphImpl impl, final Resource subject, final Procedure<DirectStatements> procedure) {
-
-               assert(subject != null);
-               assert(procedure != null);
+               try {
+                       QueryCache.runnerDirectPredicates(impl, sId, impl.parent, listener, new InternalProcedure<IntSet>() {
 
-               final ListenerBase listener = getListenerBase(procedure);
+                               @Override
+                               public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
+                                       procedure.execute(graph, result);
+                               }
 
-               org.simantics.db.impl.query.DirectStatements.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, procedure);
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
+                                       procedure.exception(graph, throwable);
+                               }
+                               
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
-       @Override
-       final public void forEachDirectStatement(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<DirectStatements> procedure, boolean ignoreVirtual) {
-
-               assert(subject != null);
-               assert(procedure != null);
-
-               final ListenerBase listener = getListenerBase(procedure);
+       final public DirectStatements getDirectStatements(final ReadGraphImpl impl, final Resource subject, final boolean ignoreVirtual) {
 
-               org.simantics.db.impl.query.DirectStatements.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, procedure, ignoreVirtual);
+//             assert(subject != null);
+//             assert(procedure != null);
+//
+//             final ListenerBase listener = getListenerBase(procedure);
+//
+//             org.simantics.db.impl.query.DirectStatements.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, procedure);
+               
+               return querySupport.getStatements(impl, querySupport.getId(subject), this, ignoreVirtual);
 
        }
 
+//     @Override
+//     final public void forEachDirectStatement(final ReadGraphImpl impl, final Resource subject, final SyncProcedure<DirectStatements> procedure, boolean ignoreVirtual) {
+//
+//             assert(subject != null);
+//             assert(procedure != null);
+//
+//             final ListenerBase listener = getListenerBase(procedure);
+//
+//             org.simantics.db.impl.query.DirectStatements.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, procedure, ignoreVirtual);
+//
+//     }
+       
        private static final Resource INVALID_RESOURCE = new ResourceImpl(null, Integer.MIN_VALUE);
 
        @Override
@@ -3824,16 +2449,59 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                final int sId = querySupport.getId(subject);
                final int pId = querySupport.getId(predicate);
 
-               Objects.runner(impl, sId, pId, impl.parent, listener, procedure);
+               try {
+                       QueryCache.runnerObjects(impl, sId, pId, impl.parent, listener, procedure);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
                
        }
        
-       final public int getSingleObject(final ReadGraphImpl impl, final Resource subject, final Resource predicate) throws DatabaseException {
+       static class Runner2Procedure implements IntProcedure {
+           
+           public int single = 0;
+           public Throwable t = null;
+
+           public void clear() {
+               single = 0;
+               t = null;
+           }
+           
+        @Override
+        public void execute(ReadGraphImpl graph, int i) {
+            if(single == 0) single = i;
+            else single = -1;
+        }
+
+        @Override
+        public void finished(ReadGraphImpl graph) {
+            if(single == -1) single = 0;
+        }
 
-        final int sId = querySupport.getId(subject);
-        final int pId = querySupport.getId(predicate);
+        @Override
+        public void exception(ReadGraphImpl graph, Throwable throwable) {
+            single = 0;
+            this.t = throwable;
+        }
+        
+        public int get() throws DatabaseException {
+            if(t != null) {
+                if(t instanceof DatabaseException) throw (DatabaseException)t;
+                else throw new DatabaseException(t);
+            }
+            return single;
+        }
+           
+       }
+       
+       final public int getSingleObject(final ReadGraphImpl impl, final Resource subject, final Resource predicate) throws DatabaseException {
+               
+               final int sId = querySupport.getId(subject);
+               final int pId = querySupport.getId(predicate);
 
-        return Objects.runner2(impl, sId, pId, impl.parent);
+               Runner2Procedure proc = new Runner2Procedure();
+               QueryCache.runnerObjects(impl, sId, pId, impl.parent, null, proc);
+               return proc.get();
            
        }
 
@@ -4245,40 +2913,42 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                final ListenerBase listener = getListenerBase(procedure);
 
-//             impl.state.barrier.inc();
-
-               AssertedStatements.queryEach(impl, querySupport.getId(subject), querySupport.getId(predicate), this, impl.parent, listener, new TripleIntProcedure() {
+               try {
+                       QueryCache.runnerAssertedStatements(impl, querySupport.getId(subject), querySupport.getId(predicate), impl.parent, listener, new TripleIntProcedure() {
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int s, int p, int o) {
-                               try {
-                                       procedure.execute(graph, querySupport.getResource(o));
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
+                               @Override
+                               public void execute(ReadGraphImpl graph, int s, int p, int o) {
+                                       try {
+                                               procedure.execute(graph, querySupport.getResource(o));
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
                                }
-                       }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {               
-                                       procedure.finished(graph);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void finished(ReadGraphImpl graph) {
+                                       try {               
+                                               procedure.finished(graph);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(graph, t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
+
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               procedure.exception(graph, t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
+                               }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -4328,7 +2998,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#PrincipalTypes#" + sId);
 //             else impl.state.barrier.inc(null, null);
 
-               PrincipalTypes.queryEach(impl, sId, this, impl.parent, listener, ip);
+               try {
+                       QueryCache.runnerPrincipalTypes(impl, sId, impl.parent, listener, ip);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -4342,39 +3016,42 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
 //             impl.state.barrier.inc();
 
-               PrincipalTypes.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, new IntProcedure() {
+               try {
+                       QueryCache.runnerPrincipalTypes(impl, querySupport.getId(subject), impl.parent, listener, new IntProcedure() {
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int i) {
-                               try {
-                                       procedure.execute(querySupport.getResource(i));
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
+                               @Override
+                               public void execute(ReadGraphImpl graph, int i) {
+                                       try {
+                                               procedure.execute(querySupport.getResource(i));
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
                                }
-                       }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       procedure.finished();
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void finished(ReadGraphImpl graph) {
+                                       try {
+                                               procedure.finished();
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
-//                             impl.state.barrier.dec();
-                       }
 
-               });
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               procedure.exception(t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
+//                             impl.state.barrier.dec();
+                               }
 
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
        }
 
     final public void forTypes(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<Set<Resource>> procedure) {
@@ -4383,47 +3060,29 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
         assert(procedure != null);
 
         final ListenerBase listener = getListenerBase(procedure);
+        assert(listener == null);
 
         InternalProcedure<IntSet> ip = new InternalProcedure<IntSet>() {
 
-            AtomicBoolean first = new AtomicBoolean(true);
-
             @Override
             public void execute(final ReadGraphImpl graph, IntSet set) {
-                try {
-                    if(first.compareAndSet(true, false)) {
-                        procedure.execute(graph, set);
-//                      impl.state.barrier.dec(this);
-                    } else {
-                        procedure.execute(impl.newRestart(graph), set);
-                    }
-                } catch (Throwable t2) {
-                    Logger.defaultLogError(t2);
-                }
+               procedure.execute(graph, set);
             }
 
             @Override
             public void exception(ReadGraphImpl graph, Throwable t) {
-                try {
-                    if(first.compareAndSet(true, false)) {
-                        procedure.exception(graph, t);
-//                      impl.state.barrier.dec(this);
-                    } else {
-                        procedure.exception(impl.newRestart(graph), t);
-                    }
-                } catch (Throwable t2) {
-                    Logger.defaultLogError(t2);
-                }
+               procedure.exception(graph, t);
             }
 
         };
 
         int sId = querySupport.getId(subject);
 
-//      if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#Types" + sId);
-//      else impl.state.barrier.inc(null, null);
-
-        Types.queryEach(impl, sId, this, impl.parent, listener, ip);
+        try {
+                       QueryCache.runnerTypes(impl, sId, impl.parent, listener, ip);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
     }
     
@@ -4432,53 +3091,16 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                assert(subject != null);
                
-               return Types.queryEach2(impl, querySupport.getId(subject), this, impl.parent);
+               return QueryCacheBase.resultTypes(impl, querySupport.getId(subject), impl.parent, null);
 
        }
 
        @Override
-       final public void forRelationInfo(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<RelationInfo> procedure) {
-
+       final public RelationInfo getRelationInfo(final ReadGraphImpl impl, final Resource subject) throws DatabaseException {
+               
                assert(subject != null);
-               assert(procedure != null);
-
-               final ListenerBase listener = getListenerBase(procedure);
-
-//             impl.state.barrier.inc();
-
-               RelationInfoQuery.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, new InternalProcedure<RelationInfo>() {
-
-                       AtomicBoolean first = new AtomicBoolean(true);
-
-                       @Override
-                       public void execute(final ReadGraphImpl graph, RelationInfo set) {
-                               try {
-                                       if(first.compareAndSet(true, false)) {
-                                               procedure.execute(graph, set);
-//                                             impl.state.barrier.dec();
-                                       } else {
-                                               procedure.execute(impl.newRestart(graph), set);
-                                       }
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       if(first.compareAndSet(true, false)) {
-                                               procedure.exception(graph, t);
-//                                             impl.state.barrier.dec("ReadGraphSupportImpl.1353");
-                                       } else {
-                                               procedure.exception(impl.newRestart(graph), t);
-                                       }
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
 
-               });
+               return QueryCache.resultRelationInfoQuery(impl, querySupport.getId(subject), impl.parent, null);
 
        }
 
@@ -4490,14 +3112,13 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                final ListenerBase listener = getListenerBase(procedure);
 
-//             impl.state.barrier.inc();
-
-               SuperTypes.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, new InternalProcedure<IntSet>() {
+               try {
+                       QueryCache.runnerSuperTypes(impl, querySupport.getId(subject), impl.parent, listener, new InternalProcedure<IntSet>() {
 
-                       AtomicBoolean first = new AtomicBoolean(true);
+                               AtomicBoolean first = new AtomicBoolean(true);
 
-                       @Override
-                       public void execute(final ReadGraphImpl graph, IntSet set) {
+                               @Override
+                               public void execute(final ReadGraphImpl graph, IntSet set) {
 //                             final HashSet<Resource> result = new HashSet<Resource>();
 //                             set.forEach(new TIntProcedure() {
 //
@@ -4508,33 +3129,36 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //                                     }
 //
 //                             });
-                               try {
-                                       if(first.compareAndSet(true, false)) {
-                                               procedure.execute(graph, set);
+                                       try {
+                                               if(first.compareAndSet(true, false)) {
+                                                       procedure.execute(graph, set);
 //                                             impl.state.barrier.dec();
-                                       } else {
-                                               procedure.execute(impl.newRestart(graph), set);
+                                               } else {
+                                                       procedure.execute(impl.newRestart(graph), set);
+                                               }
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
                                        }
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
-                       }
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       if(first.compareAndSet(true, false)) {
-                                               procedure.exception(graph, t);
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               if(first.compareAndSet(true, false)) {
+                                                       procedure.exception(graph, t);
 //                                             impl.state.barrier.dec();
-                                       } else {
-                                               procedure.exception(impl.newRestart(graph), t);
+                                               } else {
+                                                       procedure.exception(impl.newRestart(graph), t);
+                                               }
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
                                        }
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
-                       }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -4585,7 +3209,13 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#DirectSuperRelations#" + sId);
 //             else impl.state.barrier.inc(null, null);
 
-               DirectSuperRelations.queryEach(impl, sId, this, impl.parent, listener, ip);
+               try {
+                       QueryCache.runnerDirectSuperRelations(impl, sId, impl.parent, listener, ip);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
+               
+//             DirectSuperRelations.queryEach(impl, sId, this, impl.parent, listener, ip);
 
        }
 
@@ -4650,31 +3280,31 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#SuperRelations#" + sId);
 //             else impl.state.barrier.inc(null, null);
 
-               SuperRelations.queryEach(impl, sId, this, impl.parent, listener, ip);
+               try {
+                       QueryCache.runnerSuperRelations(impl, sId, impl.parent, listener, ip);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
        final public byte[] getValue(final ReadGraphImpl impl, final Resource subject) throws DatabaseException {
-
-         int sId = querySupport.getId(subject);
-      return ValueQuery.queryEach(impl, sId, impl.parent);
-
+         return getValue(impl, querySupport.getId(subject));
        }
 
        final public byte[] getValue(final ReadGraphImpl impl, final int subject) throws DatabaseException {
-
-           return ValueQuery.queryEach(impl, subject, impl.parent);
-
+               return QueryCache.resultValueQuery(impl, subject, impl.parent, null); 
        }
 
        @Override
-       final public byte[] forValue(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<byte[]> procedure) {
+       final public void forValue(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<byte[]> procedure) {
 
                assert(subject != null);
+               assert(procedure != null);
 
                int sId = querySupport.getId(subject);
 
-               if(procedure != null) {
+//             if(procedure != null) {
                
                        final ListenerBase listener = getListenerBase(procedure);
 
@@ -4715,13 +3345,19 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //                     if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#Value" + sId);
 //                     else impl.state.barrier.inc(null, null);
 
-                       return ValueQuery.queryEach(impl, sId, impl.parent, listener, ip);
-
-               } else {
+                       try {
+                               QueryCache.runnerValueQuery(impl, sId, impl.parent, listener, ip);
+                       } catch (DatabaseException e) {
+                               throw new IllegalStateException("Internal error");
+                       }
 
-                       return ValueQuery.queryEach(impl, sId, impl.parent, null, null);
-                       
-               }
+//             } else {
+//
+//                     return QueryCacheBase.runnerValueQuery(impl, sId, impl.parent, null, null);
+//                     
+//             }
+//             
+//             throw new IllegalStateException("Internal error");
 
        }
 
@@ -4774,7 +3410,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //                     if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#Value" + sId);
 //                     else impl.state.barrier.inc(null, null);
 
-                       ValueQuery.queryEach(impl, sId, impl.parent, listener, ip);
+                       try {
+                               QueryCache.runnerValueQuery(impl, sId, impl.parent, listener, ip);
+                       } catch (DatabaseException e) {
+                               Logger.defaultLogError(e);
+                       }
 
                } else {
 
@@ -4798,7 +3438,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                        int sId = querySupport.getId(subject);
 
-                       ValueQuery.queryEach(impl, sId, impl.parent, listener, ip);
+                       try {
+                               QueryCache.runnerValueQuery(impl, sId, impl.parent, listener, ip);
+                       } catch (DatabaseException e) {
+                               Logger.defaultLogError(e);
+                       }
 
                }
 
@@ -4878,7 +3522,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "#DirectObjects#" + sId);
 //             else impl.state.barrier.inc(null, null);
 
-               Objects.runner(impl, sId, getInverseOf(), impl.parent, listener, ip);
+               try {
+                       QueryCache.runnerObjects(impl, sId, getInverseOf(), impl.parent, listener, ip);
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -4916,85 +3564,63 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(ip, "Resource");
 //             else impl.state.barrier.inc(null, null);
 
-               forResource(impl, id, impl.parent, ip);
-
-       }
-
-       @Override
-       final public void forBuiltin(final ReadGraphImpl impl, final String id, final AsyncProcedure<Resource> procedure) {
-
-               assert(id != null);
-               assert(procedure != null);
-
-//             impl.state.barrier.inc();
-
-               forBuiltin(impl, id, impl.parent, new InternalProcedure<Integer>() {
-
-                       @Override
-                       public void execute(ReadGraphImpl graph, Integer result) {
-                               try {
-                                       procedure.execute(graph, querySupport.getResource(result)); 
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-//                             impl.state.barrier.dec();
-                       }   
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(graph, t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-//                             impl.state.barrier.dec();
-                       }
-
-               });
+               forResource(impl, id, impl.parent, ip);
 
        }
 
        @Override
-       final public void forHasStatement(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<Boolean> procedure) {
+       final public void forBuiltin(final ReadGraphImpl impl, final String id, final AsyncProcedure<Resource> procedure) {
 
-               assert(subject != null);
+               assert(id != null);
                assert(procedure != null);
 
-               final ListenerBase listener = getListenerBase(procedure);
-
 //             impl.state.barrier.inc();
 
-               DirectPredicates.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, new IntProcedure() {
-
-                       boolean found = false;
-
-                       @Override
-                       public void execute(ReadGraphImpl graph, int object) {
-                               found = true;
-                       }
+               try {
+                       forBuiltin(impl, id, impl.parent, new InternalProcedure<Integer>() {
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       procedure.execute(graph, found);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void execute(ReadGraphImpl graph, Integer result) {
+                                       try {
+                                               procedure.execute(graph, querySupport.getResource(result)); 
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
+                               }   
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(graph, t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               procedure.exception(graph, t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
+                               }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
+
+       }
+
+       @Override
+       final public void forHasStatement(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<Boolean> procedure) {
+
+               assert(subject != null);
+               assert(procedure != null);
+
+               final ListenerBase listener = getListenerBase(procedure);
 
+               try {
+                       IntSet result = QueryCache.resultDirectPredicates(impl, querySupport.getId(subject), impl.parent, listener);
+                       procedure.execute(impl, !result.isEmpty());
+               } catch (DatabaseException e) {
+                       procedure.exception(impl, e);
+               }
+                       
        }
 
        @Override
@@ -5094,30 +3720,34 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
 //             impl.state.barrier.inc();
 
-               ValueQuery.queryEach(impl, querySupport.getId(subject), impl.parent, listener, new InternalProcedure<byte[]>() {
+               try {
+                       QueryCache.runnerValueQuery(impl, querySupport.getId(subject), impl.parent, listener, new InternalProcedure<byte[]>() {
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, byte[] object) {
-                               boolean result = object != null;
-                               try {
-                                       procedure.execute(graph, result);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void execute(ReadGraphImpl graph, byte[] object) {
+                                       boolean result = object != null;
+                                       try {
+                                               procedure.execute(graph, result);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
-
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(graph, t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
+
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               procedure.exception(graph, t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
+                               }
 
-               });
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+               }
 
        }
 
@@ -5129,149 +3759,155 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                final ListenerBase listener = getListenerBase(procedure);
 
-//             impl.state.barrier.inc();
-
-               OrderedSet.queryEach(impl, querySupport.getId(subject), this, impl.parent, listener, new IntProcedure() {
+               try {
+                       
+                       QueryCache.runnerOrderedSet(impl, querySupport.getId(subject), impl.parent, listener, new IntProcedure() {
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               try {
-                                       procedure.exception(graph, t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
+                               @Override
+                               public void exception(ReadGraphImpl graph, Throwable t) {
+                                       try {
+                                               procedure.exception(graph, t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
 //                             impl.state.barrier.dec();
-                       }
-
-                       @Override
-                       public void execute(ReadGraphImpl graph, int i) {
-                               try {
-                                       procedure.execute(graph, querySupport.getResource(i));
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
                                }
-                       }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                               try {
-                                       procedure.finished(graph);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
+                               @Override
+                               public void execute(ReadGraphImpl graph, int i) {
+                                       try {
+                                               procedure.execute(graph, querySupport.getResource(i));
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
                                }
-//                             impl.state.barrier.dec();
-                       }
-
-               });
-
-       }
-
-       @Override
-       final public <T> void query(final ReadGraphImpl impl, final AsyncRead<T> request, final CacheEntry parent, final AsyncProcedure<T> procedure, ListenerBase listener) {
-
-               assert(request != null);
-               assert(procedure != null);
 
-//             if(AsyncBarrierImpl.BOOKKEEPING) impl.state.barrier.inc(request, "#" + request.toString() + ".1999");
-//             else impl.state.barrier.inc(null, null);
-
-               runAsyncRead(impl, request, parent, listener, procedure);
-
-       }
-
-       @Override
-       final public <T> T tryQuery(final ReadGraphImpl graph, final Read<T> request) throws DatabaseException {
-
-               assert(graph != null);
-               assert(request != null);
+                               @Override
+                               public void finished(ReadGraphImpl graph) {
+                                       try {
+                                               procedure.finished(graph);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
+//                             impl.state.barrier.dec();
+                               }
 
-               final ReadEntry entry = readMap.get(request);
-               if(entry != null && entry.isReady()) {
-                   return (T)entry.get(graph, this, null);
-               } else {
-                       return request.perform(graph);
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
                }
 
        }
 
-    final public <T> T tryQuery(final ReadGraphImpl graph, final ExternalRead<T> request) throws DatabaseException {
-
-        assert(graph != null);
-        assert(request != null);
-
-        final ExternalReadEntry<T> entry = externalReadMap.get(request);
-        if(entry != null && entry.isReady()) {
-            if(entry.isExcepted()) {
-                Throwable t = (Throwable)entry.getResult();
-                if(t instanceof DatabaseException) throw (DatabaseException)t;
-                else throw new DatabaseException(t);
-            } else {
-                return (T)entry.getResult();
-            }            
-        } else {
-
-            final DataContainer<T> result = new DataContainer<T>();
-            final DataContainer<Throwable> exception = new DataContainer<Throwable>();
-            
-            request.register(graph, new Listener<T>() {
-                
-                @Override
-                public void exception(Throwable t) {
-                    exception.set(t);
-                }
-
-                @Override
-                public void execute(T t) {
-                    result.set(t);
-                }
-
-                @Override
-                public boolean isDisposed() {
-                    return true;
-                }
-            
-            });
-            
-            Throwable t = exception.get();
-            if(t != null) {
-                if(t instanceof DatabaseException) throw (DatabaseException)t;
-                else throw new DatabaseException(t);
-            }
-            
-            return result.get();
+//     @Override
+//     final public <T> void query(final ReadGraphImpl impl, final AsyncRead<T> request, final CacheEntry parent, final AsyncProcedure<T> procedure, ListenerBase listener) throws DatabaseException {
+//
+//             assert(request != null);
+//             assert(procedure != null);
+//
+//             QueryCache.runnerAsyncReadEntry(impl, request, parent, listener, procedure);
+//
+//     }
 
-        }
+//     @Override
+//     final public <T> T tryQuery(final ReadGraphImpl graph, final Read<T> request) throws DatabaseException {
+//
+//             assert(graph != null);
+//             assert(request != null);
+//
+//             final ReadEntry entry = (ReadEntry)cache.getCached(request);
+//             if(entry != null && entry.isReady()) {
+//                 return (T)entry.get(graph, this, null);
+//             } else {
+//                     return request.perform(graph);
+//             }
+//
+//     }
 
-    }
+//    final public <T> T tryQuery(final ReadGraphImpl graph, final ExternalRead<T> request) throws DatabaseException {
+//
+//        assert(graph != null);
+//        assert(request != null);
+//
+//        final ExternalReadEntry<T> entry = cache.externalReadMap.get(request);
+//        if(entry != null && entry.isReady()) {
+//            if(entry.isExcepted()) {
+//                Throwable t = (Throwable)entry.getResult();
+//                if(t instanceof DatabaseException) throw (DatabaseException)t;
+//                else throw new DatabaseException(t);
+//            } else {
+//                return (T)entry.getResult();
+//            }            
+//        } else {
+//
+//            final DataContainer<T> result = new DataContainer<T>();
+//            final DataContainer<Throwable> exception = new DataContainer<Throwable>();
+//            
+//            request.register(graph, new Listener<T>() {
+//                
+//                @Override
+//                public void exception(Throwable t) {
+//                    exception.set(t);
+//                }
+//
+//                @Override
+//                public void execute(T t) {
+//                    result.set(t);
+//                }
+//
+//                @Override
+//                public boolean isDisposed() {
+//                    return true;
+//                }
+//            
+//            });
+//            
+//            Throwable t = exception.get();
+//            if(t != null) {
+//                if(t instanceof DatabaseException) throw (DatabaseException)t;
+//                else throw new DatabaseException(t);
+//            }
+//            
+//            return result.get();
+//
+//        }
+//
+//    }
        
-       @Override
-       final public <T> void tryQuery(final ReadGraphImpl graph, final AsyncRead<T> request, AsyncProcedure<T> procedure) {
-
-               assert(graph != null);
-               assert(request != null);
-
-               final AsyncReadEntry entry = asyncReadMap.get(request);
-               if(entry != null && entry.isReady()) {
-                       if(entry.isExcepted()) {
-                               procedure.exception(graph, (Throwable)entry.getResult());
-                       } else {
-                               procedure.execute(graph, (T)entry.getResult());
-                       }
-               } else {
-                       request.perform(graph, procedure);
-               }
-
-       }
+//     @Override
+//     final public <T> void tryQuery(final ReadGraphImpl graph, final AsyncRead<T> request, AsyncProcedure<T> procedure) {
+//
+//             assert(graph != null);
+//             assert(request != null);
+//
+//             final AsyncReadEntry entry = cache.asyncReadMap.get(request);
+//             if(entry != null && entry.isReady()) {
+//                     if(entry.isExcepted()) {
+//                             procedure.exception(graph, (Throwable)entry.getResult());
+//                     } else {
+//                             procedure.execute(graph, (T)entry.getResult());
+//                     }
+//             } else {
+//                     request.perform(graph, procedure);
+//             }
+//
+//     }
 
        @Override
-       final public <T> void query(final ReadGraphImpl impl, final MultiRead<T> request, final CacheEntry parent, final AsyncMultiProcedure<T> procedure, ListenerBase listener) {
+       final public <T> void query(final ReadGraphImpl impl, final MultiRead<T> request, final CacheEntry parent, final SyncMultiProcedure<T> procedure, ListenerBase listener) {
 
                assert(request != null);
                assert(procedure != null);
 
-//             impl.state.barrier.inc(null, null);
+               try {
 
-               queryMultiRead(impl, request, parent, listener, procedure);
+                       queryMultiRead(impl, request, parent, listener, procedure);
+                       
+               } catch (DatabaseException e) {
+                       
+                       throw new IllegalStateException(e);
+                       
+               }
 
        }
 
@@ -5329,40 +3965,48 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        }
 
-       @Override
-       final public <T> void query(final ReadGraphImpl impl, final ExternalRead<T> request, final CacheEntry parent, final Procedure<T> procedure, ListenerBase listener) {
-
-               assert(request != null);
-               assert(procedure != null);
-
-               queryPrimitiveRead(impl, request, parent, listener, new Procedure<T>() {
-
-                       @Override
-                       public void execute(T result) {
-                               try {
-                                       procedure.execute(result);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
-
-                       @Override
-                       public String toString() {
-                               return procedure.toString();
-                       }
-
-                       @Override
-                       public void exception(Throwable t) {
-                               try {
-                                       procedure.exception(t);
-                               } catch (Throwable t2) {
-                                       Logger.defaultLogError(t2);
-                               }
-                       }
-
-               });
-
-       }
+//     @Override
+//     final public <T> void query(final ReadGraphImpl impl, final ExternalRead<T> request, final CacheEntry parent, final Procedure<T> procedure, ListenerBase listener) throws DatabaseException {
+//
+//             assert(request != null);
+//             assert(procedure != null);
+//
+//             try {
+//             
+//                     queryPrimitiveRead(impl, request, parent, listener, new AsyncProcedure<T>() {
+//     
+//                             @Override
+//                             public String toString() {
+//                                     return procedure.toString();
+//                             }
+//     
+//                             @Override
+//                             public void execute(AsyncReadGraph graph, T result) {
+//                                     try {
+//                                             procedure.execute(result);
+//                                     } catch (Throwable t2) {
+//                                             Logger.defaultLogError(t2);
+//                                     }
+//                             }
+//
+//                             @Override
+//                             public void exception(AsyncReadGraph graph, Throwable throwable) {
+//                                     try {
+//                                             procedure.exception(throwable);
+//                                     } catch (Throwable t2) {
+//                                             Logger.defaultLogError(t2);
+//                                     }
+//                             }
+//     
+//                     });
+//                     
+//             } catch (DatabaseException e) {
+//                     
+//                     throw new IllegalStateException(e);
+//                     
+//             }
+//
+//     }
 
        @Override
        public VirtualGraph getProvider(Resource subject, Resource predicate, Resource object) {
@@ -5408,5 +4052,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                }
                return L0;
        }
+
+    public static ThreadLocal<Integer> thread = new ThreadLocal<Integer>() {
+        protected Integer initialValue() {
+            return -1;
+        }
+    };
        
 }