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