]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java
Trying to remove synchronization problems
[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(QueryProcessor processor, CacheEntry entry) throws DatabaseException {
639                 
640                 int counter = 0;
641                 while(entry.isPending()) {
642                         try {
643                                 SessionTask task = null;//processor.getOwnTask(processor.thread.get());
644                                 if(task != null) {
645                                         task.run(processor.thread.get());
646                                 } else {
647                                         Thread.sleep(1);
648                                         counter++;
649                                         if(counter > 5000) {
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().toString()).printStackTrace();
664                                                 throw new DatabaseException("Timeout waiting for request to complete.");
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         static public Collection<Objects> entriesObjects(QueryProcessor processor, int r1) {
678                 synchronized(processor.cache.objectsMap) {
679                         return processor.cache.objectsMap.values(r1);
680                 }
681         }
682         
683         static public Collection<Objects> entriesObjects(QueryProcessor processor) {
684                 synchronized(processor.cache.objectsMap) {
685                         return processor.cache.objectsMap.values();
686                 }
687         }
688         
689         static public Collection<CacheEntry> entriesDirectPredicates(QueryProcessor processor) {
690                 synchronized(processor.cache.directPredicatesMap) {
691                         return processor.cache.directPredicatesMap.values();
692                 }
693         }
694
695         final static Collection<DirectObjects> entriesDirectObjects(final QueryProcessor processor, final int r1) {
696                 DoubleKeyQueryHashMap<IntProcedure> hash = processor.cache.directObjectsMap;
697                 return hash.values(r1);
698         }
699         
700         final static Collection<Statements> entriesStatements(final QueryProcessor processor, final int r1) {
701                 return processor.cache.statementsMap.values(r1);
702         }
703
704         final static Types entryTypes(final QueryProcessor processor, final int r) {
705                 return (Types)processor.cache.typesMap.get(r);
706         }
707
708         final static PrincipalTypes entryPrincipalTypes(final QueryProcessor processor, final int r) {
709                 return (PrincipalTypes)processor.cache.principalTypesMap.get(r);
710         }
711
712         final static OrderedSet entryOrderedSet(final QueryProcessor processor, final int r) {
713                 return (OrderedSet)processor.cache.orderedSetMap.get(r);
714         }
715         
716         final static ValueQuery entryValueQuery(final QueryProcessor processor, final int r) {
717                 return (ValueQuery)processor.cache.valueQueryMap.get(r);
718         }
719
720         final static DirectPredicates entryDirectPredicates(final QueryProcessor processor, final int r) {
721                 return (DirectPredicates)processor.cache.directPredicatesMap.get(r);
722         }
723
724         public final static ReadEntry entryRead(final QueryProcessor processor, final Read request) {
725                 return (ReadEntry)processor.cache.readEntryMap.get(request);
726         }
727
728         public final static MultiReadEntry entryMultiRead(final QueryProcessor processor, final MultiRead request) {
729                 return (MultiReadEntry)processor.cache.multiReadEntryMap.get(request);
730         }
731
732         public final static AsyncReadEntry entryAsyncRead(final QueryProcessor processor, final AsyncRead request) {
733                 return (AsyncReadEntry)processor.cache.asyncReadEntryMap.get(request);
734         }
735
736         public final static AsyncMultiReadEntry entryAsyncMultiRead(final QueryProcessor processor, final AsyncMultiRead request) {
737                 return (AsyncMultiReadEntry)processor.cache.asyncMultiReadEntryMap.get(request);
738         }
739
740         final protected static long keyR2(long r1, long r2) {
741         long result = (r1<<32) | (r2 & 0xffffffffL); 
742         return result;
743     }
744         
745         final protected static <T> T id(T o) {
746                 return o;
747         }
748
749     final protected static int keyR(int r) {
750         return r;
751     }
752
753     final protected static 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         
832         
833         protected static IntProcedure emptyIntProcedure = new IntProcedure() {
834                 
835                 @Override
836                 public void finished(ReadGraphImpl graph) {
837                 }
838                 
839                 @Override
840                 public void execute(ReadGraphImpl graph, int i) {
841                 }
842                 
843                 @Override
844                 public void exception(ReadGraphImpl graph, Throwable throwable) {
845                 }
846         }; 
847         
848         protected static TripleIntProcedure emptyTripleIntProcedure = new TripleIntProcedure() {
849
850                 @Override
851                 public void execute(ReadGraphImpl graph, int s, int p, int o) {
852                 }
853
854                 @Override
855                 public void finished(ReadGraphImpl graph) {
856                 }
857
858                 @Override
859                 public void exception(ReadGraphImpl graph, Throwable throwable) {
860                 }
861                 
862         }; 
863
864     protected static AsyncProcedure<Object> emptyAsyncProcedure = new AsyncProcedure<Object>() {
865
866                 @Override
867                 public void execute(AsyncReadGraph graph, Object result) {
868                 }
869
870                 @Override
871                 public void exception(AsyncReadGraph graph, Throwable throwable) {
872                 }
873                 
874         }; 
875         
876     protected static AsyncMultiProcedure<Object> emptyAsyncMultiProcedure = new AsyncMultiProcedure<Object>() {
877
878                 @Override
879                 public void execute(AsyncReadGraph graph, Object result) {
880                 }
881
882                 @Override
883                 public void finished(AsyncReadGraph graph) {
884                 }
885
886                 @Override
887                 public void exception(AsyncReadGraph graph, Throwable throwable) {
888                 }
889
890                 
891         }; 
892
893         protected static InternalProcedure<IntSet> emptyProcedureTypes = emptyIntSetProcedure;
894     protected static InternalProcedure<IntSet> emptyProcedureSuperTypes = emptyIntSetProcedure;
895     protected static InternalProcedure<IntSet> emptyProcedureTypeHierarchy = emptyIntSetProcedure;
896     protected static InternalProcedure<IntSet> emptyProcedureSuperRelations = emptyIntSetProcedure;
897     protected static InternalProcedure<IntSet> emptyProcedurePredicates = emptyIntSetProcedure;
898     protected static InternalProcedure<IntSet> emptyProcedureDirectPredicates = emptyIntSetProcedure;
899
900     protected static IntProcedure emptyProcedureObjects = emptyIntProcedure;
901     protected static IntProcedure emptyProcedureDirectObjects = emptyIntProcedure;
902     protected static IntProcedure emptyProcedurePrincipalTypes = emptyIntProcedure;
903     protected static IntProcedure emptyProcedureDirectSuperRelations = emptyIntProcedure;
904     protected static IntProcedure emptyProcedureAssertedPredicates = emptyIntProcedure;
905     protected static IntProcedure emptyProcedureOrderedSet = emptyIntProcedure;
906     
907     protected static TripleIntProcedure emptyProcedureStatements = emptyTripleIntProcedure;
908     protected static TripleIntProcedure emptyProcedureAssertedStatements = emptyTripleIntProcedure;
909
910     protected static InternalProcedure<byte[]> emptyProcedureValueQuery = emptyBytesProcedure;
911     
912     protected static InternalProcedure<Integer> emptyProcedureURIToResource = emptyIntegerProcedure;
913     protected static InternalProcedure<TObjectIntHashMap<String>> emptyProcedureNamespaceIndex = emptyNamespaceProcedure;
914     protected static InternalProcedure<ObjectResourceIdMap<String>> emptyProcedureChildMap = emptyChildMapProcedure;
915     protected static InternalProcedure<RelationInfo> emptyProcedureRelationInfoQuery = emptyRelationInfoProcedure;
916
917     protected static AsyncProcedure emptyProcedureReadEntry = emptyAsyncProcedure;
918     protected static AsyncProcedure emptyProcedureAsyncReadEntry = emptyAsyncProcedure;
919     protected static AsyncMultiProcedure emptyProcedureMultiReadEntry = emptyAsyncMultiProcedure;
920     protected static AsyncMultiProcedure emptyProcedureAsyncMultiReadEntry = emptyAsyncMultiProcedure;
921     protected static AsyncProcedure emptyProcedureExternalReadEntry = emptyAsyncProcedure;
922         
923     static class AsyncProcedureWrapper<T> implements AsyncProcedure<T> {
924         
925         private AsyncProcedure<T> procedure;
926         private T result = null;
927         private Throwable throwable = null;
928         private Semaphore s = new Semaphore(0);
929         
930         AsyncProcedureWrapper(AsyncProcedure<T> procedure) {
931                 this.procedure = procedure;
932         }
933
934                 @Override
935                 public void execute(AsyncReadGraph graph, T result) {
936                         if(procedure != null) procedure.execute(graph, result);
937                         this.result = result;
938                         s.release();
939                 }
940
941                 @Override
942                 public void exception(AsyncReadGraph graph, Throwable throwable) {
943                         if(procedure != null) procedure.exception(graph, throwable);
944                         this.throwable = throwable;
945                         s.release();
946                 }
947                 
948                 public T get() throws DatabaseException {
949                         try {
950                                 s.acquire();
951                         } catch (InterruptedException e) {
952                                 e.printStackTrace();
953                         }
954                         if(throwable != null) {
955                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
956                                 else throw new DatabaseException(throwable);
957                         } else {
958                                 return result;
959                         }
960                 }
961                 
962     }
963
964     static class ExternalProcedureWrapper<T> implements AsyncProcedure<T> {
965         
966         private Procedure<T> procedure;
967         private T result = null;
968         private Throwable throwable = null;
969         
970         ExternalProcedureWrapper(Procedure<T> procedure) {
971             this.procedure = procedure;
972         }
973
974         @Override
975         public void execute(AsyncReadGraph graph, T result) {
976             if(procedure != null) procedure.execute(result);
977             this.result = result;
978         }
979
980         @Override
981         public void exception(AsyncReadGraph graph, Throwable throwable) {
982             if(procedure != null) procedure.exception(throwable);
983             this.throwable = throwable;
984         }
985         
986         public T get() throws DatabaseException {
987             if(throwable != null) {
988                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
989                 else throw new DatabaseException(throwable);
990             } else {
991                 return result;
992             }
993         }
994         
995     }
996
997     
998     static class InternalProcedureWrapper<T> implements InternalProcedure<T> {
999         
1000         private InternalProcedure<T> procedure;
1001         private T result = null;
1002         private Throwable throwable = null;
1003         
1004         InternalProcedureWrapper(InternalProcedure<T> procedure) {
1005                 this.procedure = procedure;
1006         }
1007
1008                 @Override
1009                 public void execute(ReadGraphImpl graph, T result) throws DatabaseException {
1010                         if(procedure != null) procedure.execute(graph, result);
1011                         this.result = result;
1012                 }
1013
1014                 @Override
1015                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1016                         if(procedure != null) procedure.exception(graph, throwable);
1017                         this.throwable = throwable;
1018                 }
1019                 
1020                 public T get() throws DatabaseException {
1021                         if(throwable != null) {
1022                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1023                                 else throw new DatabaseException(throwable);
1024                         } else {
1025                                 return result;
1026                         }
1027                 }
1028                 
1029     }
1030     
1031     static class IntSetWrapper implements IntProcedure {
1032         
1033         private IntProcedure procedure;
1034         final private IntSet result;
1035         private Throwable throwable = null;
1036         
1037         IntSetWrapper(ReadGraphImpl graph, IntProcedure procedure) {
1038                 this.procedure = procedure;
1039                 result = new IntSet(graph.processor.querySupport);
1040         }
1041
1042                 @Override
1043                 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
1044                         if(procedure != null) procedure.execute(graph, i);
1045                         result.add(i);
1046                 }
1047
1048                 @Override
1049                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1050                         if(procedure != null) procedure.exception(graph, throwable);
1051                         this.throwable = throwable;
1052                 }
1053                 
1054                 @Override
1055                 public void finished(ReadGraphImpl graph) throws DatabaseException {
1056                         if(procedure != null) procedure.finished(graph);
1057                 }
1058                 
1059                 public IntSet get() throws DatabaseException {
1060                         if(throwable != null) {
1061                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1062                                 else throw new DatabaseException(throwable);
1063                         } else {
1064                                 return result;
1065                         }
1066                 }
1067
1068     }
1069
1070     static class TripleIntProcedureWrapper implements TripleIntProcedure {
1071         
1072         private TripleIntProcedure procedure;
1073         private IntArray result = new IntArray();
1074         private Throwable throwable = null;
1075         
1076         TripleIntProcedureWrapper(TripleIntProcedure procedure) {
1077                 this.procedure = procedure;
1078         }
1079
1080                 @Override
1081                 public void execute(ReadGraphImpl graph, int i1, int i2, int i3) throws DatabaseException {
1082                         if(procedure != null) procedure.execute(graph, i1, i2, i3);
1083                         result.add(i1);
1084                         result.add(i2);
1085                         result.add(i3);
1086                 }
1087
1088                 @Override
1089                 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
1090                         if(procedure != null) procedure.exception(graph, throwable);
1091                         this.throwable = throwable;
1092                 }
1093                 
1094                 @Override
1095                 public void finished(ReadGraphImpl graph) throws DatabaseException {
1096                         if(procedure != null) procedure.finished(graph);
1097                 }
1098                 
1099                 public IntArray get() throws DatabaseException {
1100                         if(throwable != null) {
1101                                 if(throwable instanceof DatabaseException) throw (DatabaseException)throwable;
1102                                 else throw new DatabaseException(throwable);
1103                         } else {
1104                                 return result;
1105                         }
1106                 }
1107
1108     }
1109
1110     public static <T> T resultExternalReadEntry(ReadGraphImpl graph, ExternalRead r, CacheEntry parent, ListenerBase listener, Procedure<T> procedure) throws DatabaseException {
1111         ExternalProcedureWrapper<T> wrap = new ExternalProcedureWrapper<>(procedure);
1112         QueryCache.runnerExternalReadEntry(graph, r, parent, listener, wrap);
1113         return wrap.get();
1114     }
1115
1116     public static <T> T resultReadEntry(ReadGraphImpl graph, Read r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
1117         AsyncProcedureWrapper<T> wrap = new AsyncProcedureWrapper<>(procedure);
1118         QueryCache.runnerReadEntry(graph, r, parent, listener, wrap, true);
1119         return wrap.get();
1120     }
1121
1122     public static <T> T resultAsyncReadEntry(ReadGraphImpl graph, AsyncRead r, CacheEntry parent, ListenerBase listener, AsyncProcedure<T> procedure) throws DatabaseException {
1123         AsyncProcedureWrapper<T> wrap = new AsyncProcedureWrapper<>(procedure);
1124         QueryCache.runnerAsyncReadEntry(graph, r, parent, listener, wrap, true);
1125         return wrap.get();
1126     }
1127
1128     public static byte[] resultValueQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1129         InternalProcedureWrapper<byte[]> wrap = new InternalProcedureWrapper<>(null);
1130         QueryCache.runnerValueQuery(graph, r, parent, listener, wrap);
1131         return wrap.get();
1132     }
1133
1134     public static RelationInfo resultRelationInfoQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1135         InternalProcedureWrapper<RelationInfo> wrap = new InternalProcedureWrapper<>(null);
1136         QueryCache.runnerRelationInfoQuery(graph, r, parent, listener, wrap);
1137         return wrap.get();
1138     }
1139
1140     public static IntSet resultSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1141         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1142         QueryCache.runnerSuperRelations(graph, r, parent, listener, wrap);
1143         return wrap.get();
1144     }
1145
1146     public static IntSet resultSuperTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1147         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1148         QueryCache.runnerSuperTypes(graph, r, parent, listener, wrap);
1149         return wrap.get();
1150     }
1151     
1152     public static IntSet resultTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1153         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1154         QueryCache.runnerTypes(graph, r, parent, listener, wrap);
1155         return wrap.get();
1156     }
1157
1158     public static IntSet resultPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1159         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1160         QueryCache.runnerPredicates(graph, r, parent, listener, wrap);
1161         return wrap.get();
1162     }
1163
1164     public static IntSet resultDirectPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1165         InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
1166         QueryCache.runnerDirectPredicates(graph, r, parent, listener, wrap);
1167         return wrap.get();
1168     }
1169
1170     public static IntArray resultAssertedStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1171         TripleIntProcedureWrapper wrap = new TripleIntProcedureWrapper(null);
1172         QueryCache.runnerAssertedStatements(graph, r1, r2, parent, listener, wrap);
1173         return wrap.get();
1174     }
1175
1176     public static Integer resultURIToResource(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1177         InternalProcedureWrapper<Integer> wrap = new InternalProcedureWrapper<Integer>(null);
1178         QueryCache.runnerURIToResource(graph, id, parent, listener, wrap);
1179         return wrap.get();
1180     }
1181
1182     public static ObjectResourceIdMap<String> resultChildMap(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
1183         InternalProcedureWrapper<ObjectResourceIdMap<String>> wrap = new InternalProcedureWrapper<ObjectResourceIdMap<String>>(null);
1184         QueryCache.runnerChildMap(graph, r, parent, listener, wrap);
1185         return wrap.get();
1186     }
1187
1188     static boolean shouldCache(QueryProcessor processor, int r) {
1189         return processor.isImmutable(r);
1190     }
1191     
1192     static boolean shouldCache(QueryProcessor processor, int r, int r2) {
1193         return processor.isImmutable(r);
1194     }
1195
1196     static boolean shouldCache(QueryProcessor processor, Object o) {
1197         return false;
1198     }
1199     
1200 }
1201