]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java
First changes
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / QueryProcessor.java
index ff15d301b58214a25d20bb663889d11430008ae2..cca9d681edd8f88893a65d819afee6b290cf5d0a 100644 (file)
@@ -94,31 +94,7 @@ 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;
+       final public QueryCache cache = new QueryCache();
 
        public static int                                       indent                = 0;
 
@@ -365,31 +341,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();
@@ -625,201 +576,223 @@ 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); 
-
-               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 {
+                       cache.runQuery(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);
-//                                             }
+               
+//             int hash = requestHash(query);
 //
-//                                             query.perform(graph, procedure);
+//             AsyncReadEntry<T> entry = asyncReadMap.get(query, hash); 
 //
-//                                             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);
-                       }
-
-               }
+//             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;
+//                     }
+//             }
+//
+//             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);
+//                     }
+//
+//             }
 
        }
 
 
-       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()) {
+       final <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) {
 
-                               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);
-//                                             }
+               try {
+                       cache.runQuery(graph, query, parent, listener, procedure);
+               } catch (DatabaseException e) {
+                       throw new IllegalStateException(e);
+               }
 
-                                               // If this was synchronized we must wait here until completion
-                                               //                        if(graph.state.synchronizedExecution) {
-                                               //                            while(entry.isPending()) {
-                                               //                              graph.resumeTasks(graph.callerThread, null, null);
-                                               //                            }
-                                               //                        }
+//             MultiReadEntry entry = cached != null ? cached : provider.multiReadMap.get(query); 
+//             if(entry == null) {
 //
-//                                             return;
-
-                                       }
-                               }
-
-                               entry.performFromCache(graph, provider, procedure);
-//                             graph.state.barrier.dec(query);
-                               return;
-
-                       } else {
-
-                               provider.performForEach(graph, query, entry, parent, listener, procedure, false);
-
-                       }
-
-               }
+//                     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);
+//                                             //                            }
+//                                             //                        }
+////
+////                                           return;
+//
+//                                     }
+//                             }
+//
+//                             entry.performFromCache(graph, provider, procedure);
+////                           graph.state.barrier.dec(query);
+//                             return;
+//
+//                     } else {
+//
+//                             provider.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) {
 
-               int hash = requestHash(query);
-
-               AsyncMultiReadEntry entry = asyncMultiReadMap.get(query, hash);
-
-               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;
-                       }
+               
+               try {
+                       cache.runQuery(graph, query, parent, listener, procedure);
+               } catch (DatabaseException e) {
+                       throw new IllegalStateException(e);
                }
 
-               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);
-
-               }
+//             int hash = requestHash(query);
+//
+//             AsyncMultiReadEntry entry = asyncMultiReadMap.get(query, hash);
+//
+//             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;
+//                     }
+//             }
+//
+//             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);
+//
+//             }
 
        }
 
-       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 <T> void runPrimitiveRead(ReadGraphImpl graph, ExternalReadEntry cached, final ExternalRead<T> query, final CacheEntry parent, final QueryProcessor provider, final ListenerBase listener, final Procedure<T> procedure) throws DatabaseException {
 
-               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);
-               }
+               cache.runQuery(graph, query, parent, listener, 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);
+//             }
 
        }
 
@@ -835,543 +808,549 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
     @Override
        public <T> T queryRead(final ReadGraphImpl graph, final Read<T> query, final CacheEntry parent, final AsyncProcedure<T> procedure, final ListenerBase listener) throws Throwable {
 
-               assert(query != null);
-
-               ReadEntry entry = readMap.get(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();
-                       }
-               }
-
-               if(entry == null) {
-
-                       entry = new ReadEntry(query);
-                       entry.setPending();
-                       entry.clearResult(querySupport);
-
-                       readMap.put(query, entry);
-
-                       return (T)performForEach(graph, query, entry, parent, listener, procedure, false);
-
-               } else {
-
-                       if(entry.isPending()) {
-                throw new IllegalStateException();
-                       } else {
-                               return (T)performForEach(graph, query, entry, parent, listener, procedure, false);
-                       }
-
-               }
-
-       }
-
-       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);
-
-               if(parent == null && !(listener != null)) {
-                       if(entry != null && entry.isReady()) { 
-                               entry.performFromCache(graph, this, procedure);
-                               return;
-                       }
-               }
-
-               runMultiRead(graph, entry, query, parent, this, listener, procedure);
-
-       }
-
-       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);
-
-               final ExternalReadEntry entry = externalReadMap.get(query);
-
-               if(parent == null && !(listener != null)) {
-                       if(entry != null && entry.isReady()) { 
-                               entry.performFromCache(procedure);
-                               return;
-                       }
-               }
-
-               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();
+               return (T)cache.runQuery(graph, query, parent, listener, procedure);
 
-                       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);
-
-                       }
-
-               } 
+//     assert(query != null);
+//
+//             ReadEntry entry = readMap.get(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();
+//                     }
+//             }
+//
+//             if(entry == null) {
+//
+//                     entry = new ReadEntry(query);
+//                     entry.setPending();
+//                     entry.clearResult(querySupport);
+//
+//                     readMap.put(query, entry);
+//
+//                     return (T)performForEach(graph, query, entry, parent, listener, procedure, false);
+//
+//             } else {
+//
+//                     if(entry.isPending()) {
+//                throw new IllegalStateException();
+//                     } else {
+//                             return (T)performForEach(graph, query, entry, parent, listener, procedure, false);
+//                     }
+//
+//             }
 
        }
 
-       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>() {
+       public <T> void queryMultiRead(final ReadGraphImpl graph, final MultiRead<T> query, final CacheEntry parent, final ListenerBase listener, final AsyncMultiProcedure<T> procedure) throws DatabaseException {
 
-                                       @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();
-                                       }
+               cache.runQuery(graph, query, parent, listener, procedure);
 
-                                       @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);
+//             assert(query != null);
+//             assert(procedure != null);
+//
+//             final MultiReadEntry entry = multiReadMap.get(query);
+//
+//             if(parent == null && !(listener != null)) {
+//                     if(entry != null && entry.isReady()) { 
+//                             entry.performFromCache(graph, this, procedure);
+//                             return;
+//                     }
+//             }
+//
+//             runMultiRead(graph, entry, query, parent, this, listener, procedure);
 
        }
 
+       public <T> void queryPrimitiveRead(final ReadGraphImpl graph, final ExternalRead<T> query, final CacheEntry parent, final ListenerBase listener, final Procedure<T> procedure) throws DatabaseException {
 
-       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++;
+               cache.runQuery(graph, query, parent, listener, procedure);
 
-                       } else {
-
-                               entry.performFromCache(callerGraph, this, procedure);
-
-                               hits++;
-
-                       }
-
-                       assert (!entry.isDiscarded());
-
-                       registerDependencies(callerGraph, entry, parent, listener, procedure, inferredDependency);
-
-               } catch (Throwable t) {
-
-                       Logger.defaultLogError(t);
-
-               } finally {
-
-               }
+//             assert(query != null);
+//             assert(procedure != null);
+//
+//             final ExternalReadEntry entry = externalReadMap.get(query);
+//
+//             if(parent == null && !(listener != null)) {
+//                     if(entry != null && entry.isReady()) { 
+//                             entry.performFromCache(procedure);
+//                             return;
+//                     }
+//             }
+//
+//             runPrimitiveRead(graph, entry, query, parent, this, listener, procedure);
 
        }
 
-       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);
-                                               }
-                                               
-                                       }
+//     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());
+//
+//     }
 
-                                       @Override
-                                       public void exception(Throwable t) {
-                                               
-                                               entry.except(t);
+//     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);
+//
+//                     }
+//
+//             } 
+//
+//     }
 
-                                               if(used.compareAndSet(false, true)) {
-                                                       procedure.exception(t);
-                                               } else {
+//     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();
+//
+//                     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 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());
-
-       }
+//                                                     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) {
+       boolean isBound(ExternalReadEntry<?> entry) {
                if(entry.hasParents()) return true;
                else if(hasListener(entry)) return true;
                else return false;
@@ -1690,101 +1669,12 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                }
 
                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;
-
+                       return cache.getRootList();
                }
 
                @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;
-                       
+                       return cache.calculateCurrentSize();
                }
 
                @Override
@@ -1828,10 +1718,10 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                assert (entry != null);
                assert (procedure != null);
 
-               ArrayList<ListenerEntry> list = listeners.get(entry);
+               ArrayList<ListenerEntry> list = cache.listeners.get(entry);
                if (list == null) {
                        list = new ArrayList<ListenerEntry>(1);
-                       listeners.put(entry, list);
+                       cache.listeners.put(entry, list);
                }
 
                ListenerEntry result = new ListenerEntry(entry, base, procedure);
@@ -1862,22 +1752,22 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        private void removeListener(ListenerEntry entry) {
                assert (entry != null);
-               ArrayList<ListenerEntry> list = listeners.get(entry.entry);
+               ArrayList<ListenerEntry> list = cache.listeners.get(entry.entry);
                if(list == null) return;
                boolean success = list.remove(entry);
                assert (success);
                if (list.isEmpty())
-                       listeners.remove(entry.entry);
+                       cache.listeners.remove(entry.entry);
        }
 
        private boolean hasListener(CacheEntry entry) {
-               if(listeners.get(entry) != null) return true;
+               if(cache.listeners.get(entry) != null) return true;
                return false;
        }
 
        boolean hasListenerAfterDisposing(CacheEntry entry) {
-               if(listeners.get(entry) != null) {
-                       ArrayList<ListenerEntry> entries = listeners.get(entry);
+               if(cache.listeners.get(entry) != null) {
+                       ArrayList<ListenerEntry> entries = cache.listeners.get(entry);
                        ArrayList<ListenerEntry> list = null;
                        for (ListenerEntry e : entries) {
                                if (e.base.isDisposed()) {
@@ -1891,7 +1781,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                                }
                        }
                        if (entries.isEmpty()) {
-                               listeners.remove(entry);
+                               cache.listeners.remove(entry);
                                return false;
                        }
                        return true;
@@ -1901,8 +1791,8 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        List<ListenerEntry> getListenerEntries(CacheEntry entry) {
                hasListenerAfterDisposing(entry);
-               if(listeners.get(entry) != null)
-                       return listeners.get(entry);
+               if(cache.listeners.get(entry) != null)
+                       return cache.listeners.get(entry);
                else 
                        return Collections.emptyList();
        }
@@ -2420,7 +2310,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //             System.err.println(" => FOO " + type);
 
                if (hasListener) {
-                       ArrayList<ListenerEntry> entries = listeners.get(entry);
+                       ArrayList<ListenerEntry> entries = cache.listeners.get(entry);
                        if(entries != null) {
                                for (ListenerEntry le : entries) {
                                        scheduleListener(le);
@@ -2776,11 +2666,11 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        @Override
                        public boolean execute(Object arg0) {
 
-                               ExternalReadEntry query = (ExternalReadEntry)externalReadMap.get(arg0);
+                               ExternalReadEntry query = (ExternalReadEntry)cache.externalReadMap.get(arg0);
                                if (query != null) {
                                        boolean listening = update(graph, query);
                                        if (!listening && !query.hasParents()) {
-                                               externalReadMap.remove(arg0);
+                                               cache.externalReadMap.remove(arg0);
                                                query.discard();
                                        }
                                }
@@ -3003,15 +2893,15 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
        public Set<Long> getReferencedClusters() {
                HashSet<Long> result = new HashSet<Long>();
-               for (CacheEntry entry : objectsMap.values()) {
+               for (CacheEntry entry : cache.objectsMap.values()) {
                        Objects query = (Objects) entry.getQuery();
                        result.add(querySupport.getClusterId(query.r1()));
                }
-               for (CacheEntry entry : directPredicatesMap.values()) {
+               for (CacheEntry entry : cache.directPredicatesMap.values()) {
                        DirectPredicates query = (DirectPredicates) entry.getQuery();
                        result.add(querySupport.getClusterId(query.id));
                }
-               for (CacheEntry entry : valueMap.values()) {
+               for (CacheEntry entry : cache.valueMap.values()) {
                        ValueQuery query = (ValueQuery) entry.getQuery();
                        result.add(querySupport.getClusterId(query.id));
                }
@@ -3022,41 +2912,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);
 
        }
 
@@ -3083,7 +2940,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.externalReadMap.get(request);
                                        if (entry != null) return entry;
                                        else return iterate(level);
                                } else {
@@ -3103,7 +2960,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.externalReadMap.get(request);
                                        if (entry != null)
                                                result.add(entry);
                                }
@@ -3127,48 +2984,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();
 
        }
 
@@ -5185,7 +5002,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                assert(graph != null);
                assert(request != null);
 
-               final ReadEntry entry = readMap.get(request);
+               final ReadEntry entry = cache.readMap.get(request);
                if(entry != null && entry.isReady()) {
                    return (T)entry.get(graph, this, null);
                } else {
@@ -5199,7 +5016,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
         assert(graph != null);
         assert(request != null);
 
-        final ExternalReadEntry<T> entry = externalReadMap.get(request);
+        final ExternalReadEntry<T> entry = cache.externalReadMap.get(request);
         if(entry != null && entry.isReady()) {
             if(entry.isExcepted()) {
                 Throwable t = (Throwable)entry.getResult();
@@ -5250,7 +5067,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                assert(graph != null);
                assert(request != null);
 
-               final AsyncReadEntry entry = asyncReadMap.get(request);
+               final AsyncReadEntry entry = cache.asyncReadMap.get(request);
                if(entry != null && entry.isReady()) {
                        if(entry.isExcepted()) {
                                procedure.exception(graph, (Throwable)entry.getResult());
@@ -5269,9 +5086,15 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                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);
+                       
+               }
 
        }
 
@@ -5335,32 +5158,40 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                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);
+               try {
+               
+                       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
+                               public String toString() {
+                                       return procedure.toString();
                                }
-                       }
-
-               });
+       
+                               @Override
+                               public void exception(Throwable t) {
+                                       try {
+                                               procedure.exception(t);
+                                       } catch (Throwable t2) {
+                                               Logger.defaultLogError(t2);
+                                       }
+                               }
+       
+                       });
+                       
+               } catch (DatabaseException e) {
+                       
+                       throw new IllegalStateException(e);
+                       
+               }
 
        }