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