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