]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / DirectQuerySupportImpl.java
diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java
new file mode 100644 (file)
index 0000000..3e6e852
--- /dev/null
@@ -0,0 +1,1080 @@
+package fi.vtt.simantics.procore.internal;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.DirectStatements;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RelationInfo;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure;\r
+import org.simantics.db.common.procedure.wrapper.SyncToAsyncProcedure;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.impl.ClusterI;\r
+import org.simantics.db.impl.ClusterI.ClusterTypeEnum;\r
+import org.simantics.db.impl.ForEachObjectContextProcedure;\r
+import org.simantics.db.impl.ForEachObjectProcedure;\r
+import org.simantics.db.impl.ForPossibleRelatedValueContextProcedure;\r
+import org.simantics.db.impl.ForPossibleRelatedValueProcedure;\r
+import org.simantics.db.impl.ResourceImpl;\r
+import org.simantics.db.impl.TransientGraph;\r
+import org.simantics.db.impl.graph.ReadGraphImpl;\r
+import org.simantics.db.procedure.AsyncContextMultiProcedure;\r
+import org.simantics.db.procedure.AsyncContextProcedure;\r
+import org.simantics.db.procedure.AsyncMultiProcedure;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.db.procedure.Procedure;\r
+import org.simantics.db.procedure.SyncProcedure;\r
+import org.simantics.db.procore.cluster.ClusterBig;\r
+import org.simantics.db.procore.cluster.ClusterImpl;\r
+import org.simantics.db.procore.cluster.ClusterSmall;\r
+import org.simantics.db.procore.cluster.ResourceTableSmall;\r
+import org.simantics.db.procore.cluster.ValueTableSmall;\r
+import org.simantics.db.request.AsyncRead;\r
+import org.simantics.db.service.DirectQuerySupport;\r
+import org.simantics.utils.datastructures.Callback;\r
+\r
+public class DirectQuerySupportImpl implements DirectQuerySupport {\r
+\r
+       final private SessionImplSocket session;\r
+       \r
+       DirectQuerySupportImpl(SessionImplSocket session) {\r
+               this.session = session;\r
+       }\r
+\r
+       @Override\r
+       final public void forEachDirectPersistentStatement(AsyncReadGraph graph, final Resource subject, final AsyncProcedure<DirectStatements> procedure) {\r
+               ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+               impl.processor.forEachDirectStatement(impl, subject, procedure, true);\r
+       }\r
+\r
+       @Override\r
+       final public void forEachDirectStatement(AsyncReadGraph graph, final Resource subject, final AsyncProcedure<DirectStatements> procedure) {\r
+               ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+               impl.processor.forEachDirectStatement(impl, subject, procedure, false);\r
+       }\r
+\r
+       @Override\r
+       public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, SyncProcedure<DirectStatements> procedure) {\r
+               forEachDirectStatement(graph, subject, new SyncToAsyncProcedure<DirectStatements>(procedure));\r
+       }\r
+\r
+       @Override\r
+       public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, Procedure<DirectStatements> procedure) {\r
+               ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+               impl.processor.forEachDirectStatement(impl, subject, procedure);\r
+       }\r
+\r
+       @Override\r
+       public void forRelationInfo(AsyncReadGraph graph, Resource subject, AsyncProcedure<RelationInfo> procedure) {\r
+               ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+               impl.processor.forRelationInfo(impl, subject, procedure);\r
+       }\r
+\r
+       @Override\r
+       public void forRelationInfo(AsyncReadGraph graph, Resource subject, SyncProcedure<RelationInfo> procedure) {\r
+               forRelationInfo(graph, subject, new SyncToAsyncProcedure<RelationInfo>(procedure));\r
+       }\r
+\r
+       @Override\r
+       public void forRelationInfo(AsyncReadGraph graph, Resource subject, Procedure<RelationInfo> procedure) {\r
+               forRelationInfo(graph, subject, new NoneToAsyncProcedure<RelationInfo>(procedure));\r
+       }\r
+\r
+       @Override\r
+       public AsyncMultiProcedure<Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncMultiProcedure<Resource> user) {\r
+               \r
+               try {\r
+                       RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {\r
+\r
+                               @Override\r
+                               public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {\r
+                                       forRelationInfo(graph, relation, procedure);\r
+                               }\r
+\r
+                @Override\r
+                   public int threadHash() {\r
+                       return hashCode();\r
+                   }\r
+\r
+                               @Override\r
+                               public int getFlags() {\r
+                                       return 0;\r
+                               }\r
+\r
+                       });\r
+               final int predicateKey = ((ResourceImpl)relation).id;\r
+                       return new ForEachObjectProcedure(predicateKey, info, session.queryProvider2, user);\r
+               } catch (DatabaseException e) {\r
+                       return null;\r
+               }               \r
+        \r
+       }\r
+\r
+       @Override\r
+       public <C> AsyncContextMultiProcedure<C, Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncContextMultiProcedure<C, Resource> user) {\r
+               \r
+               try {\r
+                       RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {\r
+\r
+                               @Override\r
+                               public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {\r
+                                       forRelationInfo(graph, relation, procedure);\r
+                               }\r
+\r
+                @Override\r
+                   public int threadHash() {\r
+                       return hashCode();\r
+                   }\r
+\r
+                               @Override\r
+                               public int getFlags() {\r
+                                       return 0;\r
+                               }\r
+\r
+                       });\r
+               final int predicateKey = ((ResourceImpl)relation).id;\r
+                       return new ForEachObjectContextProcedure<C>(predicateKey, info, session.queryProvider2, user);\r
+               } catch (DatabaseException e) {\r
+                       return null;\r
+               }               \r
+        \r
+       }\r
+       \r
+       @Override\r
+       public <T> AsyncProcedure<T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncProcedure<T> user) {\r
+               \r
+               try {\r
+                       RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {\r
+\r
+                               @Override\r
+                               public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {\r
+                                       forRelationInfo(graph, relation, procedure);\r
+                               }\r
+\r
+                @Override\r
+                   public int threadHash() {\r
+                       return hashCode();\r
+                   }\r
+\r
+                               @Override\r
+                               public int getFlags() {\r
+                                       return 0;\r
+                               }\r
+\r
+                       });\r
+               final int predicateKey = ((ResourceImpl)relation).id;\r
+                       return new ForPossibleRelatedValueProcedure<T>(predicateKey, info, user);\r
+               } catch (DatabaseException e) {\r
+                       return null;\r
+               }               \r
+        \r
+       }\r
+\r
+       @Override\r
+       public <C, T> AsyncContextProcedure<C, T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncContextProcedure<C, T> user) {\r
+               \r
+               try {\r
+                       RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {\r
+\r
+                               @Override\r
+                               public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {\r
+                                       forRelationInfo(graph, relation, procedure);\r
+                               }\r
+\r
+                @Override\r
+                   public int threadHash() {\r
+                       return hashCode();\r
+                   }\r
+\r
+                               @Override\r
+                               public int getFlags() {\r
+                                       return 0;\r
+                               }\r
+\r
+                       });\r
+               final int predicateKey = ((ResourceImpl)relation).id;\r
+                       return new ForPossibleRelatedValueContextProcedure<C, T>(predicateKey, info, user);\r
+               } catch (DatabaseException e) {\r
+                       return null;\r
+               }               \r
+        \r
+       }\r
+       \r
+       @Override\r
+       public void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, final AsyncMultiProcedure<Resource> procedure) {\r
+               \r
+        assert(subject != null);\r
+        \r
+        final ForEachObjectProcedure proc = (ForEachObjectProcedure)procedure;\r
+//        final RelationInfo info = proc.info;\r
+\r
+        final ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+        final int subjectId = ((ResourceImpl)subject).id;\r
+\r
+//        int callerThread = impl.callerThread;\r
+//        int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;\r
+        \r
+//        impl.inc();\r
+        \r
+//        if(callerThread == suggestSchedule) {\r
+               \r
+//             if(info.isFunctional) {\r
+//                     querySupport.getObjects4(impl, subjectId, proc);\r
+//             } else {\r
+               session.querySupport.getObjects4(impl, subjectId, proc);\r
+//             }\r
+               \r
+//        } else {\r
+//             \r
+//             impl.state.barrier.inc();\r
+//            impl.state.barrier.dec(callerThread);\r
+//             \r
+//             queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {\r
+//     \r
+//                     @Override\r
+//                     public void run(int thread) {\r
+//                             \r
+//                     impl.state.barrier.inc(thread);\r
+//                             impl.state.barrier.dec();\r
+//\r
+//                     if(info.isFunctional) {\r
+//                             querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);\r
+//                     } else {\r
+//                             querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);\r
+//                     }\r
+//                             \r
+//                     }\r
+//                     \r
+//                     @Override\r
+//                     public String toString() {\r
+//                             return "gaff8";\r
+//                     }\r
+//     \r
+//             });\r
+//             \r
+//        }\r
+               \r
+       }\r
+\r
+       @Override\r
+       public <C> void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextMultiProcedure<C, Resource> procedure) {\r
+               \r
+               assert(subject != null);\r
+\r
+               final ForEachObjectContextProcedure<C> proc = (ForEachObjectContextProcedure<C>)procedure;\r
+               final RelationInfo info = proc.info;\r
+\r
+               final ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+               final int subjectId = ((ResourceImpl)subject).id;\r
+\r
+//             int callerThread = impl.callerThread;\r
+//             int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;\r
+\r
+//             impl.inc();\r
+\r
+               if(info.isFunctional) {\r
+                       session.querySupport.getObjects4(impl, subjectId, context, proc);\r
+               } else {\r
+                       session.querySupport.getObjects4(impl, subjectId, context, proc);\r
+               }\r
+               \r
+       }\r
+       \r
+       @Override\r
+       public <T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, final AsyncProcedure<T> procedure) {\r
+               \r
+               assert(subject != null);\r
+\r
+        final ForPossibleRelatedValueProcedure<T> proc = (ForPossibleRelatedValueProcedure<T>)procedure;\r
+        final RelationInfo info = proc.info;\r
+        \r
+        final ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+        final int subjectId = ((ResourceImpl)subject).id;\r
+        \r
+//        int callerThread = impl.callerThread;\r
+//        int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;\r
+        \r
+//        impl.inc();\r
+        \r
+//        if(callerThread == suggestSchedule) {\r
+               \r
+               if(info.isFunctional) {\r
+                       getRelatedValue4(impl, subjectId, proc);\r
+               } else {\r
+                       getRelatedValue4(impl, subjectId, proc);\r
+               }\r
+               \r
+//        } else {\r
+//             \r
+//             impl.state.barrier.inc();\r
+//            impl.state.barrier.dec(callerThread);\r
+//             \r
+//             queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {\r
+//     \r
+//                     @Override\r
+//                     public void run(int thread) {\r
+//\r
+//                     impl.state.barrier.inc(thread);\r
+//                     impl.state.barrier.dec();\r
+//                             \r
+//                     if(info.isFunctional) {\r
+//                             getRelatedValue4(impl.newAsync(thread), subjectId, proc);\r
+//                     } else {\r
+//                             getRelatedValue4(impl.newAsync(thread), subjectId, proc);\r
+//                     }\r
+//                             \r
+//                     }\r
+//                     \r
+//                     @Override\r
+//                     public String toString() {\r
+//                             return "gaff11";\r
+//                     }\r
+//     \r
+//             });\r
+//             \r
+//        }\r
+               \r
+       }\r
+\r
+       @Override\r
+       public <C, T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextProcedure<C, T> procedure) {\r
+               \r
+               assert(subject != null);\r
+\r
+        final ForPossibleRelatedValueContextProcedure<C, T> proc = (ForPossibleRelatedValueContextProcedure<C, T>)procedure;\r
+        final RelationInfo info = proc.info;\r
+        \r
+        final ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+        final int subjectId = ((ResourceImpl)subject).id;\r
+        \r
+//        int callerThread = impl.callerThread;\r
+//        int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;\r
+        \r
+//        impl.inc();\r
+               \r
+        if(info.isFunctional) {\r
+               getRelatedValue4(impl, subjectId, context, proc);\r
+        } else {\r
+               getRelatedValue4(impl, subjectId, context, proc);\r
+        }\r
+               \r
+       }\r
+       \r
+       @Override\r
+       public <T> void forPossibleType(final AsyncReadGraph graph, Resource subject, final AsyncProcedure<Resource> procedure) {\r
+               \r
+        assert(subject != null);\r
+\r
+        final ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+        final int subjectId = ((ResourceImpl)subject).id;\r
+\r
+        try {\r
+               \r
+               final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);\r
+               if(!cluster.isLoaded()) {\r
+\r
+//                     impl.state.inc(0);\r
+                       \r
+                       session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {\r
+               \r
+                                       @Override\r
+                                       public void run() {\r
+\r
+                                       try {\r
+\r
+                                                       int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);\r
+                                               procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));\r
+\r
+//                                             impl.state.dec(0);                                              \r
+                                               \r
+                                       } catch (DatabaseException e) {\r
+                                               e.printStackTrace();\r
+                                       }\r
+               \r
+                                       }\r
+               \r
+                               });\r
+                               \r
+               } else {\r
+\r
+                       int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);\r
+                       procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));\r
+                       \r
+               }\r
+               \r
+        } catch (DatabaseException e) {\r
+               e.printStackTrace();\r
+        }\r
+       \r
+       \r
+               \r
+       }\r
+\r
+       @Override\r
+       public <C> void forPossibleDirectType(final AsyncReadGraph graph, Resource subject, final C context, final AsyncContextProcedure<C, Resource> procedure) {\r
+               \r
+        assert(subject != null);\r
+\r
+        final ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+        final int subjectId = ((ResourceImpl)subject).id;\r
+        \r
+        try {\r
+               \r
+               final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);\r
+               if(!cluster.isLoaded()) {\r
+\r
+//                     impl.state.inc(0);\r
+                       \r
+                       session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {\r
+               \r
+                                       @Override\r
+                                       public void run() {\r
+\r
+                                       try {\r
+\r
+                                               ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);\r
+                                               if(ClusterI.CompleteTypeEnum.InstanceOf == type) {\r
+                                                       int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);\r
+                                                       procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));\r
+                                               } else {\r
+                                               procedure.execute(graph, context, null);\r
+                                               }\r
+\r
+//                                             impl.state.dec(0);\r
+                                               \r
+                                       } catch (DatabaseException e) {\r
+                                               e.printStackTrace();\r
+                                       }\r
+               \r
+                                       }\r
+               \r
+                               });\r
+                               \r
+               } else {\r
+\r
+                       ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);\r
+                       if(ClusterI.CompleteTypeEnum.InstanceOf == type) {\r
+                               int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);\r
+                               procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));\r
+                       } else {\r
+                       procedure.execute(graph, context, null);\r
+                       }\r
+                       \r
+               }\r
+               \r
+        } catch (DatabaseException e) {\r
+               \r
+               procedure.execute(graph, context, null);\r
+               \r
+        } catch (Throwable t) {\r
+\r
+               t.printStackTrace();\r
+               procedure.execute(graph, context, null);\r
+               \r
+        }\r
+               \r
+       }\r
+       \r
+       \r
+       private <C, T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {\r
+               \r
+               int result = 0;\r
+               \r
+               final int predicate = procedure.predicateKey;\r
+\r
+               if(subject < 0) {\r
+\r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getRelatedValue4(graph, subject, context, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+                       \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                for (int id : g.getObjects(subject, predicate)) {\r
+                       if(result != 0) {\r
+                               procedure.exception(graph, new DatabaseException("Multiple objects"));\r
+//                             graph.dec();\r
+                               return;\r
+                       } else {\r
+                               result = id;\r
+                       }\r
+                }\r
+                       }\r
+                       \r
+                       if(result == 0) {\r
+                               \r
+                       procedure.exception(graph, new DatabaseException("No objects for " + subject ));\r
+//                     graph.dec();\r
+                       return;\r
+                       \r
+                       } else {\r
+                               \r
+                               getValue4(graph, null, result, context, procedure);\r
+                               return;\r
+                               \r
+                       }\r
+                       \r
+               } \r
+               \r
+        final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+        if(!cluster.isLoaded()) {\r
+               cluster.load(session.clusterTranslator, new Runnable() {\r
+\r
+                               @Override\r
+                               public void run() {\r
+                                       getRelatedValue4(graph, subject, context, procedure);\r
+                               }\r
+                       \r
+               });\r
+               return;\r
+        }\r
+        \r
+        if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {\r
+                       \r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getRelatedValue4(graph, subject, context, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+               \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                for (int id : g.getObjects(subject, predicate)) {\r
+                       if(result != 0) {\r
+                               procedure.exception(graph, new DatabaseException("Multiple objects"));\r
+//                             graph.dec();\r
+                               return;\r
+                       } else {\r
+                               result = id;\r
+                       }\r
+                }\r
+                       }\r
+                       \r
+                       getRelatedDirectValue4(graph, cluster, subject, result, context, procedure);\r
+                       \r
+               } else {\r
+                       \r
+                       getRelatedDirectValue4(graph, cluster, subject, 0, context, procedure);\r
+                       \r
+               }\r
+               \r
+       }\r
+       \r
+       private <T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {\r
+               \r
+               Object result = null;\r
+       \r
+               if(subject < 0) {\r
+\r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getValue4(graph, containerCluster, subject, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+                       \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                               Object value = g.getValue(subject);\r
+                               if(value != null) {\r
+                                       if(result != null) {\r
+                                               procedure.exception(graph, new DatabaseException("Multiple values"));\r
+//                                             graph.dec();\r
+                                               return;\r
+                                       } else {\r
+                                               result = value;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       procedure.execute(graph, (T)"name");\r
+//                     graph.dec();\r
+                       return;\r
+\r
+               }\r
+               \r
+               ClusterImpl cluster = containerCluster;\r
+               if(!containerCluster.contains(subject)) {\r
+                       cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+                       if(!cluster.isLoaded()) {\r
+                               cluster.load(session.clusterTranslator, new Runnable() {\r
+\r
+                                       @Override\r
+                                       public void run() {\r
+                                               getValue4(graph, containerCluster, subject, procedure);\r
+                                       }\r
+\r
+                               });\r
+                               return;\r
+                       }\r
+               }\r
+               \r
+        if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {\r
+\r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getValue4(graph, containerCluster, subject, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+               \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                               Object value = g.getValue(subject);\r
+                               if(value != null) {\r
+                                       if(result != null) {\r
+                                               procedure.exception(graph, new DatabaseException("Multiple values"));\r
+//                                             graph.dec();\r
+                                               return;\r
+                                       } else {\r
+                                               result = value;\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       if(result != null) {\r
+                               \r
+                               procedure.execute(graph, (T)result);\r
+//                             graph.state.barrier.dec();\r
+                               \r
+                       } else {\r
+                               \r
+                               if(ClusterTypeEnum.SMALL == cluster.getType())\r
+                                       getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);\r
+                               else \r
+                                       getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);\r
+                       }\r
+\r
+               } else {\r
+\r
+                       if(ClusterTypeEnum.SMALL == cluster.getType())\r
+                               getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);\r
+                       else \r
+                               getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);\r
+\r
+               }\r
+       \r
+       }\r
+       \r
+       private <C, T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {\r
+               \r
+               Object result = null;\r
+       \r
+               if(subject < 0) {\r
+\r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getValue4(graph, containerCluster, subject, context, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+                       \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                               Object value = g.getValue(subject);\r
+                               if(value != null) {\r
+                                       if(result != null) {\r
+                                               procedure.exception(graph, new DatabaseException("Multiple values"));\r
+//                                             graph.dec();\r
+                                               return;\r
+                                       } else {\r
+                                               result = value;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       procedure.execute(graph, context, (T)"name");\r
+//                     graph.dec();\r
+                       return;\r
+\r
+               }\r
+               \r
+               ClusterImpl cluster = containerCluster;\r
+               if(!containerCluster.contains(subject)) {\r
+                       cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+                       if(!cluster.isLoaded()) {\r
+                               cluster.load(session.clusterTranslator, new Runnable() {\r
+\r
+                                       @Override\r
+                                       public void run() {\r
+                                               getValue4(graph, containerCluster, subject, context, procedure);\r
+                                       }\r
+\r
+                               });\r
+                               return;\r
+                       }\r
+               }\r
+               \r
+        if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {\r
+\r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getValue4(graph, containerCluster, subject, context, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+               \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                               Object value = g.getValue(subject);\r
+                               if(value != null) {\r
+                                       if(result != null) {\r
+                                               procedure.exception(graph, new DatabaseException("Multiple values"));\r
+//                                             graph.dec();\r
+                                               return;\r
+                                       } else {\r
+                                               result = value;\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       if(result != null) {\r
+                               \r
+                               procedure.execute(graph, context, (T)result);\r
+//                             graph.state.barrier.dec();\r
+                               \r
+                       } else {\r
+                               \r
+                               if(ClusterTypeEnum.SMALL == cluster.getType())\r
+                                       getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);\r
+                               else \r
+                                       getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);\r
+                       }\r
+\r
+               } else {\r
+\r
+                       if(ClusterTypeEnum.SMALL == cluster.getType())\r
+                               getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);\r
+                       else \r
+                               getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);\r
+\r
+               }\r
+       \r
+       }\r
+\r
+       private <T> void getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final ForPossibleRelatedValueProcedure<T> procedure) {\r
+\r
+               try {\r
+\r
+                       int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);\r
+                       if(so == 0) {\r
+                               if(result == 0) {\r
+                                       procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));\r
+//                                     graph.dec();\r
+                               } else {\r
+                                       getValue4(graph, cluster, result, procedure);\r
+                               }\r
+                       } else {\r
+                               if(result == 0) {\r
+                                       getValue4(graph, cluster, so, procedure);\r
+                               } else {\r
+                                       procedure.exception(graph, new DatabaseException("Multiple objects"));\r
+//                                     graph.dec();\r
+                               }\r
+                       }\r
+\r
+               } catch (DatabaseException e) {\r
+                       e.printStackTrace();\r
+               }\r
+               \r
+       }\r
+\r
+       private <C, T> void getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {\r
+\r
+               try {\r
+\r
+                       int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);\r
+                       if(so == 0) {\r
+                               if(result == 0) {\r
+                                       procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));\r
+//                                     graph.dec();\r
+                               } else {\r
+                                       getValue4(graph, cluster, result, context, procedure);\r
+                               }\r
+                       } else {\r
+                               if(result == 0) {\r
+                                       getValue4(graph, cluster, so, context, procedure);\r
+                               } else {\r
+                                       procedure.exception(graph, new DatabaseException("Multiple objects"));\r
+//                                     graph.dec();\r
+                               }\r
+                       }\r
+\r
+               } catch (DatabaseException e) {\r
+                       e.printStackTrace();\r
+               }\r
+               \r
+       }\r
+       \r
+       public <T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {\r
+               \r
+               int result = 0;\r
+               \r
+               final int predicate = procedure.predicateKey;\r
+\r
+               if(subject < 0) {\r
+\r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getRelatedValue4(graph, subject, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+                       \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                for (int id : g.getObjects(subject, predicate)) {\r
+                       if(result != 0) {\r
+                               procedure.exception(graph, new DatabaseException("Multiple objects"));\r
+//                             graph.dec();\r
+                               return;\r
+                       } else {\r
+                               result = id;\r
+                       }\r
+                }\r
+                       }\r
+                       \r
+                       if(result == 0) {\r
+                               \r
+                       procedure.exception(graph, new DatabaseException("No objects for " + subject ));\r
+//                     graph.dec();\r
+                       return;\r
+                       \r
+                       } else {\r
+                               \r
+                               getValue4(graph, null, result, procedure);\r
+                               return;\r
+                               \r
+                       }\r
+                       \r
+               } \r
+               \r
+        final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+        if(!cluster.isLoaded()) {\r
+               cluster.load(session.clusterTranslator, new Runnable() {\r
+\r
+                               @Override\r
+                               public void run() {\r
+                                       getRelatedValue4(graph, subject, procedure);\r
+                               }\r
+                       \r
+               });\r
+               return;\r
+        }\r
+        \r
+        if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {\r
+                       \r
+                       if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {\r
+                           SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>()  {\r
+\r
+                                       @Override\r
+                                       public void run(ReadGraphImpl graph) {\r
+                                               getRelatedValue4(graph, subject, procedure);\r
+                                       }\r
+                                       \r
+                               });\r
+                               return;\r
+                       }\r
+               \r
+                       for(TransientGraph g : session.virtualGraphServerSupport.providers) {\r
+                for (int id : g.getObjects(subject, predicate)) {\r
+                       if(result != 0) {\r
+                               procedure.exception(graph, new DatabaseException("Multiple objects"));\r
+//                             graph.dec();\r
+                               return;\r
+                       } else {\r
+                               result = id;\r
+                       }\r
+                }\r
+                       }\r
+                       \r
+                       getRelatedDirectValue4(graph, cluster, subject, result, procedure);\r
+                       \r
+               } else {\r
+                       \r
+                       getRelatedDirectValue4(graph, cluster, subject, 0, procedure);\r
+                       \r
+               }\r
+               \r
+       }\r
+       \r
+       private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {\r
+               \r
+               try {\r
+                       byte[] bytes = cluster.getValue(subject, session.clusterTranslator);\r
+                       T value = (T)utf(bytes);\r
+                       procedure.execute(graph, context, value);\r
+               } catch (DatabaseException e) {\r
+                       procedure.execute(graph, context, null);\r
+               }\r
+\r
+//             graph.dec();\r
+               \r
+       }\r
+\r
+       private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {\r
+               \r
+               try {\r
+                       byte[] bytes = cluster.getValue(subject, session.clusterTranslator);\r
+                       T value = (T)utf(bytes);\r
+                       procedure.execute(graph, value);\r
+               } catch (DatabaseException e) {\r
+                       procedure.execute(graph, null);\r
+               }\r
+\r
+//             graph.dec();\r
+               \r
+       }\r
+\r
+       private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {\r
+               \r
+               try {\r
+                       byte[] bytes = cluster.getValue(subject, session.clusterTranslator);\r
+                       if(bytes == null) {\r
+                               procedure.execute(graph, context, null);\r
+                       } else {\r
+                               T value = (T)utf(bytes);\r
+                               procedure.execute(graph, context, value);\r
+                       }\r
+               } catch (DatabaseException e) {\r
+                       procedure.execute(graph, context, null);\r
+               }\r
+\r
+//             graph.dec();\r
+               \r
+       }\r
+       \r
+       private final char[] chars = new char[1024];\r
+       \r
+       private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {\r
+\r
+               ResourceTableSmall rt = cluster.resourceTable;\r
+               ValueTableSmall vt = cluster.valueTable;\r
+\r
+               byte[] bs = vt.table;\r
+               long[] ls = rt.table;\r
+\r
+               int index = ((subject&0xFFFF) << 1) - 1 + rt.offset;\r
+\r
+               int valueIndex = (int)(ls[index] >>> 24) & 0x3FFFFF + vt.offset;\r
+\r
+               int size = (int)bs[valueIndex++]-1;\r
+               valueIndex++;\r
+               for(int i=0;i<size;i++) {\r
+                       chars[i] = (char)bs[valueIndex++];\r
+               }\r
+\r
+               T value = (T)new String(chars, 0, size);\r
+\r
+               procedure.execute(graph, value);\r
+//             graph.dec();\r
+               \r
+       }\r
+\r
+       final private String utf(byte[] bytes) {\r
+               \r
+               if(bytes == null) return null;\r
+               \r
+               int index = 0;\r
+               int length = bytes[index++]&0xff; \r
+               if(length >= 0x80) {\r
+                       if(length >= 0xc0) {\r
+                               if(length >= 0xe0) {\r
+                                       if(length >= 0xf0) {\r
+                                               length &= 0x0f;\r
+                                               length += ((bytes[index++]&0xff)<<3);\r
+                                               length += ((bytes[index++]&0xff)<<11);\r
+                                               length += ((bytes[index++]&0xff)<<19);\r
+                                               length += 0x10204080;\r
+                                       }\r
+                                       else {\r
+                                               length &= 0x1f;\r
+                                               length += ((bytes[index++]&0xff)<<4);\r
+                                               length += ((bytes[index++]&0xff)<<12);\r
+                                               length += ((bytes[index++]&0xff)<<20);\r
+                                               length += 0x204080;\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       length &= 0x3f;\r
+                                       length += ((bytes[index++]&0xff)<<5);\r
+                                       length += ((bytes[index++]&0xff)<<13);\r
+                                       length += 0x4080;\r
+                               }\r
+                       }\r
+                       else {\r
+                               length &= 0x7f;\r
+                               length += ((bytes[index++]&0xff)<<6);\r
+                               length += 0x80;\r
+                       }\r
+               }\r
+               \r
+               int i = 0;\r
+               int target = length+index;\r
+               while(index < target) {\r
+                       int c = bytes[index++]&0xff;\r
+                       if(c <= 0x7F) {\r
+                               chars[i++] = (char)(c&0x7F);\r
+                       } else if (c > 0x07FF) {\r
+                               int c2 = bytes[index++]&0xff;\r
+                               int c3 = bytes[index++]&0xff;\r
+                               chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f)); \r
+                       } else {\r
+                               int c2 = bytes[index++]&0xff;\r
+                               chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f)); \r
+                       }\r
+                       \r
+                       \r
+//                     if (!((c >= 0x0001) && (c <= 0x007F))) {\r
+//                     } else {\r
+//                     }\r
+//                     \r
+//                             if ((c >= 0x0001) && (c <= 0x007F)) {\r
+//                                     bytearr[byteIndex++] = (byte)( c );\r
+//                             } else if (c > 0x07FF) {\r
+//                                     bytearr[byteIndex++] = (byte)(0xE0 | ((c >> 12) & 0x0F));\r
+//                                     bytearr[byteIndex++] = (byte)(0x80 | ((c >>  6) & 0x3F));\r
+//                                     bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));\r
+//                             } else {\r
+//                                     bytearr[byteIndex++] = (byte)(0xC0 | ((c >>  6) & 0x1F));\r
+//                                     bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));\r
+//                             }\r
+//                     }\r
+                       \r
+                       \r
+               }\r
+               return new String(chars, 0, i);\r
+       }\r
+       \r
+}\r