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