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