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