]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java
d7a235fc813d4f302e719bb66647cd2cef972d91
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / QueryCacheBase.java
1 package org.simantics.db.impl.query;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.concurrent.Semaphore;
6 import java.util.concurrent.atomic.AtomicBoolean;
7
8 import org.simantics.db.AsyncReadGraph;
9 import org.simantics.db.ObjectResourceIdMap;
10 import org.simantics.db.ReadGraph;
11 import org.simantics.db.RelationInfo;
12 import org.simantics.db.common.utils.Logger;
13 import org.simantics.db.exception.DatabaseException;
14 import org.simantics.db.impl.DebugPolicy;
15 import org.simantics.db.impl.graph.ReadGraphImpl;
16 import org.simantics.db.impl.procedure.InternalProcedure;
17 import org.simantics.db.impl.query.QueryProcessor.SessionTask;
18 import org.simantics.db.procedure.AsyncMultiProcedure;
19 import org.simantics.db.procedure.AsyncProcedure;
20 import org.simantics.db.procedure.Listener;
21 import org.simantics.db.procedure.ListenerBase;
22 import org.simantics.db.procedure.Procedure;
23 import org.simantics.db.procedure.SyncMultiProcedure;
24 import org.simantics.db.request.AsyncMultiRead;
25 import org.simantics.db.request.AsyncRead;
26 import org.simantics.db.request.ExternalRead;
27 import org.simantics.db.request.MultiRead;
28 import org.simantics.db.request.Read;
29
30 import gnu.trove.map.hash.THashMap;
31 import gnu.trove.map.hash.TObjectIntHashMap;
32
33 public class QueryCacheBase {
34
35         // Statistics
36         final int THREADS;
37         public final int THREAD_MASK;
38         int                                             hits                  = 0;
39         int                                             misses                = 0;
40         int                                             updates               = 0;
41         public int                                              size                  = 0;
42
43         public volatile boolean dirty = false;
44         public boolean collecting = false;
45
46         protected final THashMap<String, URIToResource>                           uRIToResourceMap;
47         //protected final THashMap<String, NamespaceIndex>                          namespaceIndexMap;
48         protected final UnaryQueryHashMap<InternalProcedure<ObjectResourceIdMap<String>>> childMapMap;
49         protected final DoubleKeyQueryHashMap<IntProcedure>                       objectsMap;
50         protected final DoubleKeyQueryHashMap<TripleIntProcedure>                 assertedStatementsMap;
51         protected final DoubleKeyQueryHashMap<IntProcedure>                       directObjectsMap;
52         protected final DoubleKeyQueryHashMap<TripleIntProcedure>                 statementsMap;
53         protected final UnaryQueryHashMap<InternalProcedure<IntSet>>              typesMap;
54         protected final UnaryQueryHashMap<IntProcedure>                           principalTypesMap;
55         protected final UnaryQueryHashMap<InternalProcedure<IntSet>>              predicatesMap;
56         protected final UnaryQueryHashMap<InternalProcedure<IntSet>>              superTypesMap;
57         protected final UnaryQueryHashMap<InternalProcedure<IntSet>>              typeHierarchyMap;
58         protected final UnaryQueryHashMap<InternalProcedure<IntSet>>              superRelationsMap;
59
60         protected final UnaryQueryHashMap<IntProcedure>                           orderedSetMap;
61         protected final UnaryQueryHashMap<IntProcedure>                           assertedPredicatesMap;
62         protected final UnaryQueryHashMap<InternalProcedure<IntSet>>              directPredicatesMap;
63         protected final UnaryQueryHashMap<IntProcedure>                           directSuperRelationsMap;
64
65         protected final UnaryQueryHashMap<InternalProcedure<RelationInfo>>        relationInfoQueryMap;
66         protected final UnaryQueryHashMap<InternalProcedure<byte[]>>              valueQueryMap;
67
68         protected final StableHashMap<AsyncRead, AsyncReadEntry>                  asyncReadEntryMap; 
69         protected final StableHashMap<Read, ReadEntry>                            readEntryMap;
70         protected final StableHashMap<MultiRead, MultiReadEntry>                  multiReadEntryMap; 
71         protected final StableHashMap<AsyncMultiRead, AsyncMultiReadEntry>        asyncMultiReadEntryMap; 
72         protected final StableHashMap<ExternalRead, ExternalReadEntry>            externalReadEntryMap; 
73
74         final THashMap<CacheEntry, ArrayList<ListenerEntry>>                      listeners;
75
76         public final QuerySupport                                                 querySupport;
77
78         public QueryCacheBase(QuerySupport querySupport, int threads) {
79
80                 THREADS = threads;
81                 THREAD_MASK = threads - 1;
82
83                 this.querySupport = querySupport;
84                 directPredicatesMap = new UnaryQueryHashMap();
85                 directSuperRelationsMap = new UnaryQueryHashMap();
86                 valueQueryMap = new UnaryQueryHashMap();
87                 principalTypesMap = new UnaryQueryHashMap();
88                 uRIToResourceMap = new THashMap<String, URIToResource>();
89                 //namespaceIndexMap = new THashMap<String, NamespaceIndex>();
90                 childMapMap = new UnaryQueryHashMap<InternalProcedure<ObjectResourceIdMap<String>>>();
91                 relationInfoQueryMap = new UnaryQueryHashMap();
92                 typeHierarchyMap = new UnaryQueryHashMap();
93                 superTypesMap = new UnaryQueryHashMap();
94                 superRelationsMap = new UnaryQueryHashMap();
95                 typesMap = new UnaryQueryHashMap();
96                 objectsMap = new DoubleKeyQueryHashMap();
97                 orderedSetMap = new UnaryQueryHashMap();
98                 predicatesMap = new UnaryQueryHashMap();
99                 statementsMap = new DoubleKeyQueryHashMap();
100                 directObjectsMap = new DoubleKeyQueryHashMap();
101                 assertedPredicatesMap = new UnaryQueryHashMap();
102                 assertedStatementsMap = new DoubleKeyQueryHashMap();
103                 asyncReadEntryMap = new StableHashMap<AsyncRead, AsyncReadEntry>(); 
104                 readEntryMap = new StableHashMap<Read, ReadEntry>();
105                 asyncMultiReadEntryMap = new StableHashMap<AsyncMultiRead, AsyncMultiReadEntry>(); 
106                 multiReadEntryMap = new StableHashMap<MultiRead, MultiReadEntry>(); 
107                 externalReadEntryMap = new StableHashMap<ExternalRead, ExternalReadEntry>(); 
108                 listeners = new THashMap<CacheEntry, ArrayList<ListenerEntry>>(10, 0.75f);
109         }
110
111 //      public <T> Object performQuery(ReadGraphImpl parentGraph, final AsyncRead<T> query, final CacheEntryBase entry_, AsyncProcedure procedure_) throws DatabaseException {
112 //
113 //              AsyncReadEntry<T> entry = (AsyncReadEntry<T>)entry_;
114 //              AsyncProcedure<T> procedure = (AsyncProcedure<T>)procedure_;
115 //
116 //              ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
117 //
118 //              try {
119 //                      
120 //                      query.perform(queryGraph, new AsyncProcedure<T>() {
121 //
122 //                              @Override
123 //                              public void execute(AsyncReadGraph returnGraph, T result) {
124 //                                      ReadGraphImpl impl = (ReadGraphImpl)returnGraph;
125 //                                      entry.addOrSet(parentGraph, result);
126 //                                      try {
127 //                                              procedure.execute(parentGraph, result);
128 //                                      } catch (Throwable t) {
129 //                                              t.printStackTrace();
130 //                                      }
131 ////                                    parentBarrier.dec(query);
132 //                              }
133 //
134 //                              @Override
135 //                              public void exception(AsyncReadGraph returnGraph, Throwable t) {
136 //                                      ReadGraphImpl impl = (ReadGraphImpl)returnGraph;
137 ////                                    AsyncReadGraph resumeGraph = finalParentGraph.newAsync();
138 //                                      entry.except(parentGraph, t);
139 //                                      try {
140 //                                              procedure.exception(parentGraph, t);
141 //                                      } catch (Throwable t2) {
142 //                                              t2.printStackTrace();
143 //                                      }
144 ////                                    parentBarrier.dec(query);
145 //                              }
146 //
147 //                              @Override
148 //                              public String toString() {
149 //                                      return procedure.toString();
150 //                              }
151 //
152 //                      });
153 //
154 //              } catch (Throwable t) {
155 //
156 //                      entry.except(t);
157 //                      try {
158 //                              procedure.exception(parentGraph, t);
159 //                      } catch (Throwable t2) {
160 //                              t2.printStackTrace();
161 //                      }
162 ////                    parentBarrier.dec(query);
163 //
164 //              }
165 //              
166 //              return null;
167 //              
168 //      }
169
170 //      public <T> Object performQuery(ReadGraphImpl parentGraph, final Read<T> query, final CacheEntryBase entry_, AsyncProcedure procedure_) throws DatabaseException {
171 //
172 //              ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
173 //
174 //              ReadEntry entry = (ReadEntry)entry_;
175 //
176 //              try {
177 //
178 //                      T result = (T)query.perform(queryGraph);
179 //                      entry.addOrSet(queryGraph, result);
180 //
181 //                      return (T)entry.get(parentGraph, procedure_);
182 //
183 //              }  catch (Throwable t) {
184 //
185 //                      entry.except(t);
186 //                      return (T)entry.get(parentGraph, procedure_);
187 //
188 //              }
189 //              
190 //      }
191
192         public <T> Object performQuery(ReadGraphImpl parentGraph, final ExternalRead<T> query, final CacheEntryBase entry_, AsyncProcedure procedure_) throws DatabaseException {
193
194                 ExternalReadEntry entry = (ExternalReadEntry)entry_;
195                 AsyncProcedure<T> procedure = (AsyncProcedure<T>)procedure_;
196                 
197                 try {
198
199                         query.register(parentGraph, new Listener<T>() {
200
201                                 AtomicBoolean used = new AtomicBoolean(false);
202
203                                 @Override
204                                 public void execute(T result) {
205
206                                         // Just for safety
207                                         if(entry.isDiscarded()) return;
208
209                                         if(used.compareAndSet(false, true)) {
210                                                 //entry.setPending();
211                                                 entry.addOrSet(parentGraph.processor, result);
212                                                 procedure.execute(parentGraph, result);
213                                         } else {
214                                                 entry.queue(result);
215                                                 parentGraph.processor.updatePrimitive(query);
216                                         }
217
218                                 }
219
220                                 @Override
221                                 public void exception(Throwable t) {
222
223                                         entry.except(t);
224
225                                         if(used.compareAndSet(false, true)) {
226                                                 procedure.exception(parentGraph, t);
227                                         } else {
228 //                                              entry.queue(result);
229                                                 parentGraph.processor.updatePrimitive(query);
230                                         }
231
232                                 }
233
234                                 @Override
235                                 public String toString() {
236                                         return procedure.toString();
237                                 }
238
239                                 @Override
240                                 public boolean isDisposed() {
241                                         return entry.isDiscarded() || !parentGraph.processor.isBound(entry);
242                                 }
243
244                         });
245
246                         return entry.getResult();
247
248                 } catch (Throwable t) {
249
250                         entry.except(t);
251                         procedure.exception(parentGraph, t);
252                         return entry.getResult();
253
254                 }
255
256         }
257
258         public <T> Object performQuery(ReadGraphImpl parentGraph, final AsyncMultiRead<T> query, final CacheEntryBase entry_, Object procedure_) throws DatabaseException {
259
260                 ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
261
262                 AsyncMultiReadEntry entry = (AsyncMultiReadEntry)entry_;
263                 AsyncMultiProcedure<T> procedure = (AsyncMultiProcedure<T>)procedure_;
264
265                 try {
266
267                         query.perform(queryGraph, new AsyncMultiProcedure<T>() {
268
269                                 @Override
270                                 public void execute(AsyncReadGraph graph, T result) {
271                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
272                                         entry.addOrSet(result);
273                                         try {
274                                                 procedure.execute(parentGraph, result);
275                                         } catch (Throwable t) {
276                                                 t.printStackTrace();
277                                         }
278                                 }
279
280                                 @Override
281                                 public void finished(AsyncReadGraph graph) {
282                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
283                                         entry.finish(parentGraph);
284                                         try {
285                                                 procedure.finished(parentGraph);
286                                         } catch (Throwable t) {
287                                                 t.printStackTrace();
288                                         }
289                                 }
290
291                                 @Override
292                                 public void exception(AsyncReadGraph graph, Throwable t) {
293                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
294                                         entry.except(parentGraph, t);
295                                         try {
296                                                 procedure.exception(parentGraph, t);
297                                         } catch (Throwable t2) {
298                                                 t2.printStackTrace();
299                                         }
300                                 }
301
302                         });
303
304                         return entry.getResult();
305
306                 } catch (Throwable t) {
307
308                         entry.except(t);
309                         try {
310                                 procedure.exception(parentGraph, t);
311                         } catch (Throwable t2) {
312                                 t2.printStackTrace();
313                         }
314
315                         return entry.getResult();
316
317                 }
318
319         }
320
321         public <T> Object performQuery(ReadGraphImpl parentGraph, final MultiRead<T> query, final CacheEntryBase entry_, Object procedure_) throws DatabaseException {
322
323                 ReadGraphImpl queryGraph = parentGraph.withParent(entry_);
324
325                 MultiReadEntry entry = (MultiReadEntry)entry_;
326                 SyncMultiProcedure<T> procedure = (SyncMultiProcedure<T>)procedure_;
327
328                 try {
329
330                         query.perform(queryGraph, new SyncMultiProcedure<T>() {
331
332                                 @Override
333                                 public void execute(ReadGraph graph, T result) {
334                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
335                                         entry.addOrSet(result);
336                                         try {
337                                                 procedure.execute(parentGraph, result);
338                                         } catch (Throwable t) {
339                                                 t.printStackTrace();
340                                         }
341                                 }
342
343                                 @Override
344                                 public void finished(ReadGraph graph) {
345                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
346                                         entry.finish(parentGraph);
347                                         try {
348                                                 procedure.finished(parentGraph);
349                                         } catch (Throwable t) {
350                                                 t.printStackTrace();
351                                         }
352                                 }
353
354                                 @Override
355                                 public void exception(ReadGraph graph, Throwable t) {
356                                         ReadGraphImpl impl = (ReadGraphImpl)graph;
357                                         entry.except((DatabaseException)t);
358                                         try {
359                                                 procedure.exception(parentGraph, t);
360                                         } catch (Throwable t2) {
361                                                 t2.printStackTrace();
362                                         }
363                                 }
364
365                         });
366
367                         return entry.getResult();
368
369                 } catch (Throwable t) {
370
371                         entry.except(t);
372                         try {
373                                 procedure.exception(parentGraph, t);
374                         } catch (Throwable t2) {
375                                 t2.printStackTrace();
376                         }
377
378                         return entry.getResult();
379
380                 }
381                 
382         }
383         
384         public ListenerEntry registerDependencies(ReadGraphImpl graph, CacheEntry child, CacheEntry parent, ListenerBase listener, Object procedure, boolean inferred) {
385
386                 if (parent != null && !inferred) {
387                         try {
388                                 if(!child.isImmutable(graph)) {
389                                         synchronized(child) {
390                                                 child.addParent(parent);
391                                         }
392                                 }
393                         } catch (DatabaseException e) {
394                                 Logger.defaultLogError(e);
395                         }
396                         if(DebugPolicy.DEPENDENCIES) System.out.println(child + " -> " + parent);
397                 }
398
399                 if (listener != null) {
400                         return registerListener(child, listener, procedure);
401                 } else {
402                         return null;
403                 }
404
405         }
406         
407         public synchronized ListenerEntry registerListener(final CacheEntry entry, final ListenerBase base, final Object procedure) {
408
409                 assert (entry != null);
410
411                 if (base.isDisposed())
412                         return null;
413
414                 return addListener(entry, base, procedure);
415
416         }
417
418         protected void primeListenerEntry(final ListenerEntry entry, final Object result) {
419                 entry.setLastKnown(result);
420         }
421
422         private ListenerEntry addListener(CacheEntry entry, ListenerBase base, Object procedure) {
423
424                 assert (entry != null);
425                 assert (procedure != null);
426
427                 ArrayList<ListenerEntry> list = listeners.get(entry);
428                 if (list == null) {
429                         list = new ArrayList<ListenerEntry>(1);
430                         listeners.put(entry, list);
431                 }
432
433                 ListenerEntry result = new ListenerEntry(entry, base, procedure);
434                 int currentIndex = list.indexOf(result);
435                 // There was already a listener
436                 if(currentIndex > -1) {
437                         ListenerEntry current = list.get(currentIndex);
438                         if(!current.base.isDisposed()) return null;
439                         list.set(currentIndex, result);
440                 } else {
441                         list.add(result);
442                 }
443
444                 if(DebugPolicy.LISTENER) {
445                         new Exception().printStackTrace();
446                         System.out.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure);
447                 }
448
449                 return result;
450
451         }
452         
453         
454         public Collection<CacheEntry> getRootList() {
455
456                 ArrayList<CacheEntry> result = new ArrayList<CacheEntry>();
457
458                 for (Object e : valueQueryMap.values()) {
459                         result.add((CacheEntry) e);
460                 }
461                 for (Object e : directPredicatesMap.values()) {
462                         result.add((CacheEntry) e);
463                 }
464                 for (Object e : directSuperRelationsMap.values()) {
465                         result.add((CacheEntry) e);
466                 }
467                 for (Object e : objectsMap.values()) {
468                         result.add((CacheEntry) e);
469                 }
470                 for (Object e : directObjectsMap.values()) {
471                         result.add((CacheEntry) e);
472                 }
473                 for (Object e : principalTypesMap.values()) {
474                         result.add((CacheEntry) e);
475                 }
476                 for (Object e : superRelationsMap.values()) {
477                         result.add((CacheEntry) e);
478                 }
479                 for (Object e : superTypesMap.values()) {
480                         result.add((CacheEntry) e);
481                 }
482                 for (Object e : typesMap.values()) {
483                         result.add((CacheEntry) e);
484                 }
485                 for (Object e : objectsMap.values()) {
486                         result.add((CacheEntry) e);
487                 }
488                 for (Object e : assertedStatementsMap.values()) {
489                         result.add((CacheEntry) e);
490                 }
491                 for (Object e : readEntryMap.values()) {
492                         if(e instanceof CacheEntry) {
493                                 result.add((CacheEntry) e);
494                         } else {
495                                 System.err.println("e=" + e);
496                         }
497                 }
498                 for (Object e : asyncReadEntryMap.values()) {
499                         if(e instanceof CacheEntry) {
500                                 result.add((CacheEntry) e);
501                         } else {
502                                 System.err.println("e=" + e);
503                         }
504                 }
505                 for (Object e : externalReadEntryMap.values()) {
506                         result.add((CacheEntry) e);
507                 }
508                 for (Object e : orderedSetMap.values()) {
509                         result.add((CacheEntry) e);
510                 }
511
512                 return result;
513
514         }
515
516         public int calculateCurrentSize() {
517
518                 int realSize = 0;
519
520                 realSize += directPredicatesMap.size();
521                 realSize += directSuperRelationsMap.size();
522                 realSize += principalTypesMap.size();
523                 realSize += uRIToResourceMap.size();
524                 //realSize += namespaceIndexMap.size();
525                 realSize += childMapMap.size();
526
527                 realSize += relationInfoQueryMap.size();
528                 realSize += superTypesMap.size();
529                 realSize += typeHierarchyMap.size();
530                 realSize += superRelationsMap.size();
531                 realSize += typesMap.size();
532
533                 realSize += valueQueryMap.size();
534                 realSize += directObjectsMap.size();
535                 realSize += objectsMap.size();
536                 realSize += orderedSetMap.size();
537                 realSize += predicatesMap.size();
538
539                 realSize += statementsMap.size();
540                 realSize += assertedPredicatesMap.size();
541                 realSize += assertedStatementsMap.size();
542                 realSize += externalReadEntryMap.size();
543                 realSize += asyncReadEntryMap.size();
544
545                 realSize += readEntryMap.size();
546                 realSize += asyncMultiReadEntryMap.size();
547                 realSize += multiReadEntryMap.size();
548
549                 return realSize;
550
551         }
552
553         CacheCollectionResult allCaches(CacheCollectionResult result) {
554
555                 int level = Integer.MAX_VALUE;
556                 directPredicatesMap.values(level, result);
557                 directSuperRelationsMap.values(level, result);
558                 principalTypesMap.values(level, result);
559                 for(CacheEntryBase e : uRIToResourceMap.values())
560                         if(e.getLevel() <= level)
561                                 result.add(e);
562 //              for(CacheEntryBase e : namespaceIndexMap.values())
563 //                      if(e.getLevel() <= level)
564 //                              result.add(e);
565
566                 childMapMap.values(level, result);
567
568                 relationInfoQueryMap.values(level, result);
569                 superTypesMap.values(level, result);
570                 typeHierarchyMap.values(level, result);
571                 superRelationsMap.values(level, result);
572                 typesMap.values(level, result);
573
574                 valueQueryMap.values(level, result);
575                 directObjectsMap.values(level, result);
576                 objectsMap.values(level, result);
577                 orderedSetMap.values(level, result);
578                 predicatesMap.values(level, result);
579
580                 statementsMap.values(level, result);
581                 assertedPredicatesMap.values(level, result);
582                 assertedStatementsMap.values(level, result);
583                 externalReadEntryMap.values(level, result);
584                 asyncReadEntryMap.values(level, result);
585
586                 readEntryMap.values(level, result);
587                 asyncMultiReadEntryMap.values(level, result);
588                 multiReadEntryMap.values(level, result);
589
590                 return result;
591
592         }
593
594         public void scanPending() {
595
596                 ArrayList<CacheEntry> entries = new ArrayList<CacheEntry>();
597
598                 entries.addAll(directPredicatesMap.values());
599                 entries.addAll(directSuperRelationsMap.values());
600                 entries.addAll(principalTypesMap.values());
601                 entries.addAll(uRIToResourceMap.values());
602                 //entries.addAll(namespaceIndexMap.values());
603                 entries.addAll(childMapMap.values());
604                 entries.addAll(relationInfoQueryMap.values());
605                 entries.addAll(superTypesMap.values());
606                 entries.addAll(superRelationsMap.values());
607                 entries.addAll(typesMap.values());
608                 entries.addAll(valueQueryMap.values());
609                 entries.addAll(directObjectsMap.values());
610                 entries.addAll(objectsMap.values());
611                 entries.addAll(orderedSetMap.values());
612                 entries.addAll(predicatesMap.values());
613                 entries.addAll(orderedSetMap.values());
614                 entries.addAll(statementsMap.values());
615                 //                      entries.addAll(assertedObjectsMap.values());
616                 entries.addAll(assertedPredicatesMap.values());
617                 entries.addAll(assertedStatementsMap.values());
618                 entries.addAll(externalReadEntryMap.values());
619                 entries.addAll(asyncReadEntryMap.values());
620                 entries.addAll(externalReadEntryMap.values());
621                 entries.addAll(readEntryMap.values());
622                 entries.addAll(asyncMultiReadEntryMap.values());
623                 entries.addAll(multiReadEntryMap.values());
624                 entries.addAll(readEntryMap.values());
625                 System.out.println(entries.size() + " entries.");
626                 for(Object e : entries) {
627                         if(e instanceof CacheEntry) {
628                                 CacheEntry en = (CacheEntry)e;
629                                 if(en.isPending()) System.out.println("pending " + e);
630                                 if(en.isExcepted()) System.out.println("excepted " + e);
631                                 if(en.isDiscarded()) System.out.println("discarded " + e);
632                                 if(en.isRefuted()) System.out.println("refuted " + e);
633                                 if(en.isFresh()) System.out.println("fresh " + e);
634                         } else {
635                                 //System.out.println("Unknown object " + e);
636                         }
637                 }
638         }
639
640         public static void waitPending(ReadGraphImpl graph, CacheEntry entry) throws DatabaseException {
641
642                 int counter = 0;
643                 while(entry.isPending()) {
644                         try {
645                             boolean performed = graph.performPending();
646                             if(!performed) {
647                                         Thread.sleep(1);
648                                         counter++;
649                                         if(counter > 30000) {
650                                                 CacheEntryBase base = ((CacheEntryBase)entry);
651 //                                              if(base.created != null) {
652 //                                                      System.err.println("created:");
653 //                                                      base.created.printStackTrace();
654 //                                              }
655 //                                              if(base.performed != null) {
656 //                                                      System.err.println("performed:");
657 //                                                      base.performed.printStackTrace();
658 //                                              }
659 //                                              if(base.ready != null) {
660 //                                                      System.err.println("ready:");
661 //                                                      base.ready.printStackTrace();
662 //                                              }
663                                                 new Exception("Timeout waiting for request to complete: " + entry.getOriginalRequest()).printStackTrace();
664                                                 throw new DatabaseException("Timeout waiting for request to complete." +  entry.getOriginalRequest());
665                                                 //System.err.println("asd");
666                                                 //base.getQuery().recompute(null, null, entry);
667                                         }
668                                 }
669                         } catch (InterruptedException e) {
670                         }
671                 }
672
673         }
674
675         //////////////////////////////////////
676
677         public static Collection<Objects> entriesObjects(QueryProcessor processor, int r1) {
678                 synchronized(processor.cache.objectsMap) {
679                         return processor.cache.objectsMap.values(r1);
680                 }
681         }
682
683         public static Collection<Objects> entriesObjects(QueryProcessor processor) {
684                 synchronized(processor.cache.objectsMap) {
685                         return processor.cache.objectsMap.values();
686                 }
687         }
688
689         public static Collection<CacheEntry> entriesDirectPredicates(QueryProcessor processor) {
690                 synchronized(processor.cache.directPredicatesMap) {
691                         return processor.cache.directPredicatesMap.values();
692                 }
693         }
694
695         static final Collection<DirectObjects> entriesDirectObjects(final QueryProcessor processor, final int r1) {
696                 DoubleKeyQueryHashMap<IntProcedure> hash = processor.cache.directObjectsMap;
697                 return hash.values(r1);
698         }
699
700         static final Collection<Statements> entriesStatements(final QueryProcessor processor, final int r1) {
701                 return processor.cache.statementsMap.values(r1);
702         }
703
704         static final Types entryTypes(final QueryProcessor processor, final int r) {
705                 return (Types)processor.cache.typesMap.get(r);
706         }
707
708         static final PrincipalTypes entryPrincipalTypes(final QueryProcessor processor, final int r) {
709                 return (PrincipalTypes)processor.cache.principalTypesMap.get(r);
710         }
711
712         static final OrderedSet entryOrderedSet(final QueryProcessor processor, final int r) {
713                 return (OrderedSet)processor.cache.orderedSetMap.get(r);
714         }
715
716         static final ValueQuery entryValueQuery(final QueryProcessor processor, final int r) {
717                 return (ValueQuery)processor.cache.valueQueryMap.get(r);
718         }
719
720         static final DirectPredicates entryDirectPredicates(final QueryProcessor processor, final int r) {
721                 return (DirectPredicates)processor.cache.directPredicatesMap.get(r);
722         }
723
724         public static final ReadEntry entryRead(final QueryProcessor processor, final Read request) {
725                 return (ReadEntry)processor.cache.readEntryMap.get(request);
726         }
727
728         public static final MultiReadEntry entryMultiRead(final QueryProcessor processor, final MultiRead request) {
729                 return (MultiReadEntry)processor.cache.multiReadEntryMap.get(request);
730         }
731
732         public static final AsyncReadEntry entryAsyncRead(final QueryProcessor processor, final AsyncRead request) {
733                 return (AsyncReadEntry)processor.cache.asyncReadEntryMap.get(request);
734         }
735
736         public static final AsyncMultiReadEntry entryAsyncMultiRead(final QueryProcessor processor, final AsyncMultiRead request) {
737                 return (AsyncMultiReadEntry)processor.cache.asyncMultiReadEntryMap.get(request);
738         }
739
740         protected static final long keyR2(long r1, long r2) {
741                 long result = (r1<<32) | (r2 & 0xffffffffL); 
742                 return result;
743         }
744
745         protected static final <T> T id(T o) {
746                 return o;
747         }
748
749         protected static final int keyR(int r) {
750                 return r;
751         }
752
753         protected static final String keyID(String id) {
754                 return id;
755         }
756
757         protected static InternalProcedure<IntSet> emptyIntSetProcedure = new InternalProcedure<IntSet>() {
758
759                 @Override
760                 public void execute(ReadGraphImpl graph, IntSet result) {
761                 }
762
763                 @Override
764                 public void exception(ReadGraphImpl graph, Throwable throwable) {
765                 }
766
767         }; 
768
769         protected static InternalProcedure<byte[]> emptyBytesProcedure = new InternalProcedure<byte[]>() {
770
771                 @Override
772                 public void execute(ReadGraphImpl graph, byte[] bytes) {
773                 }
774
775                 @Override
776                 public void exception(ReadGraphImpl graph, Throwable throwable) {
777                 }
778
779         }; 
780
781         protected static InternalProcedure<Integer> emptyIntegerProcedure = new InternalProcedure<Integer>() {
782
783                 @Override
784                 public void execute(ReadGraphImpl graph, Integer i) {
785                 }
786
787                 @Override
788                 public void exception(ReadGraphImpl graph, Throwable throwable) {
789                 }
790
791         }; 
792
793
794         protected static InternalProcedure<TObjectIntHashMap<String>> emptyNamespaceProcedure = new InternalProcedure<TObjectIntHashMap<String>>() {
795
796                 @Override
797                 public void execute(ReadGraphImpl graph, TObjectIntHashMap<String> i) {
798                 }
799
800                 @Override
801                 public void exception(ReadGraphImpl graph, Throwable throwable) {
802                 }
803
804         }; 
805
806
807         protected static InternalProcedure<RelationInfo> emptyRelationInfoProcedure = new InternalProcedure<RelationInfo>() {
808
809                 @Override
810                 public void execute(ReadGraphImpl graph, RelationInfo i) {
811                 }
812
813                 @Override
814                 public void exception(ReadGraphImpl graph, Throwable throwable) {
815                 }
816
817         };
818
819         protected static InternalProcedure<ObjectResourceIdMap<String>> emptyChildMapProcedure = new InternalProcedure<ObjectResourceIdMap<String>>() {
820
821                 @Override
822                 public void execute(ReadGraphImpl graph, ObjectResourceIdMap<String> i) {
823                 }
824
825                 @Override
826                 public void exception(ReadGraphImpl graph, Throwable throwable) {
827                 }
828
829         };
830
831         protected static IntProcedure emptyIntProcedure = new IntProcedure() {
832
833                 @Override
834                 public void finished(ReadGraphImpl graph) {
835                 }
836
837                 @Override
838                 public void execute(ReadGraphImpl graph, int i) {
839                 }
840
841                 @Override
842                 public void exception(ReadGraphImpl graph, Throwable throwable) {
843                 }
844         };
845
846         protected static TripleIntProcedure emptyTripleIntProcedure = new TripleIntProcedure() {
847
848                 @Override
849                 public void execute(ReadGraphImpl graph, int s, int p, int o) {
850                 }
851
852                 @Override
853                 public void finished(ReadGraphImpl graph) {
854                 }
855
856                 @Override
857                 public void exception(ReadGraphImpl graph, Throwable throwable) {
858                 }
859
860         }; 
861
862         protected static AsyncProcedure<Object> emptyAsyncProcedure = new AsyncProcedure<Object>() {
863
864                 @Override
865                 public void execute(AsyncReadGraph graph, Object result) {
866                 }
867
868                 @Override
869                 public void exception(AsyncReadGraph graph, Throwable throwable) {
870                 }
871
872         };
873
874         protected static AsyncMultiProcedure<Object> emptyAsyncMultiProcedure = new AsyncMultiProcedure<Object>() {
875
876                 @Override
877                 public void execute(AsyncReadGraph graph, Object result) {
878                 }
879
880                 @Override
881                 public void finished(AsyncReadGraph graph) {
882                 }
883
884                 @Override
885                 public void exception(AsyncReadGraph graph, Throwable throwable) {
886                 }
887
888         }; 
889
890         protected static SyncMultiProcedure<Object> emptySyncMultiProcedure = new SyncMultiProcedure<Object>() {
891
892                 @Override
893                 public void execute(ReadGraph graph, Object result) {
894                 }
895
896                 @Override
897                 public void finished(ReadGraph graph) {
898                 }
899
900                 @Override
901                 public void exception(ReadGraph graph, Throwable throwable) {
902                 }
903
904         };
905
906         protected static InternalProcedure<IntSet> emptyProcedureTypes = emptyIntSetProcedure;
907         protected static InternalProcedure<IntSet> emptyProcedureSuperTypes = emptyIntSetProcedure;
908         protected static InternalProcedure<IntSet> emptyProcedureTypeHierarchy = emptyIntSetProcedure;
909         protected static InternalProcedure<IntSet> emptyProcedureSuperRelations = emptyIntSetProcedure;
910         protected static InternalProcedure<IntSet> emptyProcedurePredicates = emptyIntSetProcedure;
911         protected static InternalProcedure<IntSet> emptyProcedureDirectPredicates = emptyIntSetProcedure;
912
913         protected static IntProcedure emptyProcedureObjects = emptyIntProcedure;
914         protected static IntProcedure emptyProcedureDirectObjects = emptyIntProcedure;
915         protected static IntProcedure emptyProcedurePrincipalTypes = emptyIntProcedure;
916         protected static IntProcedure emptyProcedureDirectSuperRelations = emptyIntProcedure;
917         protected static IntProcedure emptyProcedureAssertedPredicates = emptyIntProcedure;
918         protected static IntProcedure emptyProcedureOrderedSet = emptyIntProcedure;
919
920         protected static TripleIntProcedure emptyProcedureStatements = emptyTripleIntProcedure;
921         protected static TripleIntProcedure emptyProcedureAssertedStatements = emptyTripleIntProcedure;
922
923         protected static InternalProcedure<byte[]> emptyProcedureValueQuery = emptyBytesProcedure;
924
925         protected static InternalProcedure<Integer> emptyProcedureURIToResource = emptyIntegerProcedure;
926         protected static InternalProcedure<TObjectIntHashMap<String>> emptyProcedureNamespaceIndex = emptyNamespaceProcedure;
927         protected static InternalProcedure<ObjectResourceIdMap<String>> emptyProcedureChildMap = emptyChildMapProcedure;
928         protected static InternalProcedure<RelationInfo> emptyProcedureRelationInfoQuery = emptyRelationInfoProcedure;
929
930         protected static AsyncProcedure emptyProcedureReadEntry = emptyAsyncProcedure;
931         protected static AsyncProcedure emptyProcedureAsyncReadEntry = emptyAsyncProcedure;
932         protected static SyncMultiProcedure emptyProcedureMultiReadEntry = emptySyncMultiProcedure;
933         protected static AsyncMultiProcedure emptyProcedureAsyncMultiReadEntry = emptyAsyncMultiProcedure;
934         protected static AsyncProcedure emptyProcedureExternalReadEntry = emptyAsyncProcedure;
935
936         static class AsyncProcedureWrapper<T> implements AsyncProcedure<T> {
937
938                 private AsyncProcedure<T> procedure;
939                 private T result = null;
940                 private Throwable throwable = null;
941                 private Semaphore s = new Semaphore(0);
942
943                 AsyncProcedureWrapper(AsyncProcedure<T> procedure) {
944                         this.procedure = procedure;
945                 }
946
947                 @Override
948                 public void execute(AsyncReadGraph graph, T result) {
949                         if(procedure != null) procedure.execute(graph, result);
950                         this.result = result;
951                         s.release();
952                 }
953
954                 @Override
955                 public void exception(AsyncReadGraph graph, Throwable throwable) {
956                         if(procedure != null) procedure.exception(graph, throwable);
957                         this.throwable = throwable;
958                         s.release();
959                 }
960
961                 public T get() throws DatabaseException {
962                         try {
963                                 s.acquire();
964                         } catch (InterruptedException e) {
965                                 e.printStackTrace();
966                         }
967                         if(throwable != null) {
968                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
969                                 else throw new DatabaseException(throwable);
970                         } else {
971                                 return result;
972                         }
973                 }
974                 
975         }
976
977         static class ExternalProcedureWrapper<T> implements AsyncProcedure<T> {
978
979                 private Procedure<T> procedure;
980                 private T result = null;
981                 private Throwable throwable = null;
982
983                 ExternalProcedureWrapper(Procedure<T> procedure) {
984                         this.procedure = procedure;
985                 }
986
987                 @Override
988                 public void execute(AsyncReadGraph graph, T result) {
989                         if(procedure != null) procedure.execute(result);
990                         this.result = result;
991                 }
992
993                 @Override
994                 public void exception(AsyncReadGraph graph, Throwable throwable) {
995                         if(procedure != null) procedure.exception(throwable);
996                         this.throwable = throwable;
997                 }
998
999                 public T get() throws DatabaseException {
1000                         if(throwable != null) {
1001                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1002                                 else throw new DatabaseException(throwable);
1003                         } else {
1004                                 return result;
1005                         }
1006                 }
1007
1008         }
1009
1010
1011         static class InternalProcedureWrapper<T> implements InternalProcedure<T> {
1012
1013                 private InternalProcedure<T> procedure;
1014                 private T result = null;
1015                 private Throwable throwable = null;
1016
1017                 InternalProcedureWrapper(InternalProcedure<T> procedure) {
1018                         this.procedure = procedure;
1019                 }
1020
1021                 @Override
1022                 public void execute(ReadGraphImpl graph, T result) throws DatabaseException {
1023                         if(procedure != null) procedure.execute(graph, result);
1024                         this.result = result;
1025                 }
1026
1027                 @Override
1028                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1029                         if(procedure != null) procedure.exception(graph, throwable);
1030                         this.throwable = throwable;
1031                 }
1032
1033                 public T get() throws DatabaseException {
1034                         if(throwable != null) {
1035                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1036                                 else throw new DatabaseException(throwable);
1037                         } else {
1038                                 return result;
1039                         }
1040                 }
1041
1042         }
1043
1044         static class IntSetWrapper implements IntProcedure {
1045
1046                 private IntProcedure procedure;
1047                 private final IntSet result;
1048                 private Throwable throwable = null;
1049
1050                 IntSetWrapper(ReadGraphImpl graph, IntProcedure procedure) {
1051                         this.procedure = procedure;
1052                         result = new IntSet(graph.processor.querySupport);
1053                 }
1054
1055                 @Override
1056                 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
1057                         if(procedure != null) procedure.execute(graph, i);
1058                         result.add(i);
1059                 }
1060
1061                 @Override
1062                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1063                         if(procedure != null) procedure.exception(graph, throwable);
1064                         this.throwable = throwable;
1065                 }
1066
1067                 @Override
1068                 public void finished(ReadGraphImpl graph) throws DatabaseException {
1069                         if(procedure != null) procedure.finished(graph);
1070                 }
1071
1072                 public IntSet get() throws DatabaseException {
1073                         if(throwable != null) {
1074                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1075                                 else throw new DatabaseException(throwable);
1076                         } else {
1077                                 return result;
1078                         }
1079                 }
1080
1081         }
1082
1083         static class TripleIntProcedureWrapper implements TripleIntProcedure {
1084
1085                 private TripleIntProcedure procedure;
1086                 private IntArray result = new IntArray();
1087                 private Throwable throwable = null;
1088
1089                 TripleIntProcedureWrapper(TripleIntProcedure procedure) {
1090                         this.procedure = procedure;
1091                 }
1092
1093                 @Override
1094                 public void execute(ReadGraphImpl graph, int i1, int i2, int i3) throws DatabaseException {
1095                         if(procedure != null) procedure.execute(graph, i1, i2, i3);
1096                         result.add(i1);
1097                         result.add(i2);
1098                         result.add(i3);
1099                 }
1100
1101                 @Override
1102                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1103                         if(procedure != null) procedure.exception(graph, throwable);
1104                         this.throwable = throwable;
1105                 }
1106
1107                 @Override
1108                 public void finished(ReadGraphImpl graph) throws DatabaseException {
1109                         if(procedure != null) procedure.finished(graph);
1110                 }
1111
1112                 public IntArray get() throws DatabaseException {
1113                         if(throwable != null) {
1114                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1115                                 else throw new DatabaseException(throwable);
1116                         } else {
1117                                 return result;
1118                         }
1119                 }
1120
1121         }
1122
1123         public static <T> T resultExternalReadEntry(ReadGraphImpl graph, ExternalRead r, CacheEntry parent, ListenerBase listener, Procedure<T> procedure) throws DatabaseException {
1124                 ExternalProcedureWrapper<T> wrap = new ExternalProcedureWrapper<>(procedure);
1125                 QueryCache.runnerExternalReadEntry(graph, r, parent, listener, wrap);
1126                 return wrap.get();
1127         }
1128
1129         public static <T> T resultReadEntry(ReadGraphImpl graph, Read r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
1130                 return (T)QueryCache.runnerReadEntry(graph, r, parent, listener, procedure, true);
1131         }
1132
1133         public static <T> T resultAsyncReadEntry(ReadGraphImpl graph, AsyncRead r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
1134                 return (T)QueryCache.runnerAsyncReadEntry(graph, r, parent, listener, procedure, true);
1135         }
1136
1137         public static byte[] resultValueQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1138                 InternalProcedureWrapper<byte[]> wrap = new InternalProcedureWrapper<>(null);
1139                 QueryCache.runnerValueQuery(graph, r, parent, listener, wrap);
1140                 return wrap.get();
1141         }
1142
1143         public static RelationInfo resultRelationInfoQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1144                 InternalProcedureWrapper<RelationInfo> wrap = new InternalProcedureWrapper<>(null);
1145                 QueryCache.runnerRelationInfoQuery(graph, r, parent, listener, wrap);
1146                 return wrap.get();
1147         }
1148
1149         public static IntSet resultSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1150                 InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1151                 QueryCache.runnerSuperRelations(graph, r, parent, listener, wrap);
1152                 return wrap.get();
1153         }
1154
1155         public static IntSet resultSuperTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1156                 InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1157                 QueryCache.runnerSuperTypes(graph, r, parent, listener, wrap);
1158                 return wrap.get();
1159         }
1160
1161         public static IntSet resultTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1162                 InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1163                 QueryCache.runnerTypes(graph, r, parent, listener, wrap);
1164                 return wrap.get();
1165         }
1166
1167         public static IntSet resultPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1168                 InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1169                 QueryCache.runnerPredicates(graph, r, parent, listener, wrap);
1170                 return wrap.get();
1171         }
1172
1173         public static IntSet resultDirectPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1174                 InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1175                 QueryCache.runnerDirectPredicates(graph, r, parent, listener, wrap);
1176                 return wrap.get();
1177         }
1178
1179         public static IntArray resultAssertedStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1180                 TripleIntProcedureWrapper wrap = new TripleIntProcedureWrapper(null);
1181                 QueryCache.runnerAssertedStatements(graph, r1, r2, parent, listener, wrap);
1182                 return wrap.get();
1183         }
1184
1185         public static Integer resultURIToResource(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1186                 InternalProcedureWrapper<Integer> wrap = new InternalProcedureWrapper<Integer>(null);
1187                 QueryCache.runnerURIToResource(graph, id, parent, listener, wrap);
1188                 return wrap.get();
1189         }
1190
1191         public static ObjectResourceIdMap<String> resultChildMap(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1192                 InternalProcedureWrapper<ObjectResourceIdMap<String>> wrap = new InternalProcedureWrapper<ObjectResourceIdMap<String>>(null);
1193                 QueryCache.runnerChildMap(graph, r, parent, listener, wrap);
1194                 return wrap.get();
1195         }
1196
1197         static boolean shouldCache(QueryProcessor processor, int r) {
1198                 return processor.isImmutable(r);
1199         }
1200
1201         static boolean shouldCache(QueryProcessor processor, int r, int r2) {
1202                 return processor.isImmutable(r);
1203         }
1204
1205         static boolean shouldCache(QueryProcessor processor, Object o) {
1206                 return false;
1207         }
1208
1209 }