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