]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QuerySupportImpl.java
Working towards multiple readers.
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / QuerySupportImpl.java
1 package fi.vtt.simantics.procore.internal;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.InputStream;
5 import java.util.Collection;
6 import java.util.function.Consumer;
7
8 import org.simantics.db.Resource;
9 import org.simantics.db.Session;
10 import org.simantics.db.Statement;
11 import org.simantics.db.VirtualGraph;
12 import org.simantics.db.WriteGraph;
13 import org.simantics.db.common.StandardStatement;
14 import org.simantics.db.common.request.WriteRequest;
15 import org.simantics.db.common.utils.Logger;
16 import org.simantics.db.exception.DatabaseException;
17 import org.simantics.db.exception.InvalidResourceReferenceException;
18 import org.simantics.db.exception.ResourceNotFoundException;
19 import org.simantics.db.impl.ClusterI;
20 import org.simantics.db.impl.ClusterSupport;
21 import org.simantics.db.impl.ForEachObjectContextProcedure;
22 import org.simantics.db.impl.ForEachObjectProcedure;
23 import org.simantics.db.impl.ResourceImpl;
24 import org.simantics.db.impl.TransientGraph;
25 import org.simantics.db.impl.VirtualGraphImpl;
26 import org.simantics.db.impl.graph.ReadGraphImpl;
27 import org.simantics.db.impl.query.IntProcedure;
28 import org.simantics.db.impl.query.QueryProcessor;
29 import org.simantics.db.impl.query.QuerySupport;
30 import org.simantics.db.impl.support.BuiltinSupport;
31 import org.simantics.db.impl.support.ResourceSupport;
32 import org.simantics.db.procore.cluster.ClusterImpl;
33 import org.simantics.db.procore.cluster.ClusterSmall;
34 import org.simantics.db.service.SerialisationSupport;
35 import org.simantics.utils.DataContainer;
36 import org.slf4j.LoggerFactory;
37
38 import gnu.trove.set.hash.TIntHashSet;
39
40 public class QuerySupportImpl implements QuerySupport {
41
42     private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(QuerySupportImpl.class);
43
44         final SessionImplSocket session;
45         final State state;
46         final ClusterTable clusterTable;
47         final BuiltinSupport builtinSupport;
48         final ClusterSupport clusterSupport;
49         final ResourceSupport resourceSupport;
50         final SerialisationSupport serializationSupport;
51         final VirtualGraphServerSupportImpl virtualGraphServerSupport;
52         final GraphSession graphSession;
53         final SessionRequestManager syncThreads;
54         final int root;
55
56     private boolean pendingPrimitives = false;
57         
58         QuerySupportImpl(SessionImplSocket session, ClusterSupport clusterSupport, SerialisationSupport serializationSupport, SessionRequestManager syncThreads) {
59                 this.session = session;
60                 this.state = session.state;
61                 this.clusterTable = session.clusterTable;
62                 this.resourceSupport = session.resourceSupport;
63                 this.virtualGraphServerSupport = session.virtualGraphServerSupport;
64                 this.graphSession = session.graphSession;
65                 this.builtinSupport = session.builtinSupport;
66                 this.clusterSupport = clusterSupport;
67                 this.serializationSupport = serializationSupport;
68                 this.syncThreads = syncThreads;
69                 this.root = getBuiltin("http:/");
70                 assert(this.session != null);
71                 assert(this.state != null);
72                 assert(this.clusterTable != null);
73                 assert(this.resourceSupport != null);
74                 assert(this.virtualGraphServerSupport != null);
75                 assert(this.graphSession != null);
76                 assert(this.builtinSupport != null);
77                 assert(this.clusterSupport != null);
78                 assert(this.serializationSupport != null);
79                 assert(this.syncThreads != null);
80         }
81
82         @Override
83         public ResourceSupport getSupport() {
84                 return resourceSupport;
85         }
86         
87     @Override
88     public Statement getStatement(int s, int p, int o) {
89         return getStatement(null, s, p, o);
90     }
91
92     @Override
93     public Statement getStatement(ReadGraphImpl graph, int s, int p, int o) {
94         Resource sr = getResource(s);
95         Resource pr = getResource(p);
96         Resource or = getResource(o);
97         return new StandardStatement(sr, pr, or);
98     }
99
100         @Override
101         public Session getSession() {
102                 return session;
103         }
104
105     @Override
106     public long getClusterId(int id) {
107         ClusterI cluster = clusterTable.getClusterByResourceKey(id);
108         if(cluster == null) return 0;
109         return cluster.getClusterId();
110     }
111     
112     @Override
113     public boolean isImmutable(int id) {
114         // Virtuals are mutable
115         if(id < 0) return false;
116         // Root library is mutable
117         if(root == id) return false;
118         // Anything goes in service mode
119         if(session.serviceMode > 0) return false;
120         return clusterTable.isImmutable(id);
121     }
122
123     @Override
124     public int getId(Resource resource) {
125         if (resource instanceof ResourceImpl)
126             return ((ResourceImpl)resource).id;
127         return 0;
128     }
129
130         @Override
131         public Resource getResource(int id) {
132                 try {
133                         return serializationSupport.getResource(id);
134                 } catch (DatabaseException e) {
135                         e.printStackTrace();
136                 }
137                 return null;
138         }
139
140         @Override
141     public boolean resume(ReadGraphImpl graph) {
142                 
143                 return syncThreads.session.queryProvider2.resume(graph);
144                 
145     }
146
147 //    @Override
148 //    final public void sync(int resumeThread, final SessionRunnable runnable) {
149 //      
150 //      syncThreads.session.queryProvider2.schedule(Integer.MIN_VALUE, new SessionTask(resumeThread) {
151 //
152 //                      @Override
153 //                      public void run(int thread) {
154 //                              runnable.run(thread);
155 //                      }
156 //              
157 //      });
158 //      
159 //    }
160
161 //    @Override
162 //    final public int nextSyncThread() {
163 //      throw new Error();
164 ////        return syncThreads.nextThread();
165 //    }
166
167         @Override
168     public void dirtyPrimitives() {
169         session.dirtyPrimitives = true;
170         if(state.getWriteCount() == 0 && !pendingPrimitives) {
171             pendingPrimitives = true;
172             session.asyncRequest(new WriteRequest() {
173
174                 @Override
175                 public void perform(WriteGraph graph) throws DatabaseException {
176                     pendingPrimitives = false;
177                 }
178                 
179             });
180         }
181     }
182
183     @Override
184     @Deprecated
185     final public void aboutToRead() {
186     }
187
188 //    @Override
189 //    public void increaseReferenceCount(int callerThread, int subject) {
190 //        if (subject < 0)
191 //            return;
192 //        ClusterI proxy = clusterTable.getClusterByResourceKey(subject);
193 //        if (null == proxy)
194 //            return;
195 //        proxy.increaseReferenceCount(callerThread, 1);
196 //    }
197 //
198 //    @Override
199 //    public void decreaseReferenceCount(int callerThread, int subject) {
200 //        if (subject < 0)
201 //            return;
202 //        ClusterProxy proxy = clusterTable.getClusterByResourceKey(subject);
203 //        if (null == proxy)
204 //            return;
205 //        proxy.decreaseReferenceCount(callerThread, 1);
206 //    }
207
208 //      @Override
209         public void getObjects4(final ReadGraphImpl graph, final int subject, final ForEachObjectProcedure procedure) {
210                 
211                 if(subject < 0) {
212                         
213                         for(TransientGraph g : virtualGraphServerSupport.providers) {
214                 for (final int id : g.getObjects(subject, procedure.predicateKey)) {
215
216 //                    int suggestSchedule = graph.processor.processor.resourceThread(id);
217 //                    if(graph.callerThread == suggestSchedule) {
218                         try {
219                                                         procedure.execute(graph, new ResourceImpl(resourceSupport, id));
220                                                 } catch (DatabaseException e) {
221                                                         LOGGER.error("Unexpected exception while handling object", e);
222                                                 }
223 //                    } else {
224 //                      graph.processor.processor.schedule(graph.callerThread, new SessionTask(suggestSchedule) {
225 //              
226 //                              @Override
227 //                              public void run(int thread) {
228 //                              procedure.execute(graph.newAsync(thread), new ResourceImpl(resourceSupport, id));
229 //                              }
230 //              
231 //                      });
232 //                    }
233                         
234                 }
235                         }
236                 try {
237                         procedure.finished(graph);
238                         } catch (DatabaseException e) {
239                                 LOGGER.error("Unexpected exception while handling objects", e);
240                         }
241 //              graph.dec();
242                 return;
243                 
244                 } 
245                 
246         final ClusterImpl cluster = (ClusterImpl)clusterTable.getClusterByResourceKey(subject);
247         if(!cluster.isLoaded()) {
248                 try {
249                                 cluster.load();
250                         } catch (DatabaseException e) {
251                                 LOGGER.error("Unexpected exception while handling objects", e);
252                         }
253                 getObjects4(graph, subject, procedure);
254                 return;
255         }
256                 
257                 if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject)) {
258                         
259                         for(TransientGraph g : virtualGraphServerSupport.providers) {
260                 for (final int id : g.getObjects(subject, procedure.predicateKey)) {
261                         try {
262                         procedure.execute(graph, new ResourceImpl(resourceSupport, id));
263                                 } catch (DatabaseException e) {
264                                         LOGGER.error("Unexpected exception while handling objects", e);
265                                 }
266                         
267                         
268 //                    int suggestSchedule = graph.processor.processor.resourceThread(id);
269 //                    if(graph.callerThread == suggestSchedule) {
270 //                    } else {
271 //                      graph.processor.processor.schedule(graph.callerThread, new SessionTask(suggestSchedule) {
272 //              
273 //                              @Override
274 //                              public void run(int thread) {
275 //                              procedure.execute(graph.newAsync(thread), new ResourceImpl(resourceSupport, id));
276 //                              }
277 //              
278 //                      });
279 //                    }
280                 }
281                         }
282                         
283                         try {
284                                 cluster.forObjects(graph, subject, procedure);
285                         } catch (DatabaseException e) {
286                                 e.printStackTrace();
287                         }
288                         
289                 } else {
290                         
291                         try {
292                                 cluster.forObjects(graph, subject, procedure);
293                         } catch (DatabaseException e) {
294                                 e.printStackTrace();
295                         }
296                         
297                 }
298                 
299         }
300
301         public <C> void getObjects4(final ReadGraphImpl graph, final int subject, final C context, final ForEachObjectContextProcedure<C> procedure) {
302                 
303                 if(subject < 0) {
304                         
305                         for(TransientGraph g : virtualGraphServerSupport.providers) {
306                 for (final int id : g.getObjects(subject, procedure.predicateKey)) {
307
308 //                    int suggestSchedule = graph.processor.processor.resourceThread(id);
309 //                    if(graph.callerThread == suggestSchedule) {
310                         
311                         try {
312                                 procedure.execute(graph, context, new ResourceImpl(resourceSupport, id));
313                                 } catch (DatabaseException e) {
314                                         LOGGER.error("Unexpected exception while handling objects", e);
315                                 }
316                         
317                         
318                         
319 //                    } else {
320 //                      graph.processor.processor.schedule(graph.callerThread, new SessionTask(suggestSchedule) {
321 //              
322 //                              @Override
323 //                              public void run(int thread) {
324 //                              procedure.execute(graph.newAsync(thread), context, new ResourceImpl(resourceSupport, id));
325 //                              }
326 //              
327 //                      });
328 //                    }
329                         
330                 }
331                         }
332                         
333                 try {
334                         procedure.finished(graph, context);
335                         } catch (DatabaseException e) {
336                                 LOGGER.error("Unexpected exception while handling objects", e);
337                         }
338
339                         
340 //              graph.dec();
341                 return;
342                 
343                 } 
344                 
345         final ClusterImpl cluster = (ClusterImpl)clusterTable.getClusterByResourceKey(subject);
346         if(!cluster.isLoaded()) {
347                 cluster.load(session.clusterTranslator, new Runnable() {
348
349                                 @Override
350                                 public void run() {
351                                         getObjects4(graph, subject, context, procedure);
352                                 }
353                         
354                 });
355                 return;
356         }
357                 
358                 if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject)) {
359                         
360                         for(TransientGraph g : virtualGraphServerSupport.providers) {
361                 for (final int id : g.getObjects(subject, procedure.predicateKey)) {
362 //                    int suggestSchedule = graph.processor.processor.resourceThread(id);
363 //                    if(graph.callerThread == suggestSchedule) {
364                         try {
365                                 procedure.execute(graph, context, new ResourceImpl(resourceSupport, id));
366                                 } catch (DatabaseException e) {
367                                         LOGGER.error("Unexpected exception while handling objects", e);
368                                 }
369 //                    } else {
370 //                      graph.processor.processor.schedule(graph.callerThread, new SessionTask(suggestSchedule) {
371 //              
372 //                              @Override
373 //                              public void run(int thread) {
374 //                              procedure.execute(graph.newAsync(thread), context, new ResourceImpl(resourceSupport, id));
375 //                              }
376 //              
377 //                      });
378 //                    }
379                 }
380                         }
381                         
382                         try {
383                                 cluster.forObjects(graph, subject, context, procedure);
384                         } catch (DatabaseException e) {
385                                 e.printStackTrace();
386                         }
387                         
388                 } else {
389                         
390                         try {
391                                 cluster.forObjects(graph, subject, context, procedure);
392                         } catch (DatabaseException e) {
393                                 e.printStackTrace();
394                         }
395                         
396                 }
397                 
398         }
399         
400         @Override
401     public int getSingleInstance(final int subject) {
402         
403         // Do not process this information for virtual resources
404         if(subject < 0) return 0;
405         
406         final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
407         if (cluster == null)
408             System.out.println("null cluster: " + Integer.toString(subject, 16));
409         assert (cluster != null);
410
411         try {
412         
413                 ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subject, clusterSupport);
414                 if(ClusterI.CompleteTypeEnum.InstanceOf == type) {
415                         int result = cluster.getCompleteObjectKey(subject, clusterSupport);
416                         assert(result > 0);
417                         return result;
418                 } else {
419                         return 0;
420                 }
421         
422         } catch (DatabaseException e) {
423                 
424                 Logger.defaultLogError(e);
425                 return 0;
426                 
427         }
428         // This happens is the resource is bogus
429         catch (Throwable t) {
430                 
431                 analyseProblem(cluster);
432                 
433                 Logger.defaultLogError(t);
434                 
435                 return 0;
436                 
437         }
438         
439     }
440
441         @Override
442     public int getSingleSuperrelation(final int subject) {
443         
444         // Do not process this information for virtual resources
445         if(subject < 0) return 0;
446
447         final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
448         if (cluster == null)
449             System.out.println("null cluster: " + Integer.toString(subject, 16));
450         assert (cluster != null);
451
452         try {
453         
454                 ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subject, clusterSupport);
455                 if(ClusterI.CompleteTypeEnum.SubrelationOf == type) {
456                         int result = cluster.getCompleteObjectKey(subject, clusterSupport);
457                         assert(result > 0);
458                         return result;
459                 } else {
460                         return 0;
461                 }
462         
463         } catch (DatabaseException e) {
464                 
465                 Logger.defaultLogError(e);
466                 return 0;
467                 
468         }
469         
470     }
471
472         @Override
473     public boolean getObjects(final ReadGraphImpl graph, final int subject, final int predicate, final IntProcedure procedure) throws DatabaseException {
474                 
475                 assert (subject != 0);
476                 assert (predicate != 0);
477
478                 if(subject < 0) {
479
480                         boolean found = false;
481                         
482                         for(TransientGraph g : virtualGraphServerSupport.providers) {
483                                 for (final int id : g.getObjects(subject, predicate)) {
484                                         found = true;
485                                         procedure.execute(graph, id);
486                                 }
487                         }
488                         
489                         return found;
490
491                 }
492
493                 final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
494                 assert(cluster.isLoaded());
495         
496         if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject)) {
497                 
498                 final DataContainer<Boolean> found = new DataContainer<Boolean>(Boolean.FALSE);
499                 final TIntHashSet result = new TIntHashSet(5);
500                 
501                         for(TransientGraph g : virtualGraphServerSupport.providers) {
502                                 for (final int id : g.getObjects(subject, predicate)) {
503
504                                         found.set(true);
505                                         if (result.add(id)) {
506                                                 procedure.execute(graph, id);
507                                         }
508
509                                 }
510                         }
511                         
512                         // Virtual predicates are not found from persistent clusters
513                         if(predicate < 0) return found.get();
514
515                 // wheels within wheels
516                 final ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {
517
518                         @Override
519                         public boolean execute(Object context, int object) {
520
521                                 found.set(true);
522                                 if (result.add(object)) {
523                                         try {
524                                                         procedure.execute(graph, object);
525                                                 } catch (DatabaseException e) {
526                                                         Logger.defaultLogError(e);
527                                                 }
528                                 }
529
530                                 return false; // continue looping
531
532                         }
533
534                 };
535                         
536                         try {
537                 cluster.forObjects(subject, predicate, proc, null, clusterSupport);
538                         } catch (DatabaseException e) {
539                                 e.printStackTrace();
540                         }
541                         
542                         return found.get();
543                         
544                 } else {
545                         
546                         // Virtual predicates are not found from persistent clusters
547                         if(predicate < 0) return false;
548                         
549                         class A implements ClusterI.ObjectProcedure<Object> {
550
551                         boolean found = false;
552
553                         @Override
554                         public boolean execute(Object context, int object) {
555
556                                 found = true;
557                                 try {
558                                                 procedure.execute(graph, object);
559                                         } catch (DatabaseException e) {
560                                                 Logger.defaultLogError(e);
561                                         }
562                                 return false; // continue looping
563
564                         }
565
566                                 public boolean found() {
567                                         return found;
568                                 }
569
570                         }
571                         
572                 // wheels within wheels
573                 final A proc = new A();
574                 
575                         try {
576                 cluster.forObjects(subject, predicate, proc, null, clusterSupport);
577                         } catch (DatabaseException e) {
578                                 e.printStackTrace();
579                         } 
580                         // This happens if resource is bogus
581                         catch (Throwable t) {
582                                 
583                         analyseProblem(cluster);
584                         
585                         Logger.defaultLogError(t);
586                                 
587                         }
588                 
589                 return proc.found();
590                         
591                 }
592         
593     }
594
595 //      @Override
596 //    public boolean getFunctionalObject(final ReadGraphImpl graph, final int subject, final int predicate,
597 //            final IntProcedure procedure) {
598 //
599 //        assert (subject != 0);
600 //        assert (predicate != 0);
601 //
602 //        if(subject < 0) {
603 //
604 //              boolean found = false;
605 //
606 //              Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(subject);
607 //              if (providers != null) {
608 //
609 //                      for (VirtualGraph provider : providers) {
610 //
611 //                              for (int id : ((VirtualGraphImpl)provider).getObjects(subject, predicate)) {
612 //                                      found = true;
613 //                      procedure.execute(graph, id);
614 //                    }
615 //
616 //                }
617 //
618 //            }
619 //              
620 //              return found;
621 //              
622 //        }
623 //        
624 //        final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
625 //        
626 //        if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject)) {
627 //        
628 //              final DataContainer<Boolean> found = new DataContainer<Boolean>(false);
629 //              final TIntHashSet result = new TIntHashSet(5);
630 //
631 //              Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(subject);
632 //              if (providers != null) {
633 //
634 //                      for (VirtualGraph provider : providers) {
635 //
636 //                              for (int id : ((VirtualGraphImpl)provider).getObjects(subject, predicate)) {
637 //                                      found.set(true);
638 //                      procedure.execute(graph, id);
639 //                    }
640 //
641 //                }
642 //
643 //            }
644 //              
645 //            // wheels within wheels
646 //            final ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {
647 //
648 //                @Override
649 //                public boolean execute(int callerThread, Object context, int object) {
650 //
651 //                    found.set(true);
652 //                    System.out.println("-found object " + object);
653 //                    if (result.add(object)) {
654 //                      procedure.execute(graph.newAsync(callerThread), object);
655 //                    }
656 //
657 //                    return false; // continue looping
658 //
659 //                }
660 //                
661 //                              @Override
662 //                              public boolean found() {
663 //                                      throw new UnsupportedOperationException();
664 //                              }
665 //                
666 //            };
667 //            
668 //            try {
669 //                cluster.forObjects(graph.callerThread, subject, predicate, proc, null, clusterSupport);
670 //            } catch (DatabaseException e) {
671 //                Logger.defaultLogError(e);
672 //                return false;
673 //            } catch (Throwable t) {
674 //                Logger.defaultLogError(t);
675 //              t.printStackTrace();
676 //            }
677 //            
678 //            return found.get();
679 //            
680 //        } else {
681 //
682 //              // wheels within wheels
683 //              final ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {
684 //                  
685 //                      boolean found = false;
686 //                      
687 //                  @Override
688 //                  public boolean execute(int callerThread, Object context, int object) {
689 //      
690 //                      found = true;
691 //                      procedure.execute(graph.newAsync(callerThread), object);
692 //                      return false; // continue looping
693 //                      
694 //                  }
695 //                  
696 //                              @Override
697 //                              public boolean found() {
698 //                                      return found;
699 //                              }
700 //                  
701 //                  @Override
702 //                  public String toString() {
703 //                      return "Wheels for " + procedure;
704 //                  }
705 //                  
706 //              };
707 //              
708 //              try {
709 //                  cluster.forObjects(graph.callerThread, subject, predicate, proc, null, clusterSupport);
710 //              } catch (DatabaseException e) {
711 //                  Logger.defaultLogError(e);
712 //                  return false;
713 //              } catch (Throwable t) {
714 //                      t.printStackTrace();
715 //                  Logger.defaultLogError(t);
716 //                  return false;
717 //              }
718 //              
719 //              return proc.found();
720 //        
721 //        }
722 //        
723 //    }
724         
725         @Override
726     public int getFunctionalObject(final int subject, final int predicate) {
727
728         assert (subject != 0);
729         assert (predicate != 0);
730
731         if(subject < 0) {
732
733                 int found = 0;
734
735                 Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(subject);
736                 if (providers != null) {
737
738                         for (VirtualGraph provider : providers) {
739
740                                 for (int id : ((VirtualGraphImpl)provider).getObjects(subject, predicate)) {
741                                         if(found == 0) found = id;
742                                         else found = -1;
743                     }
744
745                 }
746
747             }
748                 
749                 return found;
750 //              if(found == -1) return 0;
751 //              else return found;
752                 
753         }
754         
755         final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
756         
757         if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject)) {
758
759                 int result = 0;
760                 Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(subject);
761                 if (providers != null) {
762
763                         for (VirtualGraph provider : providers) {
764
765                                 for (int id : ((VirtualGraphImpl)provider).getObjects(subject, predicate)) {
766                                         if(result == 0) result = id;
767                                         else result = -1;
768                     }
769
770                 }
771
772             }
773                 
774                 if(result != 0) return result; 
775             
776                 try {
777                                 return cluster.getSingleObject(subject, predicate, clusterSupport);
778                         } catch (DatabaseException e) {
779                                 return -1;
780                         }
781             
782         } else {
783
784                 try {
785                                 return cluster.getSingleObject(subject, predicate, clusterSupport);
786                         } catch (DatabaseException e) {
787                                 return -1;
788                         }
789                 // This comes if the resource is bogus
790                 catch (Throwable t) {
791                         
792                 analyseProblem(cluster);
793                 
794                 Logger.defaultLogError(t);
795                         
796                                 return -1;
797                                 
798                         }
799         
800         }
801         
802     }
803
804 //      @Override
805 //    public boolean getStatements(final ReadGraphImpl graph, final int subject, final int predicate,
806 //            final TripleIntProcedure procedure, final Statements entry) {
807 //
808 //        assert (subject != 0);
809 //        assert (predicate != 0);
810 //
811 //        final TIntHashSet result = new TIntHashSet(16);
812 //        final DataContainer<Boolean> found = new DataContainer<Boolean>(false);
813 //
814 //        Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(subject);
815 //        
816 //        if (providers != null) {
817 //
818 //            for (VirtualGraph provider : providers) {
819 //
820 //                for (int id : ((VirtualGraphImpl)provider).getObjects(subject, predicate)) {
821 //
822 //                    found.set(true);
823 //
824 //                    if (result.add(id)) {
825 //                        if (null != entry) {
826 //                            entry.addOrSet(subject, predicate, id);
827 //                            procedure.execute(graph, subject, predicate, id);
828 //                            return true; // break;
829 //                        } else {
830 //                            procedure.execute(graph, subject, predicate, id);
831 //                        }
832 //                    }
833 //
834 //                }
835 //
836 //            }
837 //
838 //        }
839 //
840 //        if (subject < 0)
841 //            return found.get();
842 //
843 //        final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
844 //        assert (cluster != null);
845 //
846 //        // wheels within wheels
847 //        final ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {
848 //            @Override
849 //            public boolean execute(int callerThread, Object context, int object) {
850 //
851 //                found.set(true);
852 //
853 //                if (result.add(object)) {
854 //                    if (null != entry) {
855 //                        entry.addOrSet(subject, predicate, object);
856 //                        procedure.execute(graph.newAsync(callerThread), subject, predicate, object);
857 //                        return true; // break;
858 //                    } else {
859 //                        procedure.execute(graph.newAsync(callerThread), subject, predicate, object);
860 //                    }
861 //                }
862 //
863 //                return false; // continue looping
864 //
865 //            }
866 //            
867 //                      @Override
868 //                      public boolean found() {
869 //                              throw new UnsupportedOperationException();
870 //                      }
871 //            
872 //        };
873 //
874 //        try {
875 //            cluster.forObjects(graph.callerThread, subject, predicate, proc, null, clusterSupport);
876 //        } catch (DatabaseException e) {
877 //            Logger.defaultLogError(e);
878 //        }
879 //        return found.get();
880 //
881 //    }
882
883         @Override
884     public org.simantics.db.DirectStatements getStatements(final ReadGraphImpl graph, final int subject, final QueryProcessor processor, boolean ignoreVirtual) {
885
886         assert (subject != 0);
887
888         final DirectStatementsImpl result = new DirectStatementsImpl(resourceSupport, subject);
889
890         if (!ignoreVirtual) {
891             Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(subject);
892             if (providers != null) {
893                 for (TransientGraph provider : providers) {
894                     for (int p : provider.getPredicates(subject)) {
895                         for (int o : provider.getObjects(subject, p)) {
896                             result.addStatement(p, o);
897                         }
898                     }
899                 }
900             }
901         }
902
903         if (subject < 0) {
904                 return result;
905         } else {
906             final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
907             assert (cluster != null);
908             doGetStatements(graph, cluster, subject, result);
909         }
910         
911         return result;
912
913     }
914
915     @Override
916     public void getPredicates(final ReadGraphImpl graph, final int subject, final IntProcedure procedure) throws DatabaseException {
917
918         final TIntHashSet result = new TIntHashSet(16);
919
920         Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(subject);
921         
922         if (providers != null) {
923
924             for (VirtualGraph provider : providers) {
925
926                 for (int id : ((VirtualGraphImpl)provider).getPredicates(subject)) {
927
928                     if (result.add(id)) {
929                         procedure.execute(graph, id);
930                     }
931
932                 }
933
934             }
935
936         }
937
938         if (subject < 0) {
939             procedure.finished(graph);
940             return;
941         }
942
943         ClusterI proxy = clusterTable.getClusterByResourceKey(subject);
944         assert (proxy != null);
945
946         final DataContainer<Integer> got = new DataContainer<Integer>(0);
947         ClusterI.PredicateProcedure<Object> proc = new ClusterI.PredicateProcedure<Object>() {
948             @Override
949             public boolean execute(Object context, int predicate, int oi) {
950                 if (result.add(predicate)) {
951                     try {
952                                                 procedure.execute(graph, predicate);
953                                         } catch (DatabaseException e) {
954                                                 Logger.defaultLogError(e);
955                                         }
956                 }
957                 got.set(got.get() + 1);
958                 return false; // continue looping
959             }
960         };
961         try {
962             proxy.forPredicates(subject, proc, null, clusterSupport);
963         } catch (DatabaseException e) {
964             Logger.defaultLogError(e);
965         }
966         procedure.finished(graph);
967
968     }
969     
970     
971
972 //    @Override
973 //    public void getValue(ReadGraphImpl graph, int resource, InternalProcedure<byte[]> procedure) {
974 //
975 //      if(resource < 0) {
976 //      
977 //              Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(resource);
978 //              
979 //              if (providers != null) {
980 //      
981 //                  for (VirtualGraph provider : providers) {
982 //      
983 //                      Object value = ((VirtualGraphImpl)provider).getValue(resource);
984 //                      if (value != null) {
985 //                          procedure.execute(graph, (byte[])value);
986 //                          return;
987 //                      }
988 //      
989 //                  }
990 //      
991 //              }
992 //              
993 //              return;
994 //        
995 //      }
996 //      
997 //      ClusterI cluster = clusterTable.getClusterByResourceKey(resource);
998 //        if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(resource)) {
999 //              
1000 //              Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(resource);
1001 //              
1002 //              if (providers != null) {
1003 //      
1004 //                  for (VirtualGraph provider : providers) {
1005 //      
1006 //                      Object value = ((VirtualGraphImpl)provider).getValue(resource);
1007 //                      if (value != null) {
1008 //                          procedure.execute(graph, (byte[])value);
1009 //                          return;
1010 //                      }
1011 //      
1012 //                  }
1013 //      
1014 //              }
1015 //              
1016 //              try {
1017 //                      
1018 //                      byte[] data = cluster.getValue(resource, clusterSupport);
1019 //                      if (null == data || 0 == data.length) {
1020 //                          procedure.execute(graph, null);
1021 //                      } else {
1022 //                          procedure.execute(graph, data);
1023 //                      }
1024 //                      
1025 //              } catch (DatabaseException e) {
1026 //                  Logger.defaultLogError(e);
1027 //              }
1028 //              
1029 //        } else {
1030 //
1031 //              try {
1032 //                      
1033 //                      byte[] data = cluster.getValue(resource, clusterSupport);
1034 //                      if (null == data || 0 == data.length) {
1035 //                          procedure.execute(graph, null);
1036 //                      } else {
1037 //                          procedure.execute(graph, data);
1038 //                      }
1039 //                      
1040 //              } catch (DatabaseException e) {
1041 //                  Logger.defaultLogError(e);
1042 //              }
1043 //
1044 //        }
1045 //
1046 //    }
1047
1048
1049     @Override
1050     public byte[] getValue(ReadGraphImpl graph, int resource) {
1051
1052         if(resource < 0) {
1053         
1054                 Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(resource);
1055                 
1056                 if (providers != null) {
1057         
1058                     for (VirtualGraph provider : providers) {
1059         
1060                         Object value = ((VirtualGraphImpl)provider).getValue(resource);
1061                         if (value != null) {
1062                                 return (byte[])value;
1063                         }
1064         
1065                     }
1066         
1067                 }
1068                 
1069                 return null;
1070         
1071         }
1072         
1073         ClusterI cluster = clusterTable.getClusterByResourceKey(resource);
1074         if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(resource)) {
1075                 
1076                 Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(resource);
1077                 
1078                 if (providers != null) {
1079         
1080                     for (VirtualGraph provider : providers) {
1081         
1082                         Object value = ((VirtualGraphImpl)provider).getValue(resource);
1083                         if (value != null) {
1084                                 return (byte[])value;
1085                         }
1086         
1087                     }
1088         
1089                 }
1090                 
1091                 try {
1092                         
1093                         byte[] data = cluster.getValue(resource, clusterSupport);
1094                         if (null != data && 0 != data.length) {
1095                                 return data;
1096                         }
1097                         
1098                 } catch (DatabaseException e) {
1099                     Logger.defaultLogError(e);
1100                 }
1101                 
1102                 return null;
1103                 
1104         } else {
1105
1106                 try {
1107                         
1108                         byte[] data = cluster.getValue(resource, clusterSupport);
1109                         if (null != data && 0 != data.length) {
1110                                 return data;
1111                         }
1112                         
1113                 } catch (DatabaseException e) {
1114                     Logger.defaultLogError(e);
1115                 }
1116                 
1117                 return null;
1118
1119         }
1120
1121     }
1122
1123     @Override
1124     public InputStream getValueStream(ReadGraphImpl graph, int resource) {
1125
1126         if(resource < 0) {
1127         
1128             Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(resource);
1129             
1130             if (providers != null) {
1131     
1132                 for (VirtualGraph provider : providers) {
1133     
1134                     Object value = ((VirtualGraphImpl)provider).getValue(resource);
1135                     if (value != null) {
1136                         return new ByteArrayInputStream((byte[])value);
1137                     }
1138     
1139                 }
1140     
1141             }
1142             
1143             return null;
1144         
1145         }
1146         
1147         ClusterI cluster = clusterTable.getClusterByResourceKey(resource);
1148         if (cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(resource)) {
1149             
1150             Collection<TransientGraph> providers = virtualGraphServerSupport.getVirtualGraphs(resource);
1151             
1152             if (providers != null) {
1153     
1154                 for (VirtualGraph provider : providers) {
1155     
1156                     Object value = ((VirtualGraphImpl)provider).getValue(resource);
1157                     if (value != null) {
1158                         return new ByteArrayInputStream((byte[])value);
1159                     }
1160     
1161                 }
1162     
1163             }
1164             
1165             try {
1166                 
1167                 return cluster.getValueStream(resource, clusterSupport);
1168                 
1169             } catch (DatabaseException e) {
1170                 Logger.defaultLogError(e);
1171             }
1172             
1173             return null;
1174             
1175         } else {
1176
1177             try {
1178                 
1179                 return cluster.getValueStream(resource, clusterSupport);
1180                 
1181             } catch (DatabaseException e) {
1182                 Logger.defaultLogError(e);
1183             }
1184             
1185             return null;
1186
1187         }
1188
1189     }
1190     
1191     @Override
1192     public void requestCluster(ReadGraphImpl graph, final long clusterId, final Runnable r) {
1193
1194         class CallbackAdapter implements Consumer<DatabaseException> {
1195                 final Runnable r;
1196                 CallbackAdapter(final Runnable r) {
1197                         this.r = r;
1198                 }
1199                 @Override
1200                 public void accept(DatabaseException e) {
1201                         if (null != e)
1202                                 e.printStackTrace();
1203                         else
1204                                 r.run();
1205                 }
1206                 
1207         }
1208         
1209         double p = clusterTable.getLoadProbability();
1210 // System.out.print("Load cluster " + clusterId + " with probability " + p +
1211         // " -> ");
1212         final ClusterI proxy = clusterSupport.getClusterByClusterId(clusterId);
1213         if (!proxy.isLoaded()) {
1214                 clusterTable.gc();
1215             if (Math.random() < p) {
1216                 proxy.load(new CallbackAdapter(r));
1217             } else {
1218                 r.run();
1219             }
1220         } else {
1221             r.run();
1222         }
1223
1224     }
1225
1226     @Override
1227     public int getBuiltin(String uri) {
1228         return builtinSupport.getBuiltin(uri);
1229     }
1230
1231     @Override
1232     public void checkTasks() {
1233         System.out.println(syncThreads.toString());
1234     }
1235
1236 //    @Override
1237 //    public void asyncWrite(Write request) {
1238 //        
1239 ////            if(plainWrite(writer) && sameProvider(request)) {
1240 ////                    writer.writeSupport.pushRequest(request);
1241 ////            } else {
1242 //              asyncRequest(request);
1243 ////            }
1244 //        
1245 //    }
1246
1247     /*
1248      * Helpers
1249      * 
1250      * 
1251      */
1252     
1253     private void doGetStatements(ReadGraphImpl graph, final ClusterI cluster, final int subject, final DirectStatementsImpl result) {
1254
1255         final class Proc implements ClusterI.PredicateProcedure<Object> {
1256
1257                         @Override
1258                         public boolean execute(Object context, final int predicate, final int objectIndex) {
1259                                 
1260                                 doExecute(null, predicate, objectIndex);
1261                                 return false;
1262                                 
1263                         }
1264
1265                         private void doExecute(Object context, final int predicate, final int objectIndex) {
1266
1267                                 try {
1268                                         cluster.forObjects(subject, predicate, new ClusterI.ObjectProcedure<Object>() {
1269
1270                                                 @Override
1271                                                 public boolean execute(Object context, int object) {
1272                                                         result.addStatement(predicate, object);
1273                                                         return false;
1274                                                 }
1275
1276                                         }, null, clusterSupport);
1277                                 } catch (DatabaseException e) {
1278                                         e.printStackTrace();
1279                                 }
1280                                 
1281                         }
1282                 
1283         }
1284
1285         try {
1286                         cluster.forPredicates(subject, new Proc(), null, clusterSupport);
1287                 } catch (DatabaseException e) {
1288                         e.printStackTrace();
1289                 }
1290         
1291     }
1292     
1293 //      private void getDirectObjects4(final int callerThread, final ClusterI cluster, final int subject, final int predicate, final QueryProcessor processor, final ReadGraphImpl graph, final ForEachObjectProcedure procedure) {
1294 //
1295 //        if(!cluster.isLoaded()) {
1296 //
1297 //                      requestCluster(callerThread, cluster.getClusterId(), new Callback<Integer>() {
1298 //      
1299 //                              @Override
1300 //                              public void run(Integer i) {
1301 //      
1302 //                                      processor.schedule(i, new SessionTask(callerThread) {
1303 //      
1304 //                                              @Override
1305 //                                              public void run(int thread) {
1306 //                                                      
1307 //                                                      getDirectObjects4(thread, cluster, subject, predicate, processor, graph, procedure);
1308 //                                                      
1309 //                                              }
1310 //      
1311 //                                      });
1312 //      
1313 //                              }
1314 //      
1315 //                      });
1316 //                      
1317 //        } else {
1318 //
1319 //              try {
1320 //                      cluster.forObjects(graph, subject, predicate, procedure);
1321 //              } catch (DatabaseException e) {
1322 //                      e.printStackTrace();
1323 //              }
1324 //              
1325 ////                    procedure.finished(graph);
1326 ////                    graph.state.barrier.dec();
1327 ////                    
1328 ////            System.err.println("ai2=" + ai2.decrementAndGet());
1329 //              
1330 //        }
1331 //              
1332 //              
1333 //      }
1334
1335 //      AtomicInteger ai2  =new AtomicInteger(0);
1336         
1337 //    private boolean testCluster(int subject, ClusterI proxy) {
1338 //      
1339 //        if (proxy == null)
1340 //            System.out.println("null cluster: " + Integer.toString(subject, 16));
1341 //        
1342 //        return proxy != null;
1343 //      
1344 //    }
1345
1346     long getCluster(int id) {
1347         // Virtual resource
1348         if(id < 0) return 0;
1349         ClusterI proxy = clusterTable.getClusterByResourceKey(id);
1350         if(proxy == null) return 0;
1351         else return proxy.getClusterId();
1352     }
1353
1354         @Override
1355         public int getRandomAccessReference(String id) throws ResourceNotFoundException {
1356                 
1357                 try {
1358                         Resource res = serializationSupport.getResourceSerializer().getResource(id);
1359                         if(res == null) return 0;
1360                         else return ((ResourceImpl)res).id;
1361                 } catch (InvalidResourceReferenceException e) {
1362                         //e.printStackTrace();
1363                 }
1364                 return 0;
1365                 
1366         }
1367         
1368         @Override
1369         public void ensureLoaded(final ReadGraphImpl graph, final int subject, final int predicate) {
1370                 
1371                 if(subject < 0) {
1372                         
1373                         SessionImplSocket.loadVirtualStatements(virtualGraphServerSupport, graph, subject, predicate, g -> {});
1374                         
1375                 } else {
1376                         
1377                 final ClusterI cluster = clusterTable.checkedGetClusterByResourceKey(subject);
1378
1379                 if(cluster.isLoaded()) {
1380                         
1381                         if(cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject) && !SessionImplSocket.areVirtualStatementsLoaded(virtualGraphServerSupport, subject, predicate)) {
1382
1383                                         SessionImplSocket.loadVirtualStatements(virtualGraphServerSupport, graph, subject, predicate, g -> {});
1384                                 
1385                                 } else {
1386                                         
1387                                 }
1388                         
1389                 } else {
1390                         
1391                                 new Exception().printStackTrace();
1392                         
1393                         cluster.load(session.clusterTranslator, new Runnable() {
1394
1395                                         @Override
1396                                         public void run() {
1397                                                 
1398                                         if(cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject) && !SessionImplSocket.areVirtualStatementsLoaded(virtualGraphServerSupport, subject, predicate)) {
1399
1400                                                         SessionImplSocket.loadVirtualStatements(virtualGraphServerSupport, graph, subject, predicate, g -> {});
1401                                                 
1402                                                 } else {
1403                                                         
1404                                                 }
1405                                                 
1406                                         }
1407                                 
1408                         });
1409                         
1410                 }
1411                 
1412                 
1413                 }
1414                 
1415         }
1416         
1417         @Override
1418         public void ensureLoaded(final ReadGraphImpl graph, final int subject) {
1419                 
1420                 if(subject < 0) {
1421                         
1422                         SessionImplSocket.loadVirtualStatements(virtualGraphServerSupport, graph, subject, g -> {});
1423                         
1424                 } else {
1425                         
1426                 final ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
1427
1428                 if(cluster.isLoaded()) {
1429                         
1430                         if(cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject) && !SessionImplSocket.areVirtualStatementsLoaded(virtualGraphServerSupport, subject)) {
1431
1432                                         SessionImplSocket.loadVirtualStatements(virtualGraphServerSupport, graph, subject, g -> {});
1433                                 
1434                                 } else {
1435                                         
1436                                 }
1437                         
1438                 } else {
1439                         
1440 //                      System.err.println("cluster not loaded " + subject);
1441                                 new Exception().printStackTrace();
1442                         
1443                         cluster.load(session.clusterTranslator, new Runnable() {
1444
1445                                         @Override
1446                                         public void run() {
1447                                                 
1448                                         if(cluster.hasVirtual() && virtualGraphServerSupport.virtuals.contains(subject) && !SessionImplSocket.areVirtualStatementsLoaded(virtualGraphServerSupport, subject)) {
1449
1450                                                         SessionImplSocket.loadVirtualStatements(virtualGraphServerSupport, graph, subject, g -> {});
1451                                                 
1452                                                 } else {
1453                                                         
1454                                                 }
1455                                                 
1456                                         }
1457                                 
1458                         });
1459                         
1460                 }
1461                 
1462                 
1463                 }
1464                 
1465         }
1466
1467         @Override
1468         public boolean isLoaded(int subject) {
1469         ClusterI cluster = clusterTable.getClusterByResourceKey(subject);
1470         return cluster.isLoaded();
1471         }
1472         
1473         @Override
1474         public void ceased(int thread) {
1475                 
1476                 session.ceased(thread);
1477                 
1478         }
1479
1480     @Override
1481     public Object getLock() {
1482         
1483         return session.requestManager;
1484         
1485     }
1486
1487     @Override
1488     public VirtualGraph getProvider(int subject, int predicate, int object) {
1489
1490         if(subject > 0) {
1491             ClusterImpl cluster = (ClusterImpl)clusterTable.getClusterByResourceKey(subject);
1492                 // This persistent resource does not have virtual statements => must deny in persistent graph
1493                 if(!cluster.hasVirtual() || !virtualGraphServerSupport.virtuals.contains(subject)) return null;
1494         }
1495         
1496         for(TransientGraph g : virtualGraphServerSupport.providers) {
1497                 for (final int id : g.getObjects(subject, predicate)) {
1498                         if(object == id) return g;
1499                 }
1500         }
1501         
1502         // Nothing found from virtual graphs
1503         return null;
1504                 
1505     }
1506
1507     @Override
1508     public VirtualGraph getProvider(int subject, int predicate) {
1509
1510         if(subject > 0) {
1511             ClusterImpl cluster = (ClusterImpl)clusterTable.getClusterByResourceKey(subject);
1512                 // This persistent resource does not have virtual statements => must deny in persistent graph
1513                 if(!cluster.hasVirtual() || !virtualGraphServerSupport.virtuals.contains(subject)) return null;
1514         }
1515
1516         TransientGraph result = null;
1517         for(TransientGraph g : virtualGraphServerSupport.providers) {
1518                 if(g.getObjects(subject, predicate).length > 0) {
1519                         // Found multiple, return null;
1520                         if(result != null) return null;
1521                         else result = g;
1522                 }
1523         }
1524         return result;
1525                 
1526     }
1527
1528     @Override
1529     public VirtualGraph getValueProvider(int subject) {
1530
1531         if(subject > 0) {
1532             ClusterImpl cluster = (ClusterImpl)clusterTable.getClusterByResourceKey(subject);
1533                 // This persistent resource does not have virtual statements => must deny in persistent graph
1534                 if(!cluster.hasVirtual() || !virtualGraphServerSupport.virtuals.contains(subject)) return null;
1535         }
1536
1537         TransientGraph result = null;
1538         for(TransientGraph g : virtualGraphServerSupport.providers) {
1539                 if(g.getValue(subject) != null) {
1540                         if(result != null) return null;
1541                         else result = g;
1542                 }
1543         }
1544         return result;
1545                 
1546     }
1547     
1548     @Override
1549     public void exit(Throwable t) {
1550         state.close();
1551     }
1552     
1553     private void analyseProblem(ClusterI cluster) {
1554         
1555         if(cluster instanceof ClusterSmall)
1556                         try {
1557                                 ((ClusterSmall)cluster).check();
1558                         } catch (DatabaseException e) {
1559                                 e.printStackTrace();
1560                         }
1561         
1562     }
1563     
1564 }