]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java
fc3cbebab6753460c3b396831845d11b13bdf937
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / SuperRelations.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 gnu.trove.procedure.TIntProcedure;
15 import gnu.trove.set.hash.TIntHashSet;
16
17 import java.util.concurrent.Semaphore;
18 import java.util.concurrent.atomic.AtomicInteger;
19
20 import org.simantics.db.impl.graph.ReadGraphImpl;
21 import org.simantics.db.impl.procedure.InternalProcedure;
22 import org.simantics.db.procedure.ListenerBase;
23
24 final public class SuperRelations extends UnaryQuery<InternalProcedure<IntSet>> {
25     
26     private SuperRelations(final int resource) {
27         super(resource);
28     }
29     
30     final static SuperRelations entry(final QueryProcessor provider, final int r) {
31         
32         return (SuperRelations)provider.cache.superRelationsMap.get(r);
33
34     }
35
36     final static IntSet runner(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) {
37
38         SuperRelations entry = (SuperRelations)provider.cache.superRelationsMap.get(r);
39         if(entry == null) {
40
41                 entry = new SuperRelations(r);
42                 entry.setPending();
43                 entry.clearResult(provider.querySupport);
44                 entry.putEntry(provider);
45                 
46                 return (IntSet)provider.performForEach(graph, entry, parent, listener, procedure);
47             
48         } else {
49                 
50             if(!entry.isReady()) {
51                 throw new IllegalStateException();
52             }
53             return (IntSet)provider.performForEach(graph, entry, parent, listener, procedure);
54             
55         }
56
57     }
58     
59     final static IntSet runner2(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) throws Throwable {
60
61         SuperRelations entry = (SuperRelations)provider.cache.superRelationsMap.get(r);
62         if(entry == null) {
63
64             entry = new SuperRelations(r);
65             entry.setPending();
66             entry.clearResult(provider.querySupport);
67             entry.putEntry(provider);
68             
69             return (IntSet)provider.performForEach2(graph, entry, parent, listener, procedure);
70             
71         } else {
72             
73             if(!entry.isReady()) {
74                 throw new IllegalStateException();
75             }
76             return (IntSet)provider.performForEach2(graph, entry, parent, listener, procedure);
77             
78         }
79
80     }    
81     
82     final public static void queryEach(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) {
83
84         if(parent == null && listener == null) {
85                 SuperRelations entry = (SuperRelations)provider.cache.superRelationsMap.get(r);
86                 if(entry != null && entry.isReady()) {
87                     entry.performFromCache(graph, provider, procedure);
88                     return;
89                 }
90         }
91         
92         runner(graph, r, provider, parent, listener, procedure);
93          
94     }
95
96     final public static IntSet queryEach2(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) throws Throwable {
97
98         if(parent == null && listener == null) {
99             SuperRelations entry = (SuperRelations)provider.cache.superRelationsMap.get(r);
100             if(entry != null && entry.isReady()) {
101                 return (IntSet)entry.get(graph, provider, procedure);
102             }
103         }
104         
105         return runner2(graph, r, provider, parent, listener, procedure);
106          
107     }
108     
109         @Override
110         public UnaryQuery<InternalProcedure<IntSet>> getEntry(QueryProcessor provider) {
111         return provider.cache.superRelationsMap.get(id);
112         }
113         
114         @Override
115         public void putEntry(QueryProcessor provider) {
116         provider.cache.superRelationsMap.put(id, this);
117         }
118
119         @Override
120         final public void removeEntry(QueryProcessor provider) {
121                 provider.cache.superRelationsMap.remove(id);
122         }
123         
124         static int histoCounter = 0;
125         static IntSet EMPTY_SET = new IntSet();
126     static int counter = 0;
127     
128     class Koss {
129         
130         private TIntHashSet set = null;
131         public int single = 0;
132         
133         public boolean add(int val) {
134             if(single == val) return false;
135             if(single == 0) {
136                 single = val;
137                 return true;
138             }
139             if(set == null) set = new TIntHashSet(4);
140             return set.add(val);
141         }
142         
143         public int size() {
144             
145             if(single == 0) return 0;
146             if(set == null) return 1;
147             return set.size() + 1;
148             
149         }
150
151         public void forEach(TIntProcedure proc) {
152             if(single > 0) proc.execute(single);
153             if(set != null) set.forEach(proc);
154         }
155         
156     }
157
158         @Override
159         public Object computeForEach(final ReadGraphImpl graph, final QueryProcessor provider, final InternalProcedure<IntSet> procedure, final boolean store) {
160
161                 provider.querySupport.ensureLoaded(graph, id);
162                 
163             final InternalProcedure<IntSet> proc = (InternalProcedure<IntSet>)procedure;
164
165             final int subrelationOf = provider.getSubrelationOf();
166
167             final IntSet result = new IntSet(provider.querySupport);
168
169             final class DirectProcedure extends Koss implements IntProcedure, TIntProcedure, InternalProcedure<IntSet> {
170                 @Override
171                 final public boolean execute(int r) {
172                         result.add(r);
173                         return true;
174                 }
175                 @Override
176                 final public void execute(ReadGraphImpl graph, int r) {
177                         if(single == 0) {
178                                 single = r;
179                                 return;
180                         }
181                         add(r);
182                 }
183                 @Override
184                 final public void execute(ReadGraphImpl graph, IntSet set) {
185                         set.forEach(this);
186                         addOrSet(graph, result, provider);
187                         proc.execute(graph, result);
188                 }
189                 @Override
190                 public void finished(ReadGraphImpl graph) {
191                 }
192                 @Override
193                 public void exception(ReadGraphImpl graph, Throwable t) {
194                         throw new Error("Errors are not supported.", t);
195                 }
196
197             }
198
199             final DirectProcedure directProc = new DirectProcedure();
200
201             provider.querySupport.getObjects(graph, id, subrelationOf, directProc);
202
203             int size = directProc.size();
204
205             if(size == 0) {
206
207                 addOrSet(graph, EMPTY_SET, provider);
208                 proc.execute(graph, EMPTY_SET);
209
210             } else if (size == 1) {
211
212                 result.add(directProc.single);
213                 SuperRelations.queryEach(graph, directProc.single, provider, SuperRelations.this, null, directProc);
214
215             } else {
216
217                 //                  if((counter++ % 500) == 0) System.out.println("SR " + counter);
218
219                 final TIntProcedure addToResult = new TIntProcedure() {
220                         @Override
221                         public boolean execute(int r) {
222                                 synchronized(result) {
223                                         result.add(r);
224                                 }
225                                 return true;
226                         }
227                 };
228
229                 final AtomicInteger finishes = new AtomicInteger(0);
230
231                 directProc.forEach(new TIntProcedure() {
232
233                         @Override
234                         public boolean execute(int arg0) {
235
236                                 synchronized(result) {
237                                         result.add(arg0);
238                                 }
239
240                                 SuperRelations.queryEach(graph, arg0, provider, SuperRelations.this, null, new InternalProcedure<IntSet>() {
241
242                                         @Override
243                                         public void execute(ReadGraphImpl graph, IntSet set) {
244                                                 set.forEach(addToResult);
245                                                 int current = finishes.addAndGet(1);
246                                                 if(current == directProc.size()) {
247                                                         addOrSet(graph, result, provider);
248                                                         proc.execute(graph, result);
249                                                         return; 
250                                                 }
251                                         }
252
253                                         @Override
254                                         public void exception(ReadGraphImpl graph, Throwable t) {
255                                                 proc.exception(graph, t);
256                                         }
257
258                                 });
259
260                                 return true;
261
262                         }
263
264                 });
265
266             }
267             
268             return result;
269         
270     }
271     
272     @Override
273     public String toString() {
274         return "SuperRelations[" + id + "]";
275     }
276
277     private void addOrSet(ReadGraphImpl graph, final IntSet value, QueryProcessor provider) {
278
279         assert(!isReady());
280
281 //        ArrayList<InternalProcedure<IntSet>> p = null;
282
283         synchronized(this) {
284         
285             value.trim();
286             setResult(value);
287             setReady();
288 //            p = procs;
289 //            procs = null; 
290         
291         }
292
293 //        if(p != null) {
294 //              IntSet v = (IntSet)getResult();
295 //              if(v != null) {
296 //                  for(InternalProcedure<IntSet> proc : p) proc.execute(graph, v);
297 //              }
298 //        }
299         
300     }
301     
302     @Override
303     public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, InternalProcedure<IntSet> procedure) {
304               
305         assert(isReady());
306
307         if(handleException(graph, procedure)) return null;
308         
309         IntSet result = getResult();
310         
311         procedure.execute(graph, result);
312         
313         return result;
314         
315     }
316
317     @Override
318     public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
319         
320         final Semaphore s = new Semaphore(0);
321
322         computeForEach(graph, provider, new InternalProcedure<IntSet>() {
323
324                 @Override
325                 public void execute(ReadGraphImpl graph, IntSet result) {
326                 s.release();
327                 }
328
329             @Override
330             public void exception(ReadGraphImpl graph, Throwable t) {
331                 s.release();
332                 new Error("Error in recompute.", t).printStackTrace();
333             }
334
335         }, true);
336
337         while(!s.tryAcquire()) {
338                 provider.resume(graph);
339         }
340         
341     }
342     
343
344     @Override
345     boolean isImmutable(ReadGraphImpl graph) {
346         return graph.processor.isImmutable(id);
347     }
348     
349 }