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