]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQuery.java
f2081d35f767c9fced6b3814feb2393b0b68bca2
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / RelationInfoQuery.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.impl.query;
13
14 import java.util.concurrent.Semaphore;
15 import java.util.concurrent.atomic.AtomicBoolean;
16
17 import org.simantics.db.RelationInfo;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.impl.graph.ReadGraphImpl;
20 import org.simantics.db.impl.procedure.InternalProcedure;
21 import org.simantics.db.procedure.ListenerBase;
22 import org.simantics.db.request.RequestFlags;
23
24 final public class RelationInfoQuery extends UnaryQuery<InternalProcedure<RelationInfo>> {
25
26         private RelationInfoQuery(final int resource) {
27         super(resource);
28     }
29     
30     final static RelationInfo runner(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<RelationInfo> procedure) {
31
32         RelationInfoQuery entry = (RelationInfoQuery)provider.cache.relationInfoMap.get(r);
33         if(entry == null) {
34                 
35                 entry = new RelationInfoQuery(r);
36                 entry.setPending();
37                 entry.clearResult(provider.querySupport);
38                 entry.putEntry(provider);
39                 
40             provider.performForEach(graph, entry, parent, listener, procedure);
41             
42             return entry.getResult();
43             
44         } else {
45                 
46             if(!entry.isReady()) {
47                 synchronized(entry) {
48                     if(!entry.isReady()) {
49                         throw new IllegalStateException();
50 //                      if(entry.procs == null) entry.procs = new ArrayList<InternalProcedure<RelationInfo>>();
51 //                                      entry.procs.add(procedure);
52 //                        provider.registerDependencies(graph, entry, parent, listener, procedure, false);
53 //                                      return entry.getResult();
54                     }
55                 }
56             }
57             provider.performForEach(graph, entry, parent, listener, procedure);
58             
59             return entry.getResult();
60             
61         }
62
63     }
64     
65     final public static RelationInfo queryEach(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<RelationInfo> procedure) {
66         
67         RelationInfoQuery entry = (RelationInfoQuery)provider.cache.relationInfoMap.get(r);
68         if(entry != null && entry.isReady()) {
69                 entry.performFromCache(graph, provider, procedure);
70                 return entry.getResult();
71         }
72
73         return runner(graph, r, provider, parent, listener, procedure);
74          
75     }
76      
77     final public static RelationInfoQuery probe(ReadGraphImpl graph, int resource) {
78         
79         final int thread = graph.thread(resource);
80         RelationInfoQuery entry = (RelationInfoQuery)graph.processor.cache.relationInfoMap.get(resource);
81         if(entry != null && entry.isReady()) {
82                 return entry;
83         } else {
84                 return null;
85         }
86          
87     }
88
89     @Override
90         public UnaryQuery<InternalProcedure<RelationInfo>> getEntry(QueryProcessor provider) {
91         return provider.cache.relationInfoMap.get(id);
92         }
93         
94         @Override
95         public void putEntry(QueryProcessor provider) {
96         provider.cache.relationInfoMap.put(id, this);
97         }
98
99         @Override
100         final public void removeEntry(QueryProcessor provider) {
101                 provider.cache.relationInfoMap.remove(id);
102         }
103
104         private void computeAssertions(ReadGraphImpl graph, final boolean isFinal, final boolean isFunctional, final QueryProcessor queryProvider, final InternalProcedure<RelationInfo> proc) {
105
106             final int isUsedInAssertion = queryProvider.getHasPredicateInverse();
107         assert(isUsedInAssertion != 0);
108                 
109         DirectObjects.queryEach(graph, id, isUsedInAssertion, queryProvider, this, null, new IntProcedure() {
110
111                         AtomicBoolean done = new AtomicBoolean(false);
112                         
113                         @Override
114                         public void execute(ReadGraphImpl graph, int i) {
115                                 if(done.compareAndSet(false, true)) {
116 //                                      System.err.println("Assertions for relation " + id);
117                                         RelationInfo result = new RelationInfo(id, isFunctional, isFinal, true);
118                                         addOrSet(graph, result, queryProvider);
119                                         proc.execute(graph, result);
120                                 }
121                         }
122
123                         @Override
124                         public void finished(ReadGraphImpl graph) {
125                                 if(done.compareAndSet(false, true)) {
126 //                                      System.err.println("No assertions for relation " + id);
127                                         RelationInfo result = new RelationInfo(id, isFunctional, isFinal, false);
128                                         addOrSet(graph, result, queryProvider);
129                                         proc.execute(graph, result);
130                                 }
131                         }
132
133                         @Override
134                         public void exception(ReadGraphImpl graph, Throwable throwable) {
135                                 if(done.compareAndSet(false, true)) {
136                                         DatabaseException e = new DatabaseException("Internal error in RelationInfoQuery");
137                                         except(e);
138                                         proc.exception(graph, e);
139                                 }
140                         }
141                         
142                 });
143                 
144 //          Types.queryEach(callerThread, id, queryProvider, this, null, new InternalProcedure<IntSet>() {
145 //              
146 //          @Override
147 //          public void execute(int callerThread, IntSet types) {
148 //                computeAssertions(callerThread, isFinal, isFunctional, queryProvider, proc);
149 ////              
150 ////              
151 //////              System.out.println("RelationInfoQuery: computeTypes execute " + types);
152 ////
153 ////              RelationInfo result = new RelationInfo(id, types.contains(queryProvider.getFunctionalRelation()), isFinal);
154 ////              
155 ////              addOrSet(callerThread, result, queryProvider);
156 ////              
157 ////              proc.execute(callerThread, result);
158 ////              
159 //          }
160 //                      
161 //                      @Override
162 //                      public void exception(int callerThread, Throwable t) {
163 //                              proc.exception(callerThread, t);
164 //          }
165 //
166 //      });
167
168         }
169         
170         private void computeTypes(ReadGraphImpl graph, final boolean isFinal, final QueryProcessor queryProvider, final InternalProcedure<RelationInfo> proc) {
171         
172 //        System.out.println("RelationInfoQuery: computeTypes " + id);
173
174             Types.queryEach(graph, id, queryProvider, this, null, new InternalProcedure<IntSet>() {
175                 
176             @Override
177             public void execute(ReadGraphImpl graph, IntSet types) {
178                 computeAssertions(graph, isFinal, types.contains(queryProvider.getFunctionalRelation()), queryProvider, proc);
179 //
180 ////                System.out.println("RelationInfoQuery: computeTypes execute " + types);
181 //
182 //                RelationInfo result = new RelationInfo(id, types.contains(queryProvider.getFunctionalRelation()), isFinal);
183 //                
184 //                addOrSet(callerThread, result, queryProvider);
185 //                
186 //                proc.execute(callerThread, result);
187 //                
188             }
189                         
190                         @Override
191                         public void exception(ReadGraphImpl graph, Throwable t) {
192                                 proc.exception(graph, t);
193             }
194
195         });
196
197         }
198         
199         @Override
200         public Object computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final InternalProcedure<RelationInfo> procedure, boolean store) {
201             
202 //        System.out.println("RelationInfoQuery computeForEach begin " + id + " " + getResult() + " " + statusOrException);
203
204             final int superRelationOf = provider.getSuperrelationOf();
205         assert(superRelationOf != 0);
206         
207         DirectPredicates.queryEach(graph, id, provider, this, null, new IntProcedure() {
208             
209             boolean found = false;
210
211             @Override
212             public void execute(ReadGraphImpl graph, int i) {
213 //                System.out.println("RelationInfoQuery: execute " + i + " super = " + superRelationOf);
214                 if(i == superRelationOf) {
215                     computeTypes(graph, false, provider, procedure);
216                     found = true;
217                 }
218             }
219
220             @Override
221             public void finished(ReadGraphImpl graph) {
222 //                System.out.println("RelationInfoQuery: finished");
223                 if(!found) {
224                     computeTypes(graph, true, provider, procedure);
225                 }
226             }
227             
228             @Override
229             public void exception(ReadGraphImpl graph, Throwable t) {
230 //                System.out.println("RelationInfoQuery: exception");
231                 procedure.exception(graph, t);
232             }
233
234         });
235         
236         return getResult();
237         
238     }
239     
240     @Override
241     public String toString() {
242         return "RelationInfoQuery[" + id + "]";
243     }
244
245     public void addOrSet(ReadGraphImpl graph, final RelationInfo result, final QueryProcessor provider) {
246         
247         assert(isPending());
248         
249 //      ArrayList<InternalProcedure<RelationInfo>> p = null;
250         
251         synchronized(this) {
252
253             setResult(result);
254             setReady();
255         
256 //              p = procs;
257 //              procs = null;
258                 
259         }
260         
261 //      if(p != null) {
262 //          for(InternalProcedure<RelationInfo> proc : p) 
263 //              proc.execute(graph, (RelationInfo)result);
264 //      }
265         
266     }            
267
268     @Override
269     public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, InternalProcedure<RelationInfo> procedure) {
270
271         assert(isReady());
272         
273         if(handleException(graph, procedure)) return EXCEPTED;
274         
275         RelationInfo result = getResult();
276         
277         procedure.execute(graph, result);
278         
279         return result;
280
281     }
282     
283     @Override
284     public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
285         
286         final Semaphore s = new Semaphore(0);
287         
288         computeForEach(graph, provider, new InternalProcedure<RelationInfo>() {
289
290             @Override
291             public void execute(ReadGraphImpl graph, RelationInfo result) {
292                 s.release();
293             }
294             
295             @Override
296             public void exception(ReadGraphImpl graph, Throwable t) {
297                 throw new Error("Error in recompute.", t);
298             }
299
300         }, true);
301         
302         while(!s.tryAcquire()) {
303                 provider.resume(graph);
304         }
305 //        try {
306 //            s.acquire();
307 //        } catch (InterruptedException e) {
308 //            throw new Error(e);
309 //        }
310
311     }
312     
313     @Override
314     public int type() {
315         return RequestFlags.IMMEDIATE_UPDATE;
316     }
317     
318 }