]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQuery.java
Multiple reader thread support for db client
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / RelationInfoQuery.java
index d32da5be54bfcf324f4555ff1740cb5cd258a3c6..0b60fdd0c596a144fd9ccf5f7211786fdaf5c839 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2018 Association for Decentralized Information Management
  * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  *******************************************************************************/
 package org.simantics.db.impl.query;
 
-import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicBoolean;
-
 import org.simantics.db.RelationInfo;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.impl.graph.ReadGraphImpl;
 import org.simantics.db.impl.procedure.InternalProcedure;
-import org.simantics.db.procedure.ListenerBase;
 import org.simantics.db.request.RequestFlags;
 
-final public class RelationInfoQuery extends UnaryQuery<InternalProcedure<RelationInfo>> {
-    
-//     public ArrayList<InternalProcedure<RelationInfo>> procs = null;
-
-       private RelationInfoQuery(final int resource) {
-        super(resource);
-    }
-    
-    final static RelationInfo runner(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<RelationInfo> procedure) {
+public final class RelationInfoQuery extends UnaryQueryP<RelationInfo> {
 
-       RelationInfoQuery entry = (RelationInfoQuery)provider.relationInfoMap.get(r);
-        if(entry == null) {
-               
-               entry = new RelationInfoQuery(r);
-               entry.setPending();
-               entry.clearResult(provider.querySupport);
-               entry.putEntry(provider);
-               
-            provider.performForEach(graph, entry, parent, listener, procedure);
-            
-            return entry.getResult();
-            
-        } else {
-               
-            if(!entry.isReady()) {
-               synchronized(entry) {
-                    if(!entry.isReady()) {
-                        throw new IllegalStateException();
-//                     if(entry.procs == null) entry.procs = new ArrayList<InternalProcedure<RelationInfo>>();
-//                                     entry.procs.add(procedure);
-//                        provider.registerDependencies(graph, entry, parent, listener, procedure, false);
-//                                     return entry.getResult();
-                    }
-               }
-            }
-            provider.performForEach(graph, entry, parent, listener, procedure);
-            
-            return entry.getResult();
-            
-        }
+       RelationInfoQuery(int resource) {
+               super(resource);
+       }
 
-    }
-    
-    final public static RelationInfo queryEach(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<RelationInfo> procedure) {
-        
-       RelationInfoQuery entry = (RelationInfoQuery)provider.relationInfoMap.get(r);
-       if(entry != null && entry.isReady()) {
-               entry.performFromCache(graph, provider, procedure);
-               return entry.getResult();
-       }
+       @Override
+       public final void removeEntry(QueryProcessor provider) {
+               provider.cache.remove(this);
+       }
 
-        return runner(graph, r, provider, parent, listener, procedure);
-         
-    }
-     
-    final public static RelationInfoQuery probe(ReadGraphImpl graph, int resource) {
-        
-        final int thread = graph.thread(resource);
-       RelationInfoQuery entry = (RelationInfoQuery)graph.processor.relationInfoMap.get(resource);
-       if(entry != null && entry.isReady()) {
-               return entry;
-       } else {
-               return null;
-       }
-         
-    }
+       private static void computeAssertions(ReadGraphImpl graph, int r, final boolean isFinal, final boolean isFunctional, RelationInfoQuery parent, final InternalProcedure<RelationInfo> procedure) throws DatabaseException {
 
-    @Override
-       public UnaryQuery<InternalProcedure<RelationInfo>> getEntry(QueryProcessor provider) {
-        return provider.relationInfoMap.get(id);
-       }
-       
-       @Override
-       public void putEntry(QueryProcessor provider) {
-        provider.relationInfoMap.put(id, this);
-       }
+               QueryProcessor processor = graph.processor;
 
-       @Override
-       final public void removeEntry(QueryProcessor provider) {
-               provider.relationInfoMap.remove(id);
-       }
+               final int isUsedInAssertion = processor.getHasPredicateInverse();
+               assert(isUsedInAssertion != 0);
 
-       private void computeAssertions(ReadGraphImpl graph, final boolean isFinal, final boolean isFunctional, final QueryProcessor queryProvider, final InternalProcedure<RelationInfo> proc) {
+               QueryCache.runnerDirectObjects(graph, r, isUsedInAssertion, parent, null, new IntProcedure() {
 
-           final int isUsedInAssertion = queryProvider.getHasPredicateInverse();
-        assert(isUsedInAssertion != 0);
-               
-        DirectObjects.queryEach(graph, id, isUsedInAssertion, queryProvider, this, null, new IntProcedure() {
+                       boolean done = false;
 
-                       AtomicBoolean done = new AtomicBoolean(false);
-                       
                        @Override
-                       public void execute(ReadGraphImpl graph, int i) {
-                               if(done.compareAndSet(false, true)) {
-//                                     System.err.println("Assertions for relation " + id);
-                                       RelationInfo result = new RelationInfo(id, isFunctional, isFinal, true);
-                                       addOrSet(graph, result, queryProvider);
-                                       proc.execute(graph, result);
-                               }
+                       public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                               if(done) return;
+                               done = true;
+                               RelationInfo result = new RelationInfo(r, isFunctional, isFinal, true);
+                               procedure.execute(graph, result);
                        }
 
                        @Override
-                       public void finished(ReadGraphImpl graph) {
-                               if(done.compareAndSet(false, true)) {
-//                                     System.err.println("No assertions for relation " + id);
-                                       RelationInfo result = new RelationInfo(id, isFunctional, isFinal, false);
-                                       addOrSet(graph, result, queryProvider);
-                                       proc.execute(graph, result);
-                               }
+                       public void finished(ReadGraphImpl graph) throws DatabaseException {
+                               if(done) return;
+                               done = true;
+                               RelationInfo result = new RelationInfo(r, isFunctional, isFinal, false);
+                               procedure.execute(graph, result);
                        }
 
                        @Override
-                       public void exception(ReadGraphImpl graph, Throwable throwable) {
-                               if(done.compareAndSet(false, true)) {
-                                       DatabaseException e = new DatabaseException("Internal error in RelationInfoQuery");
-                                       except(e);
-                                       proc.exception(graph, e);
-                               }
+                       public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
+                               if(done) return;
+                               done = true;
+                               DatabaseException e = new DatabaseException("Internal error in RelationInfoQuery");
+                               procedure.exception(graph, e);
                        }
-                       
-               });
-               
-//         Types.queryEach(callerThread, id, queryProvider, this, null, new InternalProcedure<IntSet>() {
-//             
-//          @Override
-//          public void execute(int callerThread, IntSet types) {
-//               computeAssertions(callerThread, isFinal, isFunctional, queryProvider, proc);
-////             
-////             
-//////              System.out.println("RelationInfoQuery: computeTypes execute " + types);
-////
-////              RelationInfo result = new RelationInfo(id, types.contains(queryProvider.getFunctionalRelation()), isFinal);
-////              
-////              addOrSet(callerThread, result, queryProvider);
-////              
-////              proc.execute(callerThread, result);
-////              
-//          }
-//                     
-//                     @Override
-//                     public void exception(int callerThread, Throwable t) {
-//                             proc.exception(callerThread, t);
-//          }
-//
-//      });
 
-       }
-       
-       private void computeTypes(ReadGraphImpl graph, final boolean isFinal, final QueryProcessor queryProvider, final InternalProcedure<RelationInfo> proc) {
-        
-//        System.out.println("RelationInfoQuery: computeTypes " + id);
-
-           Types.queryEach(graph, id, queryProvider, this, null, new InternalProcedure<IntSet>() {
-               
-            @Override
-            public void execute(ReadGraphImpl graph, IntSet types) {
-               computeAssertions(graph, isFinal, types.contains(queryProvider.getFunctionalRelation()), queryProvider, proc);
-//
-////                System.out.println("RelationInfoQuery: computeTypes execute " + types);
-//
-//                RelationInfo result = new RelationInfo(id, types.contains(queryProvider.getFunctionalRelation()), isFinal);
-//                
-//                addOrSet(callerThread, result, queryProvider);
-//                
-//                proc.execute(callerThread, result);
-//                
-            }
-                       
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               proc.exception(graph, t);
-            }
+               });
 
-        });
+       }
 
-       }
-       
-       @Override
-       public Object computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final InternalProcedure<RelationInfo> procedure, boolean store) {
-           
-//        System.out.println("RelationInfoQuery computeForEach begin " + id + " " + getResult() + " " + statusOrException);
+       public static void computeForEach(ReadGraphImpl graph, int r, RelationInfoQuery entry, InternalProcedure<RelationInfo> procedure_) throws DatabaseException {
 
-           final int superRelationOf = provider.getSuperrelationOf();
-        assert(superRelationOf != 0);
-        
-        DirectPredicates.queryEach(graph, id, provider, this, null, new IntProcedure() {
-            
-            boolean found = false;
+               InternalProcedure<RelationInfo> procedure = entry != null ? entry : procedure_;
 
-            @Override
-            public void execute(ReadGraphImpl graph, int i) {
-//                System.out.println("RelationInfoQuery: execute " + i + " super = " + superRelationOf);
-                if(i == superRelationOf) {
-                    computeTypes(graph, false, provider, procedure);
-                    found = true;
-                }
-            }
+               QueryProcessor provider = graph.processor;
 
-            @Override
-            public void finished(ReadGraphImpl graph) {
-//                System.out.println("RelationInfoQuery: finished");
-                if(!found) {
-                    computeTypes(graph, true, provider, procedure);
-                }
-            }
-            
-            @Override
-            public void exception(ReadGraphImpl graph, Throwable t) {
-//                System.out.println("RelationInfoQuery: exception");
-                procedure.exception(graph, t);
-            }
+               final int superRelationOf = provider.getSuperrelationOf();
+               assert(superRelationOf != 0);
 
-        });
-        
-        return getResult();
-        
-    }
-    
-    @Override
-    public String toString() {
-       return "RelationInfoQuery[" + id + "]";
-    }
+               IntSet direct = QueryCache.resultDirectPredicates(graph, r, entry, null);
+               IntSet types = QueryCache.resultTypes(graph, r, entry, null);
 
-    public void addOrSet(ReadGraphImpl graph, final RelationInfo result, final QueryProcessor provider) {
-        
-       assert(isPending());
-       
-//     ArrayList<InternalProcedure<RelationInfo>> p = null;
-       
-       synchronized(this) {
+               computeAssertions(graph, r, !direct.contains(superRelationOf), types.contains(graph.processor.getFunctionalRelation()), entry, procedure);
 
-           setResult(result);
-           setReady();
-        
-//             p = procs;
-//             procs = null;
-               
-       }
-       
-//     if(p != null) {
-//          for(InternalProcedure<RelationInfo> proc : p) 
-//              proc.execute(graph, (RelationInfo)result);
-//     }
-        
-    }            
+               if(entry != null) entry.performFromCache(graph, procedure_);
 
-    @Override
-    public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, InternalProcedure<RelationInfo> procedure) {
+       }
 
-        assert(isReady());
-        
-       if(handleException(graph, procedure)) return EXCEPTED;
-        
-       RelationInfo result = getResult();
-       
-        procedure.execute(graph, result);
-        
-        return result;
+       @Override
+       public void compute(ReadGraphImpl graph, final InternalProcedure<RelationInfo> procedure) throws DatabaseException {
+               computeForEach(graph, id, this, procedure);
+       }
 
-    }
-    
-    @Override
-    public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
-        
-        final Semaphore s = new Semaphore(0);
-        
-        computeForEach(graph, provider, new InternalProcedure<RelationInfo>() {
+       @Override
+       public String toString() {
+               return "RelationInfoQuery[" + id + "]";
+       }
 
-            @Override
-            public void execute(ReadGraphImpl graph, RelationInfo result) {
-                s.release();
-            }
-            
-            @Override
-            public void exception(ReadGraphImpl graph, Throwable t) {
-                throw new Error("Error in recompute.", t);
-            }
+       @Override
+       public void setResult(Object result) {
+               super.setResult(result);
+               setReady();
+       }
 
-        }, true);
-        
-       while(!s.tryAcquire()) {
-               provider.resume(graph);
-       }
-//        try {
-//            s.acquire();
-//        } catch (InterruptedException e) {
-//            throw new Error(e);
-//        }
+       @Override
+       public int type() {
+               return RequestFlags.IMMEDIATE_UPDATE;
+       }
 
-    }
-    
-    @Override
-    public int type() {
-        return RequestFlags.IMMEDIATE_UPDATE;
-    }
-    
 }