]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java
479bd71cd4d7bb6d48303c3c38688690678f379e
[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 java.util.concurrent.atomic.AtomicInteger;
15
16 import org.simantics.db.common.utils.Logger;
17 import org.simantics.db.exception.DatabaseException;
18 import org.simantics.db.impl.graph.ReadGraphImpl;
19 import org.simantics.db.impl.procedure.InternalProcedure;
20
21 import gnu.trove.procedure.TIntProcedure;
22 import gnu.trove.set.hash.TIntHashSet;
23
24 final public class SuperRelations extends UnaryQuery<InternalProcedure<IntSet>> {
25     
26     SuperRelations(final int resource) {
27         super(resource);
28     }
29     
30     final static SuperRelations entry(final QueryProcessor provider, final int r) {
31         return (SuperRelations)provider.cache.superRelationsMap.get(r);
32     }
33
34         @Override
35         final public void removeEntry(QueryProcessor provider) {
36                 provider.cache.remove(this);
37         }
38         
39         static int histoCounter = 0;
40         static IntSet EMPTY_SET = new IntSet();
41     static int counter = 0;
42     
43     class Koss {
44         
45         private TIntHashSet set = null;
46         public int single = 0;
47         
48         public boolean add(int val) {
49             if(single == val) return false;
50             if(single == 0) {
51                 single = val;
52                 return true;
53             }
54             if(set == null) set = new TIntHashSet(4);
55             return set.add(val);
56         }
57         
58         public int size() {
59             
60             if(single == 0) return 0;
61             if(set == null) return 1;
62             return set.size() + 1;
63             
64         }
65
66         public void forEach(TIntProcedure proc) {
67             if(single > 0) proc.execute(single);
68             if(set != null) set.forEach(proc);
69         }
70         
71     }
72
73         @Override
74         public Object compute(final ReadGraphImpl graph, final InternalProcedure<IntSet> procedure) throws DatabaseException {
75
76                 QueryProcessor processor = graph.processor;
77                 
78                 processor.querySupport.ensureLoaded(graph, id);
79                 
80             final InternalProcedure<IntSet> proc = (InternalProcedure<IntSet>)procedure;
81
82             final int subrelationOf = processor.getSubrelationOf();
83
84             final IntSet result = new IntSet(processor.querySupport);
85
86             final class DirectProcedure extends Koss implements IntProcedure, TIntProcedure, InternalProcedure<IntSet> {
87                 @Override
88                 final public boolean execute(int r) {
89                         result.add(r);
90                         return true;
91                 }
92                 @Override
93                 final public void execute(ReadGraphImpl graph, int r) {
94                         if(single == 0) {
95                                 single = r;
96                                 return;
97                         }
98                         add(r);
99                 }
100                 @Override
101                 final public void execute(ReadGraphImpl graph, IntSet set) throws DatabaseException {
102                         set.forEach(this);
103                         addOrSet(graph, result, processor);
104                         proc.execute(graph, result);
105                 }
106                 @Override
107                 public void finished(ReadGraphImpl graph) {
108                 }
109                 @Override
110                 public void exception(ReadGraphImpl graph, Throwable t) {
111                         throw new Error("Errors are not supported.", t);
112                 }
113
114             }
115
116             final DirectProcedure directProc = new DirectProcedure();
117
118            processor.querySupport.getObjects(graph, id, subrelationOf, directProc);
119
120             int size = directProc.size();
121
122             if(size == 0) {
123
124                 addOrSet(graph, EMPTY_SET, processor);
125                 proc.execute(graph, EMPTY_SET);
126
127             } else if (size == 1) {
128
129                 result.add(directProc.single);
130                 QueryCache.runnerSuperRelations(graph, directProc.single, SuperRelations.this, null, directProc);
131
132             } else {
133
134                 //                  if((counter++ % 500) == 0) System.out.println("SR " + counter);
135
136                 final TIntProcedure addToResult = new TIntProcedure() {
137                         @Override
138                         public boolean execute(int r) {
139                                 synchronized(result) {
140                                         result.add(r);
141                                 }
142                                 return true;
143                         }
144                 };
145
146                 final AtomicInteger finishes = new AtomicInteger(0);
147
148                 directProc.forEach(new TIntProcedure() {
149
150                         @Override
151                         public boolean execute(int arg0) {
152                                 try {
153                                                 return execute0(arg0);
154                                         } catch (DatabaseException e) {
155                                                 Logger.defaultLogError(e);
156                                         }
157                                 return false;
158                         }
159
160                         public boolean execute0(int arg0) throws DatabaseException {
161
162                                 synchronized(result) {
163                                         result.add(arg0);
164                                 }
165
166                                 QueryCache.runnerSuperRelations(graph, arg0, SuperRelations.this, null, new InternalProcedure<IntSet>() {
167
168                                         @Override
169                                         public void execute(ReadGraphImpl graph, IntSet set) throws DatabaseException {
170                                                 set.forEach(addToResult);
171                                                 int current = finishes.addAndGet(1);
172                                                 if(current == directProc.size()) {
173                                                         addOrSet(graph, result, processor);
174                                                         proc.execute(graph, result);
175                                                         return; 
176                                                 }
177                                         }
178
179                                         @Override
180                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
181                                                 proc.exception(graph, t);
182                                         }
183
184                                 });
185
186                                 return true;
187
188                         }
189
190                 });
191
192             }
193             
194             return result;
195         
196     }
197     
198     @Override
199     public String toString() {
200         return "SuperRelations[" + id + "]";
201     }
202
203     private void addOrSet(ReadGraphImpl graph, final IntSet value, QueryProcessor provider) {
204
205         assert(!isReady());
206
207         synchronized(this) {
208         
209             value.trim();
210             setResult(value);
211             setReady();
212         
213         }
214         
215     }
216     
217     @Override
218     public Object performFromCache(ReadGraphImpl graph, InternalProcedure<IntSet> procedure) throws DatabaseException {
219               
220         assert(isReady());
221
222         if(handleException(graph, procedure)) return null;
223         
224         IntSet result = getResult();
225         
226         procedure.execute(graph, result);
227         
228         return result;
229         
230     }
231
232     @Override
233     public void recompute(ReadGraphImpl graph) throws DatabaseException {
234         
235         compute(graph, new InternalProcedure<IntSet>() {
236
237                 @Override
238                 public void execute(ReadGraphImpl graph, IntSet result) {
239                 }
240
241             @Override
242             public void exception(ReadGraphImpl graph, Throwable t) {
243                 new Error("Error in recompute.", t).printStackTrace();
244             }
245
246         });
247         
248     }
249
250     @Override
251     boolean isImmutable(ReadGraphImpl graph) {
252         return graph.processor.isImmutable(id);
253     }
254     
255 }