]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCache.java
7b591abb7fd80e062308ce3df88c86e872cfe27e
[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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, 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(processor, 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.processor, 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(QueryProcessor processor, Read<?> r, boolean isSync) 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(isSync) waitPending(processor, 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 void runnerReadEntry(ReadGraphImpl graph, Read<?> r, CacheEntry parent, ListenerBase listener, final AsyncProcedure procedure, boolean isSync) throws DatabaseException {
497         QueryCache cache  = graph.processor.cache;
498         if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
499             ReadEntry.computeForEach(graph, r, null, procedure);
500             return;
501         }
502         ReadEntry entry = (ReadEntry)cache.getOrCreateReadEntry(graph.processor, r, isSync);
503         if(entry == null) {
504             graph.processor.schedule(new SessionTask(false) {
505                 @Override
506                 public void run(int thread) {
507                     try {
508                         assert(!isSync);
509                         runnerReadEntry(graph, r, parent, listener, procedure, isSync);
510                     } catch (DatabaseException e) {
511                         Logger.defaultLogError(e);
512                     }
513                 }
514             });
515             return;
516         }
517         AsyncProcedure procedure_ = procedure != null ? procedure : emptyProcedureReadEntry;
518         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
519         if(entry.isReady()) entry.performFromCache(graph, procedure_);
520         else {
521           assert(entry.isPending());
522             ReadEntry.computeForEach(graph, r, entry, procedure_);
523             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
524         }
525     }
526     
527     AsyncReadEntry getOrCreateAsyncReadEntry(QueryProcessor processor, AsyncRead<?> r, boolean isSync) throws DatabaseException {
528         AsyncReadEntry existing = null;
529         synchronized(asyncReadEntryMap) {
530             existing = (AsyncReadEntry)asyncReadEntryMap.get(r);
531             if(existing == null) {
532                 existing = new AsyncReadEntry(r);
533                 existing.clearResult(querySupport);
534                 existing.setPending();
535                 asyncReadEntryMap.put(id(r), existing);
536                 size++;
537                 return existing;
538             }
539             if(existing.requiresComputation()) {
540                 existing.setPending();
541                 return existing;
542             }
543         }
544         if(existing.isPending()) {
545           if(isSync) waitPending(processor, existing);
546           else return null;
547         }
548         return existing;
549     }
550     
551     void remove(AsyncReadEntry entry) {
552         synchronized(asyncReadEntryMap) {
553             asyncReadEntryMap.remove(entry.request);
554         }
555     }
556     
557     public static void runnerAsyncReadEntry(ReadGraphImpl graph, AsyncRead<?> r, CacheEntry parent, ListenerBase listener, final AsyncProcedure procedure, boolean isSync) throws DatabaseException {
558         QueryCache cache  = graph.processor.cache;
559         if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
560             AsyncReadEntry.computeForEach(graph, r, null, procedure);
561             return;
562         }
563         AsyncReadEntry entry = (AsyncReadEntry)cache.getOrCreateAsyncReadEntry(graph.processor, r, isSync);
564         if(entry == null) {
565             graph.processor.schedule(new SessionTask(false) {
566                 @Override
567                 public void run(int thread) {
568                     try {
569                         assert(!isSync);
570                         runnerAsyncReadEntry(graph, r, parent, listener, procedure, isSync);
571                     } catch (DatabaseException e) {
572                         Logger.defaultLogError(e);
573                     }
574                 }
575             });
576             return;
577         }
578         AsyncProcedure procedure_ = procedure != null ? procedure : emptyProcedureAsyncReadEntry;
579         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
580         if(entry.isReady()) entry.performFromCache(graph, procedure_);
581         else {
582           assert(entry.isPending());
583             AsyncReadEntry.computeForEach(graph, r, entry, procedure_);
584             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
585         }
586     }
587     
588     Types getOrCreateTypes(QueryProcessor processor, int r) throws DatabaseException {
589         Types existing = null;
590         synchronized(typesMap) {
591             existing = (Types)typesMap.get(r);
592             if(existing == null) {
593                 existing = new Types(r);
594                 existing.clearResult(querySupport);
595                 existing.setPending();
596                 typesMap.put(keyR(r), existing);
597                 size++;
598                 return existing;
599             }
600             if(existing.requiresComputation()) {
601                 existing.setPending();
602                 return existing;
603             }
604         }
605         if(existing.isPending()) waitPending(processor, existing);
606         return existing;
607     }
608     
609     void remove(Types entry) {
610         synchronized(typesMap) {
611             typesMap.remove(entry.id);
612         }
613     }
614     
615     public static void runnerTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, final InternalProcedure<IntSet> procedure) throws DatabaseException {
616         QueryCache cache  = graph.processor.cache;
617         if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
618             Types.computeForEach(graph, r, null, procedure);
619             return;
620         }
621         Types entry = (Types)cache.getOrCreateTypes(graph.processor, r);
622         InternalProcedure<IntSet> procedure_ = procedure != null ? procedure : emptyProcedureTypes;
623         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
624         if(entry.isReady()) entry.performFromCache(graph, procedure_);
625         else {
626           assert(entry.isPending());
627             Types.computeForEach(graph, r, entry, procedure_);
628             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
629         }
630     }
631     
632     ChildMap getOrCreateChildMap(QueryProcessor processor, int r) throws DatabaseException {
633         ChildMap existing = null;
634         synchronized(childMapMap) {
635             existing = (ChildMap)childMapMap.get(r);
636             if(existing == null) {
637                 existing = new ChildMap(r);
638                 existing.clearResult(querySupport);
639                 existing.setPending();
640                 childMapMap.put(keyR(r), existing);
641                 size++;
642                 return existing;
643             }
644             if(existing.requiresComputation()) {
645                 existing.setPending();
646                 return existing;
647             }
648         }
649         if(existing.isPending()) waitPending(processor, existing);
650         return existing;
651     }
652     
653     void remove(ChildMap entry) {
654         synchronized(childMapMap) {
655             childMapMap.remove(entry.id);
656         }
657     }
658     
659     public static void runnerChildMap(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, final InternalProcedure<ObjectResourceIdMap<String>> procedure) throws DatabaseException {
660         QueryCache cache  = graph.processor.cache;
661         if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
662             ChildMap.computeForEach(graph, r, null, procedure);
663             return;
664         }
665         ChildMap entry = (ChildMap)cache.getOrCreateChildMap(graph.processor, r);
666         InternalProcedure<ObjectResourceIdMap<String>> procedure_ = procedure != null ? procedure : emptyProcedureChildMap;
667         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
668         if(entry.isReady()) entry.performFromCache(graph, procedure_);
669         else {
670           assert(entry.isPending());
671             ChildMap.computeForEach(graph, r, entry, procedure_);
672             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
673         }
674     }
675     
676     TypeHierarchy getOrCreateTypeHierarchy(QueryProcessor processor, int r) throws DatabaseException {
677         TypeHierarchy existing = null;
678         synchronized(typeHierarchyMap) {
679             existing = (TypeHierarchy)typeHierarchyMap.get(r);
680             if(existing == null) {
681                 existing = new TypeHierarchy(r);
682                 existing.clearResult(querySupport);
683                 existing.setPending();
684                 typeHierarchyMap.put(keyR(r), existing);
685                 size++;
686                 return existing;
687             }
688             if(existing.requiresComputation()) {
689                 existing.setPending();
690                 return existing;
691             }
692         }
693         if(existing.isPending()) waitPending(processor, existing);
694         return existing;
695     }
696     
697     void remove(TypeHierarchy entry) {
698         synchronized(typeHierarchyMap) {
699             typeHierarchyMap.remove(entry.id);
700         }
701     }
702     
703     public static void runnerTypeHierarchy(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, final InternalProcedure<IntSet> procedure) throws DatabaseException {
704         QueryCache cache  = graph.processor.cache;
705         if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
706             TypeHierarchy.computeForEach(graph, r, null, procedure);
707             return;
708         }
709         TypeHierarchy entry = (TypeHierarchy)cache.getOrCreateTypeHierarchy(graph.processor, r);
710         InternalProcedure<IntSet> procedure_ = procedure != null ? procedure : emptyProcedureTypeHierarchy;
711         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
712         if(entry.isReady()) entry.performFromCache(graph, procedure_);
713         else {
714           assert(entry.isPending());
715             TypeHierarchy.computeForEach(graph, r, entry, procedure_);
716             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
717         }
718     }
719     
720     SuperTypes getOrCreateSuperTypes(QueryProcessor processor, int r) throws DatabaseException {
721         SuperTypes existing = null;
722         synchronized(superTypesMap) {
723             existing = (SuperTypes)superTypesMap.get(r);
724             if(existing == null) {
725                 existing = new SuperTypes(r);
726                 existing.clearResult(querySupport);
727                 existing.setPending();
728                 superTypesMap.put(keyR(r), existing);
729                 size++;
730                 return existing;
731             }
732             if(existing.requiresComputation()) {
733                 existing.setPending();
734                 return existing;
735             }
736         }
737         if(existing.isPending()) waitPending(processor, existing);
738         return existing;
739     }
740     
741     void remove(SuperTypes entry) {
742         synchronized(superTypesMap) {
743             superTypesMap.remove(entry.id);
744         }
745     }
746     
747     public static void runnerSuperTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, final InternalProcedure<IntSet> procedure) throws DatabaseException {
748         QueryCache cache  = graph.processor.cache;
749         if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
750             SuperTypes.computeForEach(graph, r, null, procedure);
751             return;
752         }
753         SuperTypes entry = (SuperTypes)cache.getOrCreateSuperTypes(graph.processor, r);
754         InternalProcedure<IntSet> procedure_ = procedure != null ? procedure : emptyProcedureSuperTypes;
755         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
756         if(entry.isReady()) entry.performFromCache(graph, procedure_);
757         else {
758           assert(entry.isPending());
759             SuperTypes.computeForEach(graph, r, entry, procedure_);
760             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
761         }
762     }
763     
764     SuperRelations getOrCreateSuperRelations(QueryProcessor processor, int r) throws DatabaseException {
765         SuperRelations existing = null;
766         synchronized(superRelationsMap) {
767             existing = (SuperRelations)superRelationsMap.get(r);
768             if(existing == null) {
769                 existing = new SuperRelations(r);
770                 existing.clearResult(querySupport);
771                 existing.setPending();
772                 superRelationsMap.put(keyR(r), existing);
773                 size++;
774                 return existing;
775             }
776             if(existing.requiresComputation()) {
777                 existing.setPending();
778                 return existing;
779             }
780         }
781         if(existing.isPending()) waitPending(processor, existing);
782         return existing;
783     }
784     
785     void remove(SuperRelations entry) {
786         synchronized(superRelationsMap) {
787             superRelationsMap.remove(entry.id);
788         }
789     }
790     
791     public static void runnerSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, final InternalProcedure<IntSet> procedure) throws DatabaseException {
792         QueryCache cache  = graph.processor.cache;
793         if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
794             SuperRelations.computeForEach(graph, r, null, procedure);
795             return;
796         }
797         SuperRelations entry = (SuperRelations)cache.getOrCreateSuperRelations(graph.processor, r);
798         InternalProcedure<IntSet> procedure_ = procedure != null ? procedure : emptyProcedureSuperRelations;
799         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
800         if(entry.isReady()) entry.performFromCache(graph, procedure_);
801         else {
802           assert(entry.isPending());
803             SuperRelations.computeForEach(graph, r, entry, procedure_);
804             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
805         }
806     }
807     
808     AssertedPredicates getOrCreateAssertedPredicates(QueryProcessor processor, int r) throws DatabaseException {
809         AssertedPredicates existing = null;
810         synchronized(assertedPredicatesMap) {
811             existing = (AssertedPredicates)assertedPredicatesMap.get(r);
812             if(existing == null) {
813                 existing = new AssertedPredicates(r);
814                 existing.clearResult(querySupport);
815                 existing.setPending();
816                 assertedPredicatesMap.put(keyR(r), existing);
817                 size++;
818                 return existing;
819             }
820             if(existing.requiresComputation()) {
821                 existing.setPending();
822                 return existing;
823             }
824         }
825         if(existing.isPending()) waitPending(processor, existing);
826         return existing;
827     }
828     
829     void remove(AssertedPredicates entry) {
830         synchronized(assertedPredicatesMap) {
831             assertedPredicatesMap.remove(entry.id);
832         }
833     }
834     
835     public static void runnerAssertedPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, final IntProcedure procedure) throws DatabaseException {
836         QueryCache cache  = graph.processor.cache;
837         AssertedPredicates entry = (AssertedPredicates)cache.getOrCreateAssertedPredicates(graph.processor, r);
838         IntProcedure procedure_ = procedure != null ? procedure : emptyProcedureAssertedPredicates;
839         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
840         if(entry.isReady()) entry.performFromCache(graph, procedure_);
841         else {
842           assert(entry.isPending());
843             entry.compute(graph, procedure_);
844             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
845         }
846     }
847     
848     AssertedStatements getOrCreateAssertedStatements(QueryProcessor processor, int r1, int r2) throws DatabaseException {
849         AssertedStatements existing = null;
850         synchronized(assertedStatementsMap) {
851             existing = (AssertedStatements)assertedStatementsMap.get(r1,r2);
852             if(existing == null) {
853                 existing = new AssertedStatements(r1,r2);
854                 existing.clearResult(querySupport);
855                 existing.setPending();
856                 assertedStatementsMap.put(keyR2(r1,r2), existing);
857                 size++;
858                 return existing;
859             }
860             if(existing.requiresComputation()) {
861                 existing.setPending();
862                 return existing;
863             }
864         }
865         if(existing.isPending()) waitPending(processor, existing);
866         return existing;
867     }
868     
869     void remove(AssertedStatements entry) {
870         synchronized(assertedStatementsMap) {
871             assertedStatementsMap.remove(entry.id);
872         }
873     }
874     
875     public static void runnerAssertedStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, final TripleIntProcedure procedure) throws DatabaseException {
876         QueryCache cache  = graph.processor.cache;
877         AssertedStatements entry = (AssertedStatements)cache.getOrCreateAssertedStatements(graph.processor, r1,r2);
878         TripleIntProcedure procedure_ = procedure != null ? procedure : emptyProcedureAssertedStatements;
879         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
880         if(entry.isReady()) entry.performFromCache(graph, procedure_);
881         else {
882           assert(entry.isPending());
883             entry.compute(graph, procedure_);
884             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
885         }
886     }
887     
888     DirectSuperRelations getOrCreateDirectSuperRelations(QueryProcessor processor, int r) throws DatabaseException {
889         DirectSuperRelations existing = null;
890         synchronized(directSuperRelationsMap) {
891             existing = (DirectSuperRelations)directSuperRelationsMap.get(r);
892             if(existing == null) {
893                 existing = new DirectSuperRelations(r);
894                 existing.clearResult(querySupport);
895                 existing.setPending();
896                 directSuperRelationsMap.put(keyR(r), existing);
897                 size++;
898                 return existing;
899             }
900             if(existing.requiresComputation()) {
901                 existing.setPending();
902                 return existing;
903             }
904         }
905         if(existing.isPending()) waitPending(processor, existing);
906         return existing;
907     }
908     
909     void remove(DirectSuperRelations entry) {
910         synchronized(directSuperRelationsMap) {
911             directSuperRelationsMap.remove(entry.id);
912         }
913     }
914     
915     public static void runnerDirectSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, final IntProcedure procedure) throws DatabaseException {
916         QueryCache cache  = graph.processor.cache;
917         DirectSuperRelations entry = (DirectSuperRelations)cache.getOrCreateDirectSuperRelations(graph.processor, r);
918         IntProcedure procedure_ = procedure != null ? procedure : emptyProcedureDirectSuperRelations;
919         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
920         if(entry.isReady()) entry.performFromCache(graph, procedure_);
921         else {
922           assert(entry.isPending());
923             entry.compute(graph, procedure_);
924             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
925         }
926     }
927     
928     MultiReadEntry getOrCreateMultiReadEntry(QueryProcessor processor, MultiRead<?> r) throws DatabaseException {
929         MultiReadEntry existing = null;
930         synchronized(multiReadEntryMap) {
931             existing = (MultiReadEntry)multiReadEntryMap.get(r);
932             if(existing == null) {
933                 existing = new MultiReadEntry(r);
934                 existing.clearResult(querySupport);
935                 existing.setPending();
936                 multiReadEntryMap.put(id(r), existing);
937                 size++;
938                 return existing;
939             }
940             if(existing.requiresComputation()) {
941                 existing.setPending();
942                 return existing;
943             }
944         }
945         if(existing.isPending()) waitPending(processor, existing);
946         return existing;
947     }
948     
949     void remove(MultiReadEntry entry) {
950         synchronized(multiReadEntryMap) {
951             multiReadEntryMap.remove(entry.request);
952         }
953     }
954     
955     public static void runnerMultiReadEntry(ReadGraphImpl graph, MultiRead<?> r, CacheEntry parent, ListenerBase listener, final SyncMultiProcedure procedure) throws DatabaseException {
956         QueryCache cache  = graph.processor.cache;
957         MultiReadEntry entry = (MultiReadEntry)cache.getOrCreateMultiReadEntry(graph.processor, r);
958         SyncMultiProcedure procedure_ = procedure != null ? procedure : emptyProcedureMultiReadEntry;
959         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
960         if(entry.isReady()) entry.performFromCache(graph, procedure_);
961         else {
962           assert(entry.isPending());
963             entry.compute(graph, procedure_);
964             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
965         }
966     }
967     
968     AsyncMultiReadEntry getOrCreateAsyncMultiReadEntry(QueryProcessor processor, AsyncMultiRead<?> r) throws DatabaseException {
969         AsyncMultiReadEntry existing = null;
970         synchronized(asyncMultiReadEntryMap) {
971             existing = (AsyncMultiReadEntry)asyncMultiReadEntryMap.get(r);
972             if(existing == null) {
973                 existing = new AsyncMultiReadEntry(r);
974                 existing.clearResult(querySupport);
975                 existing.setPending();
976                 asyncMultiReadEntryMap.put(id(r), existing);
977                 size++;
978                 return existing;
979             }
980             if(existing.requiresComputation()) {
981                 existing.setPending();
982                 return existing;
983             }
984         }
985         if(existing.isPending()) waitPending(processor, existing);
986         return existing;
987     }
988     
989     void remove(AsyncMultiReadEntry entry) {
990         synchronized(asyncMultiReadEntryMap) {
991             asyncMultiReadEntryMap.remove(entry.request);
992         }
993     }
994     
995     public static void runnerAsyncMultiReadEntry(ReadGraphImpl graph, AsyncMultiRead<?> r, CacheEntry parent, ListenerBase listener, final AsyncMultiProcedure procedure) throws DatabaseException {
996         QueryCache cache  = graph.processor.cache;
997         AsyncMultiReadEntry entry = (AsyncMultiReadEntry)cache.getOrCreateAsyncMultiReadEntry(graph.processor, r);
998         AsyncMultiProcedure procedure_ = procedure != null ? procedure : emptyProcedureAsyncMultiReadEntry;
999         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
1000         if(entry.isReady()) entry.performFromCache(graph, procedure_);
1001         else {
1002           assert(entry.isPending());
1003             entry.compute(graph, procedure_);
1004             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
1005         }
1006     }
1007     
1008     ExternalReadEntry getOrCreateExternalReadEntry(QueryProcessor processor, ExternalRead<?> r) throws DatabaseException {
1009         ExternalReadEntry existing = null;
1010         synchronized(externalReadEntryMap) {
1011             existing = (ExternalReadEntry)externalReadEntryMap.get(r);
1012             if(existing == null) {
1013                 existing = new ExternalReadEntry(r);
1014                 existing.clearResult(querySupport);
1015                 existing.setPending();
1016                 externalReadEntryMap.put(id(r), existing);
1017                 size++;
1018                 return existing;
1019             }
1020             if(existing.requiresComputation()) {
1021                 existing.setPending();
1022                 return existing;
1023             }
1024         }
1025         if(existing.isPending()) waitPending(processor, existing);
1026         return existing;
1027     }
1028     
1029     void remove(ExternalReadEntry entry) {
1030         synchronized(externalReadEntryMap) {
1031             externalReadEntryMap.remove(entry.request);
1032         }
1033     }
1034     
1035     public static void runnerExternalReadEntry(ReadGraphImpl graph, ExternalRead<?> r, CacheEntry parent, ListenerBase listener, final AsyncProcedure procedure) throws DatabaseException {
1036         QueryCache cache  = graph.processor.cache;
1037         ExternalReadEntry entry = (ExternalReadEntry)cache.getOrCreateExternalReadEntry(graph.processor, r);
1038         AsyncProcedure procedure_ = procedure != null ? procedure : emptyProcedureExternalReadEntry;
1039         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);
1040         if(entry.isReady()) entry.performFromCache(graph, procedure_);
1041         else {
1042           assert(entry.isPending());
1043             entry.compute(graph, procedure_);
1044             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
1045         }
1046     }
1047     
1048 }