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