]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCache.java
dbd0068c3f66100404eda02d5fbba9d70fdc8308
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / QueryCache.java
1 package org.simantics.db.impl.query;
2
3 import org.simantics.db.RelationInfo;
4 import org.simantics.db.exception.DatabaseException;
5 import org.simantics.db.impl.graph.ReadGraphImpl;
6 import org.simantics.db.impl.procedure.InternalProcedure;
7 import org.simantics.db.procedure.AsyncMultiProcedure;
8 import org.simantics.db.procedure.AsyncProcedure;
9 import org.simantics.db.procedure.ListenerBase;
10 import org.simantics.db.request.AsyncMultiRead;
11 import org.simantics.db.request.AsyncRead;
12 import org.simantics.db.request.ExternalRead;
13 import org.simantics.db.request.MultiRead;
14 import org.simantics.db.request.Read;
15
16 import gnu.trove.map.hash.TObjectIntHashMap;
17
18 public class QueryCache extends QueryCacheBase {
19
20     public QueryCache(QuerySupport querySupport, int threads) {
21         super(querySupport, threads);
22     }
23
24     Objects getOrCreateObjects(int r1, int r2) throws DatabaseException {
25         Objects existing = null;
26         synchronized(objectsMap) {
27             existing = (Objects)objectsMap.get(r1,r2);
28             if(existing == null) {
29                 existing = new Objects(r1,r2);
30                 existing.clearResult(querySupport);
31                 existing.setPending();
32                 objectsMap.put(keyR2(r1,r2), existing);
33                 return existing;
34             }
35             if(existing.requiresComputation()) {
36                 existing.setPending();
37                 return existing;
38             }
39         }
40         if(existing.isPending()) waitPending(existing);
41         return existing;
42     }
43     
44     void remove(Objects entry) {
45         synchronized(objectsMap) {
46             objectsMap.remove(entry.id);
47         }
48     }
49     
50     public static void runnerObjects(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
51         if(parent == null && listener == null) {
52             Objects.computeForEach(graph, r1,r2, null, procedure);
53             return;
54         }
55         QueryCache cache  = graph.processor.cache;
56         if(procedure == null) procedure = emptyProcedureObjects;
57         Objects entry = (Objects)cache.getOrCreateObjects(r1,r2);
58         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
59         if(entry.isReady()) entry.performFromCache(graph, procedure);
60         else {
61             Objects.computeForEach(graph, r1,r2, entry, procedure);
62             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
63         }
64     }
65     
66     Statements getOrCreateStatements(int r1, int r2) throws DatabaseException {
67         Statements existing = null;
68         synchronized(statementsMap) {
69             existing = (Statements)statementsMap.get(r1,r2);
70             if(existing == null) {
71                 existing = new Statements(r1,r2);
72                 existing.clearResult(querySupport);
73                 existing.setPending();
74                 statementsMap.put(keyR2(r1,r2), existing);
75                 return existing;
76             }
77             if(existing.requiresComputation()) {
78                 existing.setPending();
79                 return existing;
80             }
81         }
82         if(existing.isPending()) waitPending(existing);
83         return existing;
84     }
85     
86     void remove(Statements entry) {
87         synchronized(statementsMap) {
88             statementsMap.remove(entry.id);
89         }
90     }
91     
92     public static void runnerStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, TripleIntProcedure procedure) throws DatabaseException {
93         if(parent == null && listener == null) {
94             Statements.computeForEach(graph, r1,r2, null, procedure);
95             return;
96         }
97         QueryCache cache  = graph.processor.cache;
98         if(procedure == null) procedure = emptyProcedureStatements;
99         Statements entry = (Statements)cache.getOrCreateStatements(r1,r2);
100         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
101         if(entry.isReady()) entry.performFromCache(graph, procedure);
102         else {
103             Statements.computeForEach(graph, r1,r2, entry, procedure);
104             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
105         }
106     }
107     
108     DirectObjects getOrCreateDirectObjects(int r1, int r2) throws DatabaseException {
109         DirectObjects existing = null;
110         synchronized(directObjectsMap) {
111             existing = (DirectObjects)directObjectsMap.get(r1,r2);
112             if(existing == null) {
113                 existing = new DirectObjects(r1,r2);
114                 existing.clearResult(querySupport);
115                 existing.setPending();
116                 directObjectsMap.put(keyR2(r1,r2), existing);
117                 return existing;
118             }
119             if(existing.requiresComputation()) {
120                 existing.setPending();
121                 return existing;
122             }
123         }
124         if(existing.isPending()) waitPending(existing);
125         return existing;
126     }
127     
128     void remove(DirectObjects entry) {
129         synchronized(directObjectsMap) {
130             directObjectsMap.remove(entry.id);
131         }
132     }
133     
134     public static void runnerDirectObjects(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
135         if(parent == null && listener == null) {
136             DirectObjects.computeForEach(graph, r1,r2, null, procedure);
137             return;
138         }
139         QueryCache cache  = graph.processor.cache;
140         if(procedure == null) procedure = emptyProcedureDirectObjects;
141         DirectObjects entry = (DirectObjects)cache.getOrCreateDirectObjects(r1,r2);
142         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
143         if(entry.isReady()) entry.performFromCache(graph, procedure);
144         else {
145             DirectObjects.computeForEach(graph, r1,r2, entry, procedure);
146             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
147         }
148     }
149     
150     RelationInfoQuery getOrCreateRelationInfoQuery(int r) throws DatabaseException {
151         RelationInfoQuery existing = null;
152         synchronized(relationInfoQueryMap) {
153             existing = (RelationInfoQuery)relationInfoQueryMap.get(r);
154             if(existing == null) {
155                 existing = new RelationInfoQuery(r);
156                 existing.clearResult(querySupport);
157                 existing.setPending();
158                 relationInfoQueryMap.put(keyR(r), existing);
159                 return existing;
160             }
161             if(existing.requiresComputation()) {
162                 existing.setPending();
163                 return existing;
164             }
165         }
166         if(existing.isPending()) waitPending(existing);
167         return existing;
168     }
169     
170     void remove(RelationInfoQuery entry) {
171         synchronized(relationInfoQueryMap) {
172             relationInfoQueryMap.remove(entry.id);
173         }
174     }
175     
176     public static void runnerRelationInfoQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<RelationInfo> procedure) throws DatabaseException {
177         if(parent == null && listener == null) {
178             RelationInfoQuery.computeForEach(graph, r, null, procedure);
179             return;
180         }
181         QueryCache cache  = graph.processor.cache;
182         if(procedure == null) procedure = emptyProcedureRelationInfoQuery;
183         RelationInfoQuery entry = (RelationInfoQuery)cache.getOrCreateRelationInfoQuery(r);
184         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
185         if(entry.isReady()) entry.performFromCache(graph, procedure);
186         else {
187             RelationInfoQuery.computeForEach(graph, r, entry, procedure);
188             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
189         }
190     }
191     
192     URIToResource getOrCreateURIToResource(String id) throws DatabaseException {
193         URIToResource existing = null;
194         synchronized(uRIToResourceMap) {
195             existing = (URIToResource)uRIToResourceMap.get(id);
196             if(existing == null) {
197                 existing = new URIToResource(id);
198                 existing.clearResult(querySupport);
199                 existing.setPending();
200                 uRIToResourceMap.put(keyID(id), existing);
201                 return existing;
202             }
203             if(existing.requiresComputation()) {
204                 existing.setPending();
205                 return existing;
206             }
207         }
208         if(existing.isPending()) waitPending(existing);
209         return existing;
210     }
211     
212     void remove(URIToResource entry) {
213         synchronized(uRIToResourceMap) {
214             uRIToResourceMap.remove(entry.id);
215         }
216     }
217     
218     public static void runnerURIToResource(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener, InternalProcedure<Integer> procedure) throws DatabaseException {
219         if(parent == null && listener == null) {
220             URIToResource.computeForEach(graph, id, null, procedure);
221             return;
222         }
223         QueryCache cache  = graph.processor.cache;
224         if(procedure == null) procedure = emptyProcedureURIToResource;
225         URIToResource entry = (URIToResource)cache.getOrCreateURIToResource(id);
226         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
227         if(entry.isReady()) entry.performFromCache(graph, procedure);
228         else {
229             URIToResource.computeForEach(graph, id, entry, procedure);
230             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
231         }
232     }
233     
234     ValueQuery getOrCreateValueQuery(int r) throws DatabaseException {
235         ValueQuery existing = null;
236         synchronized(valueQueryMap) {
237             existing = (ValueQuery)valueQueryMap.get(r);
238             if(existing == null) {
239                 existing = new ValueQuery(r);
240                 existing.clearResult(querySupport);
241                 existing.setPending();
242                 valueQueryMap.put(keyR(r), existing);
243                 return existing;
244             }
245             if(existing.requiresComputation()) {
246                 existing.setPending();
247                 return existing;
248             }
249         }
250         if(existing.isPending()) waitPending(existing);
251         return existing;
252     }
253     
254     void remove(ValueQuery entry) {
255         synchronized(valueQueryMap) {
256             valueQueryMap.remove(entry.id);
257         }
258     }
259     
260     public static void runnerValueQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<byte[]> procedure) throws DatabaseException {
261         if(parent == null && listener == null) {
262             ValueQuery.computeForEach(graph, r, null, procedure);
263             return;
264         }
265         QueryCache cache  = graph.processor.cache;
266         if(procedure == null) procedure = emptyProcedureValueQuery;
267         ValueQuery entry = (ValueQuery)cache.getOrCreateValueQuery(r);
268         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
269         if(entry.isReady()) entry.performFromCache(graph, procedure);
270         else {
271             ValueQuery.computeForEach(graph, r, entry, procedure);
272             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
273         }
274     }
275     
276     OrderedSet getOrCreateOrderedSet(int r) throws DatabaseException {
277         OrderedSet existing = null;
278         synchronized(orderedSetMap) {
279             existing = (OrderedSet)orderedSetMap.get(r);
280             if(existing == null) {
281                 existing = new OrderedSet(r);
282                 existing.clearResult(querySupport);
283                 existing.setPending();
284                 orderedSetMap.put(keyR(r), existing);
285                 return existing;
286             }
287             if(existing.requiresComputation()) {
288                 existing.setPending();
289                 return existing;
290             }
291         }
292         if(existing.isPending()) waitPending(existing);
293         return existing;
294     }
295     
296     void remove(OrderedSet entry) {
297         synchronized(orderedSetMap) {
298             orderedSetMap.remove(entry.id);
299         }
300     }
301     
302     public static void runnerOrderedSet(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
303         if(parent == null && listener == null) {
304             OrderedSet.computeForEach(graph, r, null, procedure);
305             return;
306         }
307         QueryCache cache  = graph.processor.cache;
308         if(procedure == null) procedure = emptyProcedureOrderedSet;
309         OrderedSet entry = (OrderedSet)cache.getOrCreateOrderedSet(r);
310         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
311         if(entry.isReady()) entry.performFromCache(graph, procedure);
312         else {
313             OrderedSet.computeForEach(graph, r, entry, procedure);
314             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
315         }
316     }
317     
318     PrincipalTypes getOrCreatePrincipalTypes(int r) throws DatabaseException {
319         PrincipalTypes existing = null;
320         synchronized(principalTypesMap) {
321             existing = (PrincipalTypes)principalTypesMap.get(r);
322             if(existing == null) {
323                 existing = new PrincipalTypes(r);
324                 existing.clearResult(querySupport);
325                 existing.setPending();
326                 principalTypesMap.put(keyR(r), existing);
327                 return existing;
328             }
329             if(existing.requiresComputation()) {
330                 existing.setPending();
331                 return existing;
332             }
333         }
334         if(existing.isPending()) waitPending(existing);
335         return existing;
336     }
337     
338     void remove(PrincipalTypes entry) {
339         synchronized(principalTypesMap) {
340             principalTypesMap.remove(entry.id);
341         }
342     }
343     
344     public static void runnerPrincipalTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
345         if(parent == null && listener == null) {
346             PrincipalTypes.computeForEach(graph, r, null, procedure);
347             return;
348         }
349         QueryCache cache  = graph.processor.cache;
350         if(procedure == null) procedure = emptyProcedurePrincipalTypes;
351         PrincipalTypes entry = (PrincipalTypes)cache.getOrCreatePrincipalTypes(r);
352         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
353         if(entry.isReady()) entry.performFromCache(graph, procedure);
354         else {
355             PrincipalTypes.computeForEach(graph, r, entry, procedure);
356             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
357         }
358     }
359     
360     DirectPredicates getOrCreateDirectPredicates(int r) throws DatabaseException {
361         DirectPredicates existing = null;
362         synchronized(directPredicatesMap) {
363             existing = (DirectPredicates)directPredicatesMap.get(r);
364             if(existing == null) {
365                 existing = new DirectPredicates(r);
366                 existing.clearResult(querySupport);
367                 existing.setPending();
368                 directPredicatesMap.put(keyR(r), existing);
369                 return existing;
370             }
371             if(existing.requiresComputation()) {
372                 existing.setPending();
373                 return existing;
374             }
375         }
376         if(existing.isPending()) waitPending(existing);
377         return existing;
378     }
379     
380     void remove(DirectPredicates entry) {
381         synchronized(directPredicatesMap) {
382             directPredicatesMap.remove(entry.id);
383         }
384     }
385     
386     public static void runnerDirectPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
387         if(parent == null && listener == null) {
388             DirectPredicates.computeForEach(graph, r, null, procedure);
389             return;
390         }
391         QueryCache cache  = graph.processor.cache;
392         if(procedure == null) procedure = emptyProcedureDirectPredicates;
393         DirectPredicates entry = (DirectPredicates)cache.getOrCreateDirectPredicates(r);
394         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
395         if(entry.isReady()) entry.performFromCache(graph, procedure);
396         else {
397             DirectPredicates.computeForEach(graph, r, entry, procedure);
398             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
399         }
400     }
401     
402     Predicates getOrCreatePredicates(int r) throws DatabaseException {
403         Predicates existing = null;
404         synchronized(predicatesMap) {
405             existing = (Predicates)predicatesMap.get(r);
406             if(existing == null) {
407                 existing = new Predicates(r);
408                 existing.clearResult(querySupport);
409                 existing.setPending();
410                 predicatesMap.put(keyR(r), existing);
411                 return existing;
412             }
413             if(existing.requiresComputation()) {
414                 existing.setPending();
415                 return existing;
416             }
417         }
418         if(existing.isPending()) waitPending(existing);
419         return existing;
420     }
421     
422     void remove(Predicates entry) {
423         synchronized(predicatesMap) {
424             predicatesMap.remove(entry.id);
425         }
426     }
427     
428     public static void runnerPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
429         if(parent == null && listener == null) {
430             Predicates.computeForEach(graph, r, null, procedure);
431             return;
432         }
433         QueryCache cache  = graph.processor.cache;
434         if(procedure == null) procedure = emptyProcedurePredicates;
435         Predicates entry = (Predicates)cache.getOrCreatePredicates(r);
436         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
437         if(entry.isReady()) entry.performFromCache(graph, procedure);
438         else {
439             Predicates.computeForEach(graph, r, entry, procedure);
440             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
441         }
442     }
443     
444     ReadEntry getOrCreateReadEntry(Read<?> r) throws DatabaseException {
445         ReadEntry existing = null;
446         synchronized(readEntryMap) {
447             existing = (ReadEntry)readEntryMap.get(r);
448             if(existing == null) {
449                 existing = new ReadEntry(r);
450                 existing.clearResult(querySupport);
451                 existing.setPending();
452                 readEntryMap.put(id(r), existing);
453                 return existing;
454             }
455             if(existing.requiresComputation()) {
456                 existing.setPending();
457                 return existing;
458             }
459         }
460         if(existing.isPending()) waitPending(existing);
461         return existing;
462     }
463     
464     void remove(ReadEntry entry) {
465         synchronized(readEntryMap) {
466             readEntryMap.remove(entry.request);
467         }
468     }
469     
470     public static void runnerReadEntry(ReadGraphImpl graph, Read<?> r, CacheEntry parent, ListenerBase listener, AsyncProcedure procedure) throws DatabaseException {
471         if(parent == null && listener == null) {
472             ReadEntry.computeForEach(graph, r, null, procedure);
473             return;
474         }
475         QueryCache cache  = graph.processor.cache;
476         if(procedure == null) procedure = emptyProcedureReadEntry;
477         ReadEntry entry = (ReadEntry)cache.getOrCreateReadEntry(r);
478         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
479         if(entry.isReady()) entry.performFromCache(graph, procedure);
480         else {
481             ReadEntry.computeForEach(graph, r, entry, procedure);
482             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
483         }
484     }
485     
486     AsyncReadEntry getOrCreateAsyncReadEntry(AsyncRead<?> r) throws DatabaseException {
487         AsyncReadEntry existing = null;
488         synchronized(asyncReadEntryMap) {
489             existing = (AsyncReadEntry)asyncReadEntryMap.get(r);
490             if(existing == null) {
491                 existing = new AsyncReadEntry(r);
492                 existing.clearResult(querySupport);
493                 existing.setPending();
494                 asyncReadEntryMap.put(id(r), existing);
495                 return existing;
496             }
497             if(existing.requiresComputation()) {
498                 existing.setPending();
499                 return existing;
500             }
501         }
502         if(existing.isPending()) waitPending(existing);
503         return existing;
504     }
505     
506     void remove(AsyncReadEntry entry) {
507         synchronized(asyncReadEntryMap) {
508             asyncReadEntryMap.remove(entry.request);
509         }
510     }
511     
512     public static void runnerAsyncReadEntry(ReadGraphImpl graph, AsyncRead<?> r, CacheEntry parent, ListenerBase listener, AsyncProcedure procedure) throws DatabaseException {
513         if(parent == null && listener == null) {
514             AsyncReadEntry.computeForEach(graph, r, null, procedure);
515             return;
516         }
517         QueryCache cache  = graph.processor.cache;
518         if(procedure == null) procedure = emptyProcedureAsyncReadEntry;
519         AsyncReadEntry entry = (AsyncReadEntry)cache.getOrCreateAsyncReadEntry(r);
520         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
521         if(entry.isReady()) entry.performFromCache(graph, procedure);
522         else {
523             AsyncReadEntry.computeForEach(graph, r, entry, procedure);
524             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
525         }
526     }
527     
528     Types getOrCreateTypes(int r) throws DatabaseException {
529         Types existing = null;
530         synchronized(typesMap) {
531             existing = (Types)typesMap.get(r);
532             if(existing == null) {
533                 existing = new Types(r);
534                 existing.clearResult(querySupport);
535                 existing.setPending();
536                 typesMap.put(keyR(r), existing);
537                 return existing;
538             }
539             if(existing.requiresComputation()) {
540                 existing.setPending();
541                 return existing;
542             }
543         }
544         if(existing.isPending()) waitPending(existing);
545         return existing;
546     }
547     
548     void remove(Types entry) {
549         synchronized(typesMap) {
550             typesMap.remove(entry.id);
551         }
552     }
553     
554     public static void runnerTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
555         if(parent == null && listener == null) {
556             Types.computeForEach(graph, r, null, procedure);
557             return;
558         }
559         QueryCache cache  = graph.processor.cache;
560         if(procedure == null) procedure = emptyProcedureTypes;
561         Types entry = (Types)cache.getOrCreateTypes(r);
562         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
563         if(entry.isReady()) entry.performFromCache(graph, procedure);
564         else {
565             Types.computeForEach(graph, r, entry, procedure);
566             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
567         }
568     }
569     
570     NamespaceIndex getOrCreateNamespaceIndex(String id) throws DatabaseException {
571         NamespaceIndex existing = null;
572         synchronized(namespaceIndexMap) {
573             existing = (NamespaceIndex)namespaceIndexMap.get(id);
574             if(existing == null) {
575                 existing = new NamespaceIndex(id);
576                 existing.clearResult(querySupport);
577                 existing.setPending();
578                 namespaceIndexMap.put(keyID(id), existing);
579                 return existing;
580             }
581             if(existing.requiresComputation()) {
582                 existing.setPending();
583                 return existing;
584             }
585         }
586         if(existing.isPending()) waitPending(existing);
587         return existing;
588     }
589     
590     void remove(NamespaceIndex entry) {
591         synchronized(namespaceIndexMap) {
592             namespaceIndexMap.remove(entry.id);
593         }
594     }
595     
596     public static void runnerNamespaceIndex(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener, InternalProcedure<TObjectIntHashMap<String>> procedure) throws DatabaseException {
597         if(parent == null && listener == null) {
598             NamespaceIndex.computeForEach(graph, id, null, procedure);
599             return;
600         }
601         QueryCache cache  = graph.processor.cache;
602         if(procedure == null) procedure = emptyProcedureNamespaceIndex;
603         NamespaceIndex entry = (NamespaceIndex)cache.getOrCreateNamespaceIndex(id);
604         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
605         if(entry.isReady()) entry.performFromCache(graph, procedure);
606         else {
607             NamespaceIndex.computeForEach(graph, id, entry, procedure);
608             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
609         }
610     }
611     
612     AssertedStatements getOrCreateAssertedStatements(int r1, int r2) throws DatabaseException {
613         AssertedStatements existing = null;
614         synchronized(assertedStatementsMap) {
615             existing = (AssertedStatements)assertedStatementsMap.get(r1,r2);
616             if(existing == null) {
617                 existing = new AssertedStatements(r1,r2);
618                 existing.clearResult(querySupport);
619                 existing.setPending();
620                 assertedStatementsMap.put(keyR2(r1,r2), existing);
621                 return existing;
622             }
623             if(existing.requiresComputation()) {
624                 existing.setPending();
625                 return existing;
626             }
627         }
628         if(existing.isPending()) waitPending(existing);
629         return existing;
630     }
631     
632     void remove(AssertedStatements entry) {
633         synchronized(assertedStatementsMap) {
634             assertedStatementsMap.remove(entry.id);
635         }
636     }
637     
638     public static void runnerAssertedStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, TripleIntProcedure procedure) throws DatabaseException {
639         QueryCache cache  = graph.processor.cache;
640         if(procedure == null) procedure = emptyProcedureAssertedStatements;
641         AssertedStatements entry = (AssertedStatements)cache.getOrCreateAssertedStatements(r1,r2);
642         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
643         if(entry.isReady()) entry.performFromCache(graph, procedure);
644         else {
645             entry.compute(graph, procedure);
646             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
647         }
648     }
649     
650     AssertedPredicates getOrCreateAssertedPredicates(int r) throws DatabaseException {
651         AssertedPredicates existing = null;
652         synchronized(assertedPredicatesMap) {
653             existing = (AssertedPredicates)assertedPredicatesMap.get(r);
654             if(existing == null) {
655                 existing = new AssertedPredicates(r);
656                 existing.clearResult(querySupport);
657                 existing.setPending();
658                 assertedPredicatesMap.put(keyR(r), existing);
659                 return existing;
660             }
661             if(existing.requiresComputation()) {
662                 existing.setPending();
663                 return existing;
664             }
665         }
666         if(existing.isPending()) waitPending(existing);
667         return existing;
668     }
669     
670     void remove(AssertedPredicates entry) {
671         synchronized(assertedPredicatesMap) {
672             assertedPredicatesMap.remove(entry.id);
673         }
674     }
675     
676     public static void runnerAssertedPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
677         QueryCache cache  = graph.processor.cache;
678         if(procedure == null) procedure = emptyProcedureAssertedPredicates;
679         AssertedPredicates entry = (AssertedPredicates)cache.getOrCreateAssertedPredicates(r);
680         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
681         if(entry.isReady()) entry.performFromCache(graph, procedure);
682         else {
683             entry.compute(graph, procedure);
684             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
685         }
686     }
687     
688     DirectSuperRelations getOrCreateDirectSuperRelations(int r) throws DatabaseException {
689         DirectSuperRelations existing = null;
690         synchronized(directSuperRelationsMap) {
691             existing = (DirectSuperRelations)directSuperRelationsMap.get(r);
692             if(existing == null) {
693                 existing = new DirectSuperRelations(r);
694                 existing.clearResult(querySupport);
695                 existing.setPending();
696                 directSuperRelationsMap.put(keyR(r), existing);
697                 return existing;
698             }
699             if(existing.requiresComputation()) {
700                 existing.setPending();
701                 return existing;
702             }
703         }
704         if(existing.isPending()) waitPending(existing);
705         return existing;
706     }
707     
708     void remove(DirectSuperRelations entry) {
709         synchronized(directSuperRelationsMap) {
710             directSuperRelationsMap.remove(entry.id);
711         }
712     }
713     
714     public static void runnerDirectSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
715         QueryCache cache  = graph.processor.cache;
716         if(procedure == null) procedure = emptyProcedureDirectSuperRelations;
717         DirectSuperRelations entry = (DirectSuperRelations)cache.getOrCreateDirectSuperRelations(r);
718         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
719         if(entry.isReady()) entry.performFromCache(graph, procedure);
720         else {
721             entry.compute(graph, procedure);
722             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
723         }
724     }
725     
726     SuperTypes getOrCreateSuperTypes(int r) throws DatabaseException {
727         SuperTypes existing = null;
728         synchronized(superTypesMap) {
729             existing = (SuperTypes)superTypesMap.get(r);
730             if(existing == null) {
731                 existing = new SuperTypes(r);
732                 existing.clearResult(querySupport);
733                 existing.setPending();
734                 superTypesMap.put(keyR(r), existing);
735                 return existing;
736             }
737             if(existing.requiresComputation()) {
738                 existing.setPending();
739                 return existing;
740             }
741         }
742         if(existing.isPending()) waitPending(existing);
743         return existing;
744     }
745     
746     void remove(SuperTypes entry) {
747         synchronized(superTypesMap) {
748             superTypesMap.remove(entry.id);
749         }
750     }
751     
752     public static void runnerSuperTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
753         QueryCache cache  = graph.processor.cache;
754         if(procedure == null) procedure = emptyProcedureSuperTypes;
755         SuperTypes entry = (SuperTypes)cache.getOrCreateSuperTypes(r);
756         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
757         if(entry.isReady()) entry.performFromCache(graph, procedure);
758         else {
759             entry.compute(graph, procedure);
760             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
761         }
762     }
763     
764     TypeHierarchy getOrCreateTypeHierarchy(int r) throws DatabaseException {
765         TypeHierarchy existing = null;
766         synchronized(typeHierarchyMap) {
767             existing = (TypeHierarchy)typeHierarchyMap.get(r);
768             if(existing == null) {
769                 existing = new TypeHierarchy(r);
770                 existing.clearResult(querySupport);
771                 existing.setPending();
772                 typeHierarchyMap.put(keyR(r), existing);
773                 return existing;
774             }
775             if(existing.requiresComputation()) {
776                 existing.setPending();
777                 return existing;
778             }
779         }
780         if(existing.isPending()) waitPending(existing);
781         return existing;
782     }
783     
784     void remove(TypeHierarchy entry) {
785         synchronized(typeHierarchyMap) {
786             typeHierarchyMap.remove(entry.id);
787         }
788     }
789     
790     public static void runnerTypeHierarchy(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
791         QueryCache cache  = graph.processor.cache;
792         if(procedure == null) procedure = emptyProcedureTypeHierarchy;
793         TypeHierarchy entry = (TypeHierarchy)cache.getOrCreateTypeHierarchy(r);
794         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
795         if(entry.isReady()) entry.performFromCache(graph, procedure);
796         else {
797             entry.compute(graph, procedure);
798             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
799         }
800     }
801     
802     SuperRelations getOrCreateSuperRelations(int r) throws DatabaseException {
803         SuperRelations existing = null;
804         synchronized(superRelationsMap) {
805             existing = (SuperRelations)superRelationsMap.get(r);
806             if(existing == null) {
807                 existing = new SuperRelations(r);
808                 existing.clearResult(querySupport);
809                 existing.setPending();
810                 superRelationsMap.put(keyR(r), existing);
811                 return existing;
812             }
813             if(existing.requiresComputation()) {
814                 existing.setPending();
815                 return existing;
816             }
817         }
818         if(existing.isPending()) waitPending(existing);
819         return existing;
820     }
821     
822     void remove(SuperRelations entry) {
823         synchronized(superRelationsMap) {
824             superRelationsMap.remove(entry.id);
825         }
826     }
827     
828     public static void runnerSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
829         QueryCache cache  = graph.processor.cache;
830         if(procedure == null) procedure = emptyProcedureSuperRelations;
831         SuperRelations entry = (SuperRelations)cache.getOrCreateSuperRelations(r);
832         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
833         if(entry.isReady()) entry.performFromCache(graph, procedure);
834         else {
835             entry.compute(graph, procedure);
836             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
837         }
838     }
839     
840     MultiReadEntry getOrCreateMultiReadEntry(MultiRead<?> r) throws DatabaseException {
841         MultiReadEntry existing = null;
842         synchronized(multiReadEntryMap) {
843             existing = (MultiReadEntry)multiReadEntryMap.get(r);
844             if(existing == null) {
845                 existing = new MultiReadEntry(r);
846                 existing.clearResult(querySupport);
847                 existing.setPending();
848                 multiReadEntryMap.put(id(r), existing);
849                 return existing;
850             }
851             if(existing.requiresComputation()) {
852                 existing.setPending();
853                 return existing;
854             }
855         }
856         if(existing.isPending()) waitPending(existing);
857         return existing;
858     }
859     
860     void remove(MultiReadEntry entry) {
861         synchronized(multiReadEntryMap) {
862             multiReadEntryMap.remove(entry.request);
863         }
864     }
865     
866     public static void runnerMultiReadEntry(ReadGraphImpl graph, MultiRead<?> r, CacheEntry parent, ListenerBase listener, AsyncMultiProcedure procedure) throws DatabaseException {
867         QueryCache cache  = graph.processor.cache;
868         if(procedure == null) procedure = emptyProcedureMultiReadEntry;
869         MultiReadEntry entry = (MultiReadEntry)cache.getOrCreateMultiReadEntry(r);
870         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
871         if(entry.isReady()) entry.performFromCache(graph, procedure);
872         else {
873             entry.compute(graph, procedure);
874             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
875         }
876     }
877     
878     AsyncMultiReadEntry getOrCreateAsyncMultiReadEntry(AsyncMultiRead<?> r) throws DatabaseException {
879         AsyncMultiReadEntry existing = null;
880         synchronized(asyncMultiReadEntryMap) {
881             existing = (AsyncMultiReadEntry)asyncMultiReadEntryMap.get(r);
882             if(existing == null) {
883                 existing = new AsyncMultiReadEntry(r);
884                 existing.clearResult(querySupport);
885                 existing.setPending();
886                 asyncMultiReadEntryMap.put(id(r), existing);
887                 return existing;
888             }
889             if(existing.requiresComputation()) {
890                 existing.setPending();
891                 return existing;
892             }
893         }
894         if(existing.isPending()) waitPending(existing);
895         return existing;
896     }
897     
898     void remove(AsyncMultiReadEntry entry) {
899         synchronized(asyncMultiReadEntryMap) {
900             asyncMultiReadEntryMap.remove(entry.request);
901         }
902     }
903     
904     public static void runnerAsyncMultiReadEntry(ReadGraphImpl graph, AsyncMultiRead<?> r, CacheEntry parent, ListenerBase listener, AsyncMultiProcedure procedure) throws DatabaseException {
905         QueryCache cache  = graph.processor.cache;
906         if(procedure == null) procedure = emptyProcedureAsyncMultiReadEntry;
907         AsyncMultiReadEntry entry = (AsyncMultiReadEntry)cache.getOrCreateAsyncMultiReadEntry(r);
908         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
909         if(entry.isReady()) entry.performFromCache(graph, procedure);
910         else {
911             entry.compute(graph, procedure);
912             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
913         }
914     }
915     
916     ExternalReadEntry getOrCreateExternalReadEntry(ExternalRead<?> r) throws DatabaseException {
917         ExternalReadEntry existing = null;
918         synchronized(externalReadEntryMap) {
919             existing = (ExternalReadEntry)externalReadEntryMap.get(r);
920             if(existing == null) {
921                 existing = new ExternalReadEntry(r);
922                 existing.clearResult(querySupport);
923                 existing.setPending();
924                 externalReadEntryMap.put(id(r), existing);
925                 return existing;
926             }
927             if(existing.requiresComputation()) {
928                 existing.setPending();
929                 return existing;
930             }
931         }
932         if(existing.isPending()) waitPending(existing);
933         return existing;
934     }
935     
936     void remove(ExternalReadEntry entry) {
937         synchronized(externalReadEntryMap) {
938             externalReadEntryMap.remove(entry.request);
939         }
940     }
941     
942     public static void runnerExternalReadEntry(ReadGraphImpl graph, ExternalRead<?> r, CacheEntry parent, ListenerBase listener, AsyncProcedure procedure) throws DatabaseException {
943         QueryCache cache  = graph.processor.cache;
944         if(procedure == null) procedure = emptyProcedureExternalReadEntry;
945         ExternalReadEntry entry = (ExternalReadEntry)cache.getOrCreateExternalReadEntry(r);
946         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
947         if(entry.isReady()) entry.performFromCache(graph, procedure);
948         else {
949             entry.compute(graph, procedure);
950             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
951         }
952     }
953     
954 }