]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java
24a2dbe960be9ec03877a241ca0580f79ef4b3ab
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / QueryCacheBase.java
1 package org.simantics.db.impl.query;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.concurrent.Semaphore;
6 import java.util.concurrent.atomic.AtomicBoolean;
7
8 import org.simantics.db.AsyncReadGraph;
9 import org.simantics.db.ObjectResourceIdMap;
10 import org.simantics.db.RelationInfo;
11 import org.simantics.db.common.utils.Logger;
12 import org.simantics.db.exception.DatabaseException;
13 import org.simantics.db.impl.DebugPolicy;
14 import org.simantics.db.impl.graph.ReadGraphImpl;
15 import org.simantics.db.impl.procedure.InternalProcedure;
16 import org.simantics.db.procedure.AsyncMultiProcedure;
17 import org.simantics.db.procedure.AsyncProcedure;
18 import org.simantics.db.procedure.Listener;
19 import org.simantics.db.procedure.ListenerBase;
20 import org.simantics.db.procedure.Procedure;
21 import org.simantics.db.request.AsyncMultiRead;
22 import org.simantics.db.request.AsyncRead;
23 import org.simantics.db.request.ExternalRead;
24 import org.simantics.db.request.MultiRead;
25 import org.simantics.db.request.Read;
26
27 import gnu.trove.map.hash.THashMap;
28 import gnu.trove.map.hash.TObjectIntHashMap;
29
30 public class QueryCacheBase {
31
32         // Statistics
33         final int THREADS;
34         final public int  THREAD_MASK;
35         int                                             hits                  = 0;
36         int                                             misses                = 0;
37         int                                             updates               = 0;
38         public int                                              size                  = 0;
39         
40         volatile public boolean dirty = false;
41         public boolean                                         collecting            = false;
42
43         final protected THashMap<String, URIToResource>                      uRIToResourceMap;
44         //final protected THashMap<String, NamespaceIndex>                     namespaceIndexMap;
45         final protected UnaryQueryHashMap<InternalProcedure<ObjectResourceIdMap<String>>> childMapMap;
46         final protected DoubleKeyQueryHashMap<IntProcedure>                     objectsMap;
47         final protected DoubleKeyQueryHashMap<TripleIntProcedure>               assertedStatementsMap;
48         final protected DoubleKeyQueryHashMap<IntProcedure>                     directObjectsMap;
49         final protected DoubleKeyQueryHashMap<TripleIntProcedure>               statementsMap;
50         final protected UnaryQueryHashMap<InternalProcedure<IntSet>>         typesMap;
51         final protected UnaryQueryHashMap<IntProcedure>                      principalTypesMap;
52         final protected UnaryQueryHashMap<InternalProcedure<IntSet>>         predicatesMap;
53         final protected UnaryQueryHashMap<InternalProcedure<IntSet>>         superTypesMap;
54         final protected UnaryQueryHashMap<InternalProcedure<IntSet>>         typeHierarchyMap;
55         final protected UnaryQueryHashMap<InternalProcedure<IntSet>>         superRelationsMap;
56         
57         final protected UnaryQueryHashMap<IntProcedure>                      orderedSetMap;
58         final protected UnaryQueryHashMap<IntProcedure>                      assertedPredicatesMap;
59         final protected UnaryQueryHashMap<InternalProcedure<IntSet>>         directPredicatesMap;
60         final protected UnaryQueryHashMap<IntProcedure>                      directSuperRelationsMap;
61         
62         final protected UnaryQueryHashMap<InternalProcedure<RelationInfo>>   relationInfoQueryMap;
63         final protected UnaryQueryHashMap<InternalProcedure<byte[]>>         valueQueryMap;
64         
65         final protected StableHashMap<AsyncRead, AsyncReadEntry>                  asyncReadEntryMap; 
66         final protected StableHashMap<Read, ReadEntry>                            readEntryMap;
67         final protected StableHashMap<MultiRead, MultiReadEntry>                  multiReadEntryMap; 
68         final protected StableHashMap<AsyncMultiRead, AsyncMultiReadEntry>        asyncMultiReadEntryMap; 
69         final protected StableHashMap<ExternalRead, ExternalReadEntry>            externalReadEntryMap; 
70
71         final THashMap<CacheEntry, ArrayList<ListenerEntry>>       listeners;
72
73         final public QuerySupport                               querySupport;
74
75         public QueryCacheBase(QuerySupport querySupport, int threads) {
76                 
77                 THREADS = threads;
78                 THREAD_MASK = threads - 1;
79
80                 this.querySupport = querySupport;
81                 directPredicatesMap = new UnaryQueryHashMap();
82                 directSuperRelationsMap = new UnaryQueryHashMap();
83                 valueQueryMap = new UnaryQueryHashMap();
84                 principalTypesMap = new UnaryQueryHashMap();
85                 uRIToResourceMap = new THashMap<String, URIToResource>();
86                 //namespaceIndexMap = new THashMap<String, NamespaceIndex>();
87                 childMapMap = new UnaryQueryHashMap<InternalProcedure<ObjectResourceIdMap<String>>>();
88                 relationInfoQueryMap = new UnaryQueryHashMap();
89                 typeHierarchyMap = new UnaryQueryHashMap();
90                 superTypesMap = new UnaryQueryHashMap();
91                 superRelationsMap = new UnaryQueryHashMap();
92                 typesMap = new UnaryQueryHashMap();
93                 objectsMap = new DoubleKeyQueryHashMap();
94                 orderedSetMap = new UnaryQueryHashMap();
95                 predicatesMap = new UnaryQueryHashMap();
96                 statementsMap = new DoubleKeyQueryHashMap();
97                 directObjectsMap = new DoubleKeyQueryHashMap();
98                 assertedPredicatesMap = new UnaryQueryHashMap();
99                 assertedStatementsMap = new DoubleKeyQueryHashMap();
100                 asyncReadEntryMap = new StableHashMap<AsyncRead, AsyncReadEntry>(); 
101                 readEntryMap = new StableHashMap<Read, ReadEntry>();
102                 asyncMultiReadEntryMap = new StableHashMap<AsyncMultiRead, AsyncMultiReadEntry>(); 
103                 multiReadEntryMap = new StableHashMap<MultiRead, MultiReadEntry>(); 
104                 externalReadEntryMap = new StableHashMap<ExternalRead, ExternalReadEntry>(); 
105                 listeners = new THashMap<CacheEntry, ArrayList<ListenerEntry>>(10, 0.75f);
106         }
107         
108 //      public <T> Object performQuery(ReadGraphImpl parentGraph, final AsyncRead<T> query, final CacheEntryBase entry_, AsyncProcedure procedure_) throws DatabaseException {
109 //
110 //              AsyncReadEntry<T> entry = (AsyncReadEntry<T>)entry_;
111 //              AsyncProcedure<T> procedure = (AsyncProcedure<T>)procedure_;
112 //
113 //              ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
114 //
115 //              try {
116 //                      
117 //                      query.perform(queryGraph, new AsyncProcedure<T>() {
118 //
119 //                              @Override
120 //                              public void execute(AsyncReadGraph returnGraph, T result) {
121 //                                      ReadGraphImpl impl = (ReadGraphImpl)returnGraph;
122 //                                      entry.addOrSet(parentGraph, result);
123 //                                      try {
124 //                                              procedure.execute(parentGraph, result);
125 //                                      } catch (Throwable t) {
126 //                                              t.printStackTrace();
127 //                                      }
128 ////                                    parentBarrier.dec(query);
129 //                              }
130 //
131 //                              @Override
132 //                              public void exception(AsyncReadGraph returnGraph, Throwable t) {
133 //                                      ReadGraphImpl impl = (ReadGraphImpl)returnGraph;
134 ////                                    AsyncReadGraph resumeGraph = finalParentGraph.newAsync();
135 //                                      entry.except(parentGraph, t);
136 //                                      try {
137 //                                              procedure.exception(parentGraph, t);
138 //                                      } catch (Throwable t2) {
139 //                                              t2.printStackTrace();
140 //                                      }
141 ////                                    parentBarrier.dec(query);
142 //                              }
143 //
144 //                              @Override
145 //                              public String toString() {
146 //                                      return procedure.toString();
147 //                              }
148 //
149 //                      });
150 //
151 //              } catch (Throwable t) {
152 //
153 //                      entry.except(t);
154 //                      try {
155 //                              procedure.exception(parentGraph, t);
156 //                      } catch (Throwable t2) {
157 //                              t2.printStackTrace();
158 //                      }
159 ////                    parentBarrier.dec(query);
160 //
161 //              }
162 //              
163 //              return null;
164 //              
165 //      }
166
167 //      public <T> Object performQuery(ReadGraphImpl parentGraph, final Read<T> query, final CacheEntryBase entry_, AsyncProcedure procedure_) throws DatabaseException {
168 //
169 //              ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
170 //
171 //              ReadEntry entry = (ReadEntry)entry_;
172 //
173 //              try {
174 //
175 //                      T result = (T)query.perform(queryGraph);
176 //                      entry.addOrSet(queryGraph, result);
177 //
178 //                      return (T)entry.get(parentGraph, procedure_);
179 //
180 //              }  catch (Throwable t) {
181 //
182 //                      entry.except(t);
183 //                      return (T)entry.get(parentGraph, procedure_);
184 //
185 //              }
186 //              
187 //      }
188
189         public <T> Object performQuery(ReadGraphImpl parentGraph, final ExternalRead<T> query, final CacheEntryBase entry_, AsyncProcedure procedure_) throws DatabaseException {
190
191                 ExternalReadEntry entry = (ExternalReadEntry)entry_;
192                 AsyncProcedure<T> procedure = (AsyncProcedure<T>)procedure_;
193                 
194                 try {
195
196                         query.register(parentGraph, new Listener<T>() {
197
198                                 AtomicBoolean used = new AtomicBoolean(false);
199
200                                 @Override
201                                 public void execute(T result) {
202                                         
203                                         // Just for safety
204                                         if(entry.isDiscarded()) return;
205                                         
206                                         if(used.compareAndSet(false, true)) {
207                             //entry.setPending();
208                                                 entry.addOrSet(parentGraph.processor, result);
209                                                 procedure.execute(parentGraph, result);
210                                         } else {
211                                                 entry.queue(result);
212                                                 parentGraph.processor.updatePrimitive(query);
213                                         }
214                                         
215                                 }
216
217                                 @Override
218                                 public void exception(Throwable t) {
219                                         
220                                         entry.except(t);
221
222                                         if(used.compareAndSet(false, true)) {
223                                                 procedure.exception(parentGraph, t);
224                                         } else {
225 //                                              entry.queue(result);
226                                                 parentGraph.processor.updatePrimitive(query);
227                                         }
228                                         
229                                 }
230
231                                 @Override
232                                 public String toString() {
233                                         return procedure.toString();
234                                 }
235
236                                 @Override
237                                 public boolean isDisposed() {
238                                         return entry.isDiscarded() || !parentGraph.processor.isBound(entry);
239                                 }
240
241                         });
242                         
243                         return entry.getResult();
244
245                 } catch (Throwable t) {
246
247                         entry.except(t);
248                         procedure.exception(parentGraph, t);
249                         return entry.getResult();
250
251                 }
252                 
253         }
254
255         public <T> Object performQuery(ReadGraphImpl parentGraph, final AsyncMultiRead<T> query, final CacheEntryBase entry_, Object procedure_) throws DatabaseException {
256
257                 ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
258
259                 AsyncMultiReadEntry entry = (AsyncMultiReadEntry)entry_;
260                 AsyncMultiProcedure<T> procedure = (AsyncMultiProcedure<T>)procedure_;
261
262                 try {
263
264                         query.perform(queryGraph, new AsyncMultiProcedure<T>() {
265
266                                 @Override
267                                 public void execute(AsyncReadGraph graph, T result) {
268                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
269                                         entry.addOrSet(result);
270                                         try {
271                                                 procedure.execute(parentGraph, result);
272                                         } catch (Throwable t) {
273                                                 t.printStackTrace();
274                                         }
275                                 }
276
277                                 @Override
278                                 public void finished(AsyncReadGraph graph) {
279                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
280                                         entry.finish(parentGraph);
281                                         try {
282                                                 procedure.finished(parentGraph);
283                                         } catch (Throwable t) {
284                                                 t.printStackTrace();
285                                         }
286                                 }
287
288                                 @Override
289                                 public void exception(AsyncReadGraph graph, Throwable t) {
290                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
291                                         entry.except(parentGraph, t);
292                                         try {
293                                                 procedure.exception(parentGraph, t);
294                                         } catch (Throwable t2) {
295                                                 t2.printStackTrace();
296                                         }
297                                 }
298
299                         });
300                         
301                         return entry.getResult();
302
303                 } catch (Throwable t) {
304
305                         entry.except(t);
306                         try {
307                                 procedure.exception(parentGraph, t);
308                         } catch (Throwable t2) {
309                                 t2.printStackTrace();
310                         }
311                         
312                         return entry.getResult();
313                         
314                 }
315                 
316         }
317
318         public <T> Object performQuery(ReadGraphImpl parentGraph, final MultiRead<T> query, final CacheEntryBase entry_, Object procedure_) throws DatabaseException {
319
320                 ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
321
322                 AsyncMultiReadEntry entry = (AsyncMultiReadEntry)entry_;
323                 AsyncMultiProcedure<T> procedure = (AsyncMultiProcedure<T>)procedure_;
324
325                 try {
326
327                         query.perform(queryGraph, new AsyncMultiProcedure<T>() {
328
329                                 @Override
330                                 public void execute(AsyncReadGraph graph, T result) {
331                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
332                                         entry.addOrSet(result);
333                                         try {
334                                                 procedure.execute(parentGraph, result);
335                                         } catch (Throwable t) {
336                                                 t.printStackTrace();
337                                         }
338                                 }
339
340                                 @Override
341                                 public void finished(AsyncReadGraph graph) {
342                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
343                                         entry.finish(parentGraph);
344                                         try {
345                                                 procedure.finished(parentGraph);
346                                         } catch (Throwable t) {
347                                                 t.printStackTrace();
348                                         }
349                                 }
350
351                                 @Override
352                                 public void exception(AsyncReadGraph graph, Throwable t) {
353                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
354                                         entry.except(parentGraph, t);
355                                         try {
356                                                 procedure.exception(parentGraph, t);
357                                         } catch (Throwable t2) {
358                                                 t2.printStackTrace();
359                                         }
360                                 }
361
362                         });
363                         
364                         return entry.getResult();
365
366                 } catch (Throwable t) {
367
368                         entry.except(t);
369                         try {
370                                 procedure.exception(parentGraph, t);
371                         } catch (Throwable t2) {
372                                 t2.printStackTrace();
373                         }
374                         
375                         return entry.getResult();
376                         
377                 }
378                 
379         }
380         
381         public ListenerEntry registerDependencies(ReadGraphImpl graph, CacheEntry child, CacheEntry parent, ListenerBase listener, Object procedure, boolean inferred) {
382
383                 if (parent != null && !inferred) {
384                         try {
385                                 if(!child.isImmutable(graph)) {
386                                         synchronized(child) {
387                                                 child.addParent(parent);
388                                         }
389                                 }
390                         } catch (DatabaseException e) {
391                                 Logger.defaultLogError(e);
392                         }
393                         if(DebugPolicy.DEPENDENCIES) System.out.println(child + " -> " + parent);
394                 }
395
396                 if (listener != null) {
397                         return registerListener(child, listener, procedure);
398                 } else {
399                         return null;
400                 }
401
402         }
403         
404         public synchronized ListenerEntry registerListener(final CacheEntry entry, final ListenerBase base, final Object procedure) {
405
406                 assert (entry != null);
407
408                 if (base.isDisposed())
409                         return null;
410
411                 return addListener(entry, base, procedure);
412
413         }
414
415         protected void primeListenerEntry(final ListenerEntry entry, final Object result) {
416                 entry.setLastKnown(result);
417         }
418
419         private ListenerEntry addListener(CacheEntry entry, ListenerBase base, Object procedure) {
420
421                 assert (entry != null);
422                 assert (procedure != null);
423
424                 ArrayList<ListenerEntry> list = listeners.get(entry);
425                 if (list == null) {
426                         list = new ArrayList<ListenerEntry>(1);
427                         listeners.put(entry, list);
428                 }
429
430                 ListenerEntry result = new ListenerEntry(entry, base, procedure);
431                 int currentIndex = list.indexOf(result);
432                 // There was already a listener
433                 if(currentIndex > -1) {
434                         ListenerEntry current = list.get(currentIndex);
435                         if(!current.base.isDisposed()) return null;
436                         list.set(currentIndex, result);
437                 } else {
438                         list.add(result);
439                 }
440
441                 if(DebugPolicy.LISTENER) {
442                         new Exception().printStackTrace();
443                         System.out.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure);
444                 }
445
446                 return result;
447
448         }
449         
450         
451         public Collection<CacheEntry> getRootList() {
452
453                 ArrayList<CacheEntry> result = new ArrayList<CacheEntry>();
454
455                 for (Object e : valueQueryMap.values()) {
456                         result.add((CacheEntry) e);
457                 }
458                 for (Object e : directPredicatesMap.values()) {
459                         result.add((CacheEntry) e);
460                 }
461                 for (Object e : directSuperRelationsMap.values()) {
462                         result.add((CacheEntry) e);
463                 }
464                 for (Object e : objectsMap.values()) {
465                         result.add((CacheEntry) e);
466                 }
467                 for (Object e : directObjectsMap.values()) {
468                         result.add((CacheEntry) e);
469                 }
470                 for (Object e : principalTypesMap.values()) {
471                         result.add((CacheEntry) e);
472                 }
473                 for (Object e : superRelationsMap.values()) {
474                         result.add((CacheEntry) e);
475                 }
476                 for (Object e : superTypesMap.values()) {
477                         result.add((CacheEntry) e);
478                 }
479                 for (Object e : typesMap.values()) {
480                         result.add((CacheEntry) e);
481                 }
482                 for (Object e : objectsMap.values()) {
483                         result.add((CacheEntry) e);
484                 }
485                 for (Object e : assertedStatementsMap.values()) {
486                         result.add((CacheEntry) e);
487                 }
488                 for (Object e : readEntryMap.values()) {
489                         if(e instanceof CacheEntry) {
490                                 result.add((CacheEntry) e);
491                         } else {
492                                 System.err.println("e=" + e);
493                         }
494                 }
495                 for (Object e : asyncReadEntryMap.values()) {
496                         if(e instanceof CacheEntry) {
497                                 result.add((CacheEntry) e);
498                         } else {
499                                 System.err.println("e=" + e);
500                         }
501                 }
502                 for (Object e : externalReadEntryMap.values()) {
503                         result.add((CacheEntry) e);
504                 }
505                 for (Object e : orderedSetMap.values()) {
506                         result.add((CacheEntry) e);
507                 }
508
509                 return result;
510
511         }
512
513         public int calculateCurrentSize() {
514                 
515                 int realSize = 0;
516                 
517                 realSize += directPredicatesMap.size();
518                 realSize += directSuperRelationsMap.size();
519                 realSize += principalTypesMap.size();
520                 realSize += uRIToResourceMap.size();
521                 //realSize += namespaceIndexMap.size();
522                 realSize += childMapMap.size();
523                 
524                 realSize += relationInfoQueryMap.size();
525                 realSize += superTypesMap.size();
526                 realSize += typeHierarchyMap.size();
527                 realSize += superRelationsMap.size();
528                 realSize += typesMap.size();
529                 
530                 realSize += valueQueryMap.size();
531                 realSize += directObjectsMap.size();
532                 realSize += objectsMap.size();
533                 realSize += orderedSetMap.size();
534                 realSize += predicatesMap.size();
535                 
536                 realSize += statementsMap.size();
537                 realSize += assertedPredicatesMap.size();
538                 realSize += assertedStatementsMap.size();
539                 realSize += externalReadEntryMap.size();
540                 realSize += asyncReadEntryMap.size();
541                 
542                 realSize += readEntryMap.size();
543                 realSize += asyncMultiReadEntryMap.size();
544                 realSize += multiReadEntryMap.size();
545                 
546                 return realSize;
547                 
548         }
549         
550         CacheCollectionResult allCaches(CacheCollectionResult result) {
551
552                 int level = Integer.MAX_VALUE;
553                 directPredicatesMap.values(level, result);
554                 directSuperRelationsMap.values(level, result);
555                 principalTypesMap.values(level, result);
556                 for(CacheEntryBase e : uRIToResourceMap.values())
557                         if(e.getLevel() <= level)
558                                 result.add(e);
559 //              for(CacheEntryBase e : namespaceIndexMap.values())
560 //                      if(e.getLevel() <= level)
561 //                              result.add(e);
562
563                 childMapMap.values(level, result);
564                 
565                 relationInfoQueryMap.values(level, result);
566                 superTypesMap.values(level, result);
567                 typeHierarchyMap.values(level, result);
568                 superRelationsMap.values(level, result);
569                 typesMap.values(level, result);
570
571                 valueQueryMap.values(level, result);
572                 directObjectsMap.values(level, result);
573                 objectsMap.values(level, result);
574                 orderedSetMap.values(level, result);
575                 predicatesMap.values(level, result);
576
577                 statementsMap.values(level, result);
578                 assertedPredicatesMap.values(level, result);
579                 assertedStatementsMap.values(level, result);
580                 externalReadEntryMap.values(level, result);
581                 asyncReadEntryMap.values(level, result);
582                 
583                 readEntryMap.values(level, result);
584                 asyncMultiReadEntryMap.values(level, result);
585                 multiReadEntryMap.values(level, result);
586
587                 return result;
588                 
589         }
590         
591         public void scanPending() {
592
593                 ArrayList<CacheEntry> entries = new ArrayList<CacheEntry>();
594
595                 entries.addAll(directPredicatesMap.values());
596                 entries.addAll(directSuperRelationsMap.values());
597                 entries.addAll(principalTypesMap.values());
598                 entries.addAll(uRIToResourceMap.values());
599                 //entries.addAll(namespaceIndexMap.values());
600                 entries.addAll(childMapMap.values());
601                 entries.addAll(relationInfoQueryMap.values());
602                 entries.addAll(superTypesMap.values());
603                 entries.addAll(superRelationsMap.values());
604                 entries.addAll(typesMap.values());
605                 entries.addAll(valueQueryMap.values());
606                 entries.addAll(directObjectsMap.values());
607                 entries.addAll(objectsMap.values());
608                 entries.addAll(orderedSetMap.values());
609                 entries.addAll(predicatesMap.values());
610                 entries.addAll(orderedSetMap.values());
611                 entries.addAll(statementsMap.values());
612                 //                      entries.addAll(assertedObjectsMap.values());
613                 entries.addAll(assertedPredicatesMap.values());
614                 entries.addAll(assertedStatementsMap.values());
615                 entries.addAll(externalReadEntryMap.values());
616                 entries.addAll(asyncReadEntryMap.values());
617                 entries.addAll(externalReadEntryMap.values());
618                 entries.addAll(readEntryMap.values());
619                 entries.addAll(asyncMultiReadEntryMap.values());
620                 entries.addAll(multiReadEntryMap.values());
621                 entries.addAll(readEntryMap.values());
622                 System.out.println(entries.size() + " entries.");
623                 for(Object e : entries) {
624                         if(e instanceof CacheEntry) {
625                                 CacheEntry en = (CacheEntry)e;
626                                 if(en.isPending()) System.out.println("pending " + e);
627                                 if(en.isExcepted()) System.out.println("excepted " + e);
628                                 if(en.isDiscarded()) System.out.println("discarded " + e);
629                                 if(en.isRefuted()) System.out.println("refuted " + e);
630                                 if(en.isFresh()) System.out.println("fresh " + e);
631                         } else {
632                                 //System.out.println("Unknown object " + e);
633                         }
634                 }
635         }
636         
637         public static void waitPending(CacheEntry entry) throws DatabaseException {
638                 
639                 int counter = 0;
640                 while(entry.isPending()) {
641                         try {
642                                 Thread.sleep(1);
643                                 counter++;
644                                 if(counter > 5000) {
645                                         CacheEntryBase base = ((CacheEntryBase)entry);
646 //                                      if(base.created != null) {
647 //                                              System.err.println("created:");
648 //                                              base.created.printStackTrace();
649 //                                      }
650 //                                      if(base.performed != null) {
651 //                                              System.err.println("performed:");
652 //                                              base.performed.printStackTrace();
653 //                                      }
654 //                                      if(base.ready != null) {
655 //                                              System.err.println("ready:");
656 //                                              base.ready.printStackTrace();
657 //                                      }
658                                         new Exception("Timeout waiting for request to complete: " + entry.getOriginalRequest().toString()).printStackTrace();
659                                         throw new DatabaseException("Timeout waiting for request to complete.");
660                                         //System.err.println("asd");
661                                         //base.getQuery().recompute(null, null, entry);
662                                 }
663                         } catch (InterruptedException e) {
664                         }
665                 }
666
667         }
668         
669         //////////////////////////////////////
670         
671         static public Collection<Objects> entriesObjects(QueryProcessor processor, int r1) {
672                 synchronized(processor.cache.objectsMap) {
673                         return processor.cache.objectsMap.values(r1);
674                 }
675         }
676         
677         static public Collection<Objects> entriesObjects(QueryProcessor processor) {
678                 synchronized(processor.cache.objectsMap) {
679                         return processor.cache.objectsMap.values();
680                 }
681         }
682         
683         static public Collection<CacheEntry> entriesDirectPredicates(QueryProcessor processor) {
684                 synchronized(processor.cache.directPredicatesMap) {
685                         return processor.cache.directPredicatesMap.values();
686                 }
687         }
688
689         final static Collection<DirectObjects> entriesDirectObjects(final QueryProcessor processor, final int r1) {
690                 DoubleKeyQueryHashMap<IntProcedure> hash = processor.cache.directObjectsMap;
691                 return hash.values(r1);
692         }
693         
694         final static Collection<Statements> entriesStatements(final QueryProcessor processor, final int r1) {
695                 return processor.cache.statementsMap.values(r1);
696         }
697
698         final static Types entryTypes(final QueryProcessor processor, final int r) {
699                 return (Types)processor.cache.typesMap.get(r);
700         }
701
702         final static PrincipalTypes entryPrincipalTypes(final QueryProcessor processor, final int r) {
703                 return (PrincipalTypes)processor.cache.principalTypesMap.get(r);
704         }
705
706         final static OrderedSet entryOrderedSet(final QueryProcessor processor, final int r) {
707                 return (OrderedSet)processor.cache.orderedSetMap.get(r);
708         }
709         
710         final static ValueQuery entryValueQuery(final QueryProcessor processor, final int r) {
711                 return (ValueQuery)processor.cache.valueQueryMap.get(r);
712         }
713
714         final static DirectPredicates entryDirectPredicates(final QueryProcessor processor, final int r) {
715                 return (DirectPredicates)processor.cache.directPredicatesMap.get(r);
716         }
717
718         public final static ReadEntry entryRead(final QueryProcessor processor, final Read request) {
719                 return (ReadEntry)processor.cache.readEntryMap.get(request);
720         }
721
722         public final static MultiReadEntry entryMultiRead(final QueryProcessor processor, final MultiRead request) {
723                 return (MultiReadEntry)processor.cache.multiReadEntryMap.get(request);
724         }
725
726         public final static AsyncReadEntry entryAsyncRead(final QueryProcessor processor, final AsyncRead request) {
727                 return (AsyncReadEntry)processor.cache.asyncReadEntryMap.get(request);
728         }
729
730         public final static AsyncMultiReadEntry entryAsyncMultiRead(final QueryProcessor processor, final AsyncMultiRead request) {
731                 return (AsyncMultiReadEntry)processor.cache.asyncMultiReadEntryMap.get(request);
732         }
733
734         final protected static long keyR2(long r1, long r2) {
735         long result = (r1<<32) | (r2 & 0xffffffffL); 
736         return result;
737     }
738         
739         final protected static <T> T id(T o) {
740                 return o;
741         }
742
743     final protected static int keyR(int r) {
744         return r;
745     }
746
747     final protected static String keyID(String id) {
748         return id;
749     }
750         
751     protected static InternalProcedure<IntSet> emptyIntSetProcedure = new InternalProcedure<IntSet>() {
752
753                 @Override
754                 public void execute(ReadGraphImpl graph, IntSet result) {
755                 }
756
757                 @Override
758                 public void exception(ReadGraphImpl graph, Throwable throwable) {
759                 }
760                 
761         }; 
762
763     protected static InternalProcedure<byte[]> emptyBytesProcedure = new InternalProcedure<byte[]>() {
764
765                 @Override
766                 public void execute(ReadGraphImpl graph, byte[] bytes) {
767                 }
768
769                 @Override
770                 public void exception(ReadGraphImpl graph, Throwable throwable) {
771                 }
772                 
773         }; 
774
775     protected static InternalProcedure<Integer> emptyIntegerProcedure = new InternalProcedure<Integer>() {
776
777                 @Override
778                 public void execute(ReadGraphImpl graph, Integer i) {
779                 }
780
781                 @Override
782                 public void exception(ReadGraphImpl graph, Throwable throwable) {
783                 }
784                 
785         }; 
786
787
788     protected static InternalProcedure<TObjectIntHashMap<String>> emptyNamespaceProcedure = new InternalProcedure<TObjectIntHashMap<String>>() {
789
790                 @Override
791                 public void execute(ReadGraphImpl graph, TObjectIntHashMap<String> i) {
792                 }
793
794                 @Override
795                 public void exception(ReadGraphImpl graph, Throwable throwable) {
796                 }
797                 
798         }; 
799
800
801     protected static InternalProcedure<RelationInfo> emptyRelationInfoProcedure = new InternalProcedure<RelationInfo>() {
802
803                 @Override
804                 public void execute(ReadGraphImpl graph, RelationInfo i) {
805                 }
806
807                 @Override
808                 public void exception(ReadGraphImpl graph, Throwable throwable) {
809                 }
810                 
811         }; 
812
813     protected static InternalProcedure<ObjectResourceIdMap<String>> emptyChildMapProcedure = new InternalProcedure<ObjectResourceIdMap<String>>() {
814
815                 @Override
816                 public void execute(ReadGraphImpl graph, ObjectResourceIdMap<String> i) {
817                 }
818
819                 @Override
820                 public void exception(ReadGraphImpl graph, Throwable throwable) {
821                 }
822                 
823         }; 
824
825         
826         
827         protected static IntProcedure emptyIntProcedure = new IntProcedure() {
828                 
829                 @Override
830                 public void finished(ReadGraphImpl graph) {
831                 }
832                 
833                 @Override
834                 public void execute(ReadGraphImpl graph, int i) {
835                 }
836                 
837                 @Override
838                 public void exception(ReadGraphImpl graph, Throwable throwable) {
839                 }
840         }; 
841         
842         protected static TripleIntProcedure emptyTripleIntProcedure = new TripleIntProcedure() {
843
844                 @Override
845                 public void execute(ReadGraphImpl graph, int s, int p, int o) {
846                 }
847
848                 @Override
849                 public void finished(ReadGraphImpl graph) {
850                 }
851
852                 @Override
853                 public void exception(ReadGraphImpl graph, Throwable throwable) {
854                 }
855                 
856         }; 
857
858     protected static AsyncProcedure<Object> emptyAsyncProcedure = new AsyncProcedure<Object>() {
859
860                 @Override
861                 public void execute(AsyncReadGraph graph, Object result) {
862                 }
863
864                 @Override
865                 public void exception(AsyncReadGraph graph, Throwable throwable) {
866                 }
867                 
868         }; 
869         
870     protected static AsyncMultiProcedure<Object> emptyAsyncMultiProcedure = new AsyncMultiProcedure<Object>() {
871
872                 @Override
873                 public void execute(AsyncReadGraph graph, Object result) {
874                 }
875
876                 @Override
877                 public void finished(AsyncReadGraph graph) {
878                 }
879
880                 @Override
881                 public void exception(AsyncReadGraph graph, Throwable throwable) {
882                 }
883
884                 
885         }; 
886
887         protected static InternalProcedure<IntSet> emptyProcedureTypes = emptyIntSetProcedure;
888     protected static InternalProcedure<IntSet> emptyProcedureSuperTypes = emptyIntSetProcedure;
889     protected static InternalProcedure<IntSet> emptyProcedureTypeHierarchy = emptyIntSetProcedure;
890     protected static InternalProcedure<IntSet> emptyProcedureSuperRelations = emptyIntSetProcedure;
891     protected static InternalProcedure<IntSet> emptyProcedurePredicates = emptyIntSetProcedure;
892     protected static InternalProcedure<IntSet> emptyProcedureDirectPredicates = emptyIntSetProcedure;
893
894     protected static IntProcedure emptyProcedureObjects = emptyIntProcedure;
895     protected static IntProcedure emptyProcedureDirectObjects = emptyIntProcedure;
896     protected static IntProcedure emptyProcedurePrincipalTypes = emptyIntProcedure;
897     protected static IntProcedure emptyProcedureDirectSuperRelations = emptyIntProcedure;
898     protected static IntProcedure emptyProcedureAssertedPredicates = emptyIntProcedure;
899     protected static IntProcedure emptyProcedureOrderedSet = emptyIntProcedure;
900     
901     protected static TripleIntProcedure emptyProcedureStatements = emptyTripleIntProcedure;
902     protected static TripleIntProcedure emptyProcedureAssertedStatements = emptyTripleIntProcedure;
903
904     protected static InternalProcedure<byte[]> emptyProcedureValueQuery = emptyBytesProcedure;
905     
906     protected static InternalProcedure<Integer> emptyProcedureURIToResource = emptyIntegerProcedure;
907     protected static InternalProcedure<TObjectIntHashMap<String>> emptyProcedureNamespaceIndex = emptyNamespaceProcedure;
908     protected static InternalProcedure<ObjectResourceIdMap<String>> emptyProcedureChildMap = emptyChildMapProcedure;
909     protected static InternalProcedure<RelationInfo> emptyProcedureRelationInfoQuery = emptyRelationInfoProcedure;
910
911     protected static AsyncProcedure emptyProcedureReadEntry = emptyAsyncProcedure;
912     protected static AsyncProcedure emptyProcedureAsyncReadEntry = emptyAsyncProcedure;
913     protected static AsyncMultiProcedure emptyProcedureMultiReadEntry = emptyAsyncMultiProcedure;
914     protected static AsyncMultiProcedure emptyProcedureAsyncMultiReadEntry = emptyAsyncMultiProcedure;
915     protected static AsyncProcedure emptyProcedureExternalReadEntry = emptyAsyncProcedure;
916         
917     static class AsyncProcedureWrapper<T> implements AsyncProcedure<T> {
918         
919         private AsyncProcedure<T> procedure;
920         private T result = null;
921         private Throwable throwable = null;
922         private Semaphore s = new Semaphore(0);
923         
924         AsyncProcedureWrapper(AsyncProcedure<T> procedure) {
925                 this.procedure = procedure;
926         }
927
928                 @Override
929                 public void execute(AsyncReadGraph graph, T result) {
930                         if(procedure != null) procedure.execute(graph, result);
931                         this.result = result;
932                         s.release();
933                 }
934
935                 @Override
936                 public void exception(AsyncReadGraph graph, Throwable throwable) {
937                         if(procedure != null) procedure.exception(graph, throwable);
938                         this.throwable = throwable;
939                         s.release();
940                 }
941                 
942                 public T get() throws DatabaseException {
943                         try {
944                                 s.acquire();
945                         } catch (InterruptedException e) {
946                                 e.printStackTrace();
947                         }
948                         if(throwable != null) {
949                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
950                                 else throw new DatabaseException(throwable);
951                         } else {
952                                 return result;
953                         }
954                 }
955                 
956     }
957
958     static class ExternalProcedureWrapper<T> implements AsyncProcedure<T> {
959         
960         private Procedure<T> procedure;
961         private T result = null;
962         private Throwable throwable = null;
963         
964         ExternalProcedureWrapper(Procedure<T> procedure) {
965             this.procedure = procedure;
966         }
967
968         @Override
969         public void execute(AsyncReadGraph graph, T result) {
970             if(procedure != null) procedure.execute(result);
971             this.result = result;
972         }
973
974         @Override
975         public void exception(AsyncReadGraph graph, Throwable throwable) {
976             if(procedure != null) procedure.exception(throwable);
977             this.throwable = throwable;
978         }
979         
980         public T get() throws DatabaseException {
981             if(throwable != null) {
982                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
983                 else throw new DatabaseException(throwable);
984             } else {
985                 return result;
986             }
987         }
988         
989     }
990
991     
992     static class InternalProcedureWrapper<T> implements InternalProcedure<T> {
993         
994         private InternalProcedure<T> procedure;
995         private T result = null;
996         private Throwable throwable = null;
997         
998         InternalProcedureWrapper(InternalProcedure<T> procedure) {
999                 this.procedure = procedure;
1000         }
1001
1002                 @Override
1003                 public void execute(ReadGraphImpl graph, T result) throws DatabaseException {
1004                         if(procedure != null) procedure.execute(graph, result);
1005                         this.result = result;
1006                 }
1007
1008                 @Override
1009                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1010                         if(procedure != null) procedure.exception(graph, throwable);
1011                         this.throwable = throwable;
1012                 }
1013                 
1014                 public T get() throws DatabaseException {
1015                         if(throwable != null) {
1016                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1017                                 else throw new DatabaseException(throwable);
1018                         } else {
1019                                 return result;
1020                         }
1021                 }
1022                 
1023     }
1024     
1025     static class IntSetWrapper implements IntProcedure {
1026         
1027         private IntProcedure procedure;
1028         final private IntSet result;
1029         private Throwable throwable = null;
1030         
1031         IntSetWrapper(ReadGraphImpl graph, IntProcedure procedure) {
1032                 this.procedure = procedure;
1033                 result = new IntSet(graph.processor.querySupport);
1034         }
1035
1036                 @Override
1037                 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
1038                         if(procedure != null) procedure.execute(graph, i);
1039                         result.add(i);
1040                 }
1041
1042                 @Override
1043                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1044                         if(procedure != null) procedure.exception(graph, throwable);
1045                         this.throwable = throwable;
1046                 }
1047                 
1048                 @Override
1049                 public void finished(ReadGraphImpl graph) throws DatabaseException {
1050                         if(procedure != null) procedure.finished(graph);
1051                 }
1052                 
1053                 public IntSet get() throws DatabaseException {
1054                         if(throwable != null) {
1055                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1056                                 else throw new DatabaseException(throwable);
1057                         } else {
1058                                 return result;
1059                         }
1060                 }
1061
1062     }
1063
1064     static class TripleIntProcedureWrapper implements TripleIntProcedure {
1065         
1066         private TripleIntProcedure procedure;
1067         private IntArray result = new IntArray();
1068         private Throwable throwable = null;
1069         
1070         TripleIntProcedureWrapper(TripleIntProcedure procedure) {
1071                 this.procedure = procedure;
1072         }
1073
1074                 @Override
1075                 public void execute(ReadGraphImpl graph, int i1, int i2, int i3) throws DatabaseException {
1076                         if(procedure != null) procedure.execute(graph, i1, i2, i3);
1077                         result.add(i1);
1078                         result.add(i2);
1079                         result.add(i3);
1080                 }
1081
1082                 @Override
1083                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1084                         if(procedure != null) procedure.exception(graph, throwable);
1085                         this.throwable = throwable;
1086                 }
1087                 
1088                 @Override
1089                 public void finished(ReadGraphImpl graph) throws DatabaseException {
1090                         if(procedure != null) procedure.finished(graph);
1091                 }
1092                 
1093                 public IntArray get() throws DatabaseException {
1094                         if(throwable != null) {
1095                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1096                                 else throw new DatabaseException(throwable);
1097                         } else {
1098                                 return result;
1099                         }
1100                 }
1101
1102     }
1103
1104     public static <T> T resultExternalReadEntry(ReadGraphImpl graph, ExternalRead r, CacheEntry parent, ListenerBase listener, Procedure<T> procedure) throws DatabaseException {
1105         ExternalProcedureWrapper<T> wrap = new ExternalProcedureWrapper<>(procedure);
1106         QueryCache.runnerExternalReadEntry(graph, r, parent, listener, wrap);
1107         return wrap.get();
1108     }
1109
1110     public static <T> T resultReadEntry(ReadGraphImpl graph, Read r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
1111         AsyncProcedureWrapper<T> wrap = new AsyncProcedureWrapper<>(procedure);
1112         QueryCache.runnerReadEntry(graph, r, parent, listener, wrap, true);
1113         return wrap.get();
1114     }
1115
1116     public static <T> T resultAsyncReadEntry(ReadGraphImpl graph, AsyncRead r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
1117         AsyncProcedureWrapper<T> wrap = new AsyncProcedureWrapper<>(procedure);
1118         QueryCache.runnerAsyncReadEntry(graph, r, parent, listener, wrap, true);
1119         return wrap.get();
1120     }
1121
1122     public static byte[] resultValueQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1123         InternalProcedureWrapper<byte[]> wrap = new InternalProcedureWrapper<>(null);
1124         QueryCache.runnerValueQuery(graph, r, parent, listener, wrap);
1125         return wrap.get();
1126     }
1127
1128     public static RelationInfo resultRelationInfoQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1129         InternalProcedureWrapper<RelationInfo> wrap = new InternalProcedureWrapper<>(null);
1130         QueryCache.runnerRelationInfoQuery(graph, r, parent, listener, wrap);
1131         return wrap.get();
1132     }
1133
1134     public static IntSet resultSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1135         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1136         QueryCache.runnerSuperRelations(graph, r, parent, listener, wrap);
1137         return wrap.get();
1138     }
1139
1140     public static IntSet resultSuperTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1141         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1142         QueryCache.runnerSuperTypes(graph, r, parent, listener, wrap);
1143         return wrap.get();
1144     }
1145     
1146     public static IntSet resultTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1147         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1148         QueryCache.runnerTypes(graph, r, parent, listener, wrap);
1149         return wrap.get();
1150     }
1151
1152     public static IntSet resultPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1153         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1154         QueryCache.runnerPredicates(graph, r, parent, listener, wrap);
1155         return wrap.get();
1156     }
1157
1158     public static IntSet resultDirectPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1159         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1160         QueryCache.runnerDirectPredicates(graph, r, parent, listener, wrap);
1161         return wrap.get();
1162     }
1163
1164     public static IntArray resultAssertedStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1165         TripleIntProcedureWrapper wrap = new TripleIntProcedureWrapper(null);
1166         QueryCache.runnerAssertedStatements(graph, r1, r2, parent, listener, wrap);
1167         return wrap.get();
1168     }
1169
1170     public static Integer resultURIToResource(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1171         InternalProcedureWrapper<Integer> wrap = new InternalProcedureWrapper<Integer>(null);
1172         QueryCache.runnerURIToResource(graph, id, parent, listener, wrap);
1173         return wrap.get();
1174     }
1175
1176     public static ObjectResourceIdMap<String> resultChildMap(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1177         InternalProcedureWrapper<ObjectResourceIdMap<String>> wrap = new InternalProcedureWrapper<ObjectResourceIdMap<String>>(null);
1178         QueryCache.runnerChildMap(graph, r, parent, listener, wrap);
1179         return wrap.get();
1180     }
1181
1182     static boolean shouldCache(QueryProcessor processor, int r) {
1183         return processor.isImmutable(r);
1184     }
1185     
1186     static boolean shouldCache(QueryProcessor processor, int r, int r2) {
1187         return processor.isImmutable(r);
1188     }
1189
1190     static boolean shouldCache(QueryProcessor processor, Object o) {
1191         return false;
1192     }
1193     
1194 }
1195