]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PrincipalTypes.java
Trying to remove synchronization problems
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / PrincipalTypes.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.ArrayList;
15 import java.util.Arrays;
16
17 import org.simantics.db.common.utils.Logger;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.impl.graph.ReadGraphImpl;
20 import org.simantics.db.impl.procedure.IntProcedureAdapter;
21 import org.simantics.db.impl.procedure.InternalProcedure;
22
23 import gnu.trove.procedure.TIntProcedure;
24 import gnu.trove.set.hash.TIntHashSet;
25
26 final public class PrincipalTypes extends CollectionUnaryQuery {
27
28         PrincipalTypes(final int resource) {
29                 super(resource);
30         }
31
32         @Override
33         final public void removeEntry(QueryProcessor provider) {
34                 provider.cache.remove(this);
35         }
36
37         static class Koss {
38
39                 private TIntHashSet set = null;
40                 public int single = 0;
41
42                 public boolean add(int val) {
43                         if(single == val) return false;
44                         if(single == 0) {
45                                 single = val;
46                                 return true;
47                         }
48                         if(set == null) set = new TIntHashSet(4);
49                         set.add(val);
50                         return true;
51                 }
52
53                 public int size() {
54
55                         if(single == 0) return 0;
56                         if(set == null) return 1;
57                         return set.size() + 1;
58
59                 }
60
61                 public int[] toArray() {
62
63                         int[] result = Arrays.copyOf(set.toArray(), set.size() + 1);
64                         result[set.size()] = single;
65                         return result;
66
67                 }
68
69                 public void forEach(TIntProcedure proc) {
70                         proc.execute(single);
71                         if(set != null) set.forEach(proc);
72                 }
73
74         }
75
76         @Override
77         public void compute(final ReadGraphImpl graph, final IntProcedure proc) throws DatabaseException {
78                 computeForEach(graph, id, this, proc);
79         }
80         
81         public static Object computeForEach(final ReadGraphImpl graph, final int id, final PrincipalTypes entry, final IntProcedure procedure_) throws DatabaseException {
82
83             IntProcedure procedure = entry != null ? entry : procedure_;
84             
85             Object result = computeForEach2(graph, id, entry, procedure);
86             
87             if(entry != null) entry.performFromCache(graph, procedure_);
88             
89             return result;
90             
91         }
92             
93         public static Object computeForEach2(final ReadGraphImpl graph, final int id, final PrincipalTypes parent, final IntProcedure procedure) throws DatabaseException {
94
95             QueryProcessor provider = graph.processor;
96                 
97                 provider.querySupport.ensureLoaded(graph, id);
98                 assert(id != 0);
99
100                 int ret = provider.querySupport.getSingleInstance(id);
101                 if(ret > 0) {
102                         procedure.execute(graph, ret);
103                         procedure.finished(graph);
104                         return ret;
105                 }
106
107                 final int instanceOf = provider.getInstanceOf();
108                 final int inherits = provider.getInherits();
109                 final int subrelationOf = provider.getSubrelationOf();
110
111                 final Koss indirect = new Koss();
112                 final Koss material = new Koss();
113
114                 IntProcedure directProc = new IntProcedure() {
115
116                         @Override
117                         public void execute(ReadGraphImpl graph, int i) {
118                                 material.add(i);
119                         }
120
121                         @Override
122                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
123                                 procedure.exception(graph, t);
124                         }
125
126                         @Override
127                         public void finished(ReadGraphImpl graph) {
128                         }
129
130                 };
131
132                 IntProcedure indirectProc = new IntProcedure() {
133
134                         @Override
135                         public void execute(ReadGraphImpl graph, int i) {
136                                 indirect.add(i);
137                         }
138
139                         @Override
140                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
141                                 procedure.exception(graph, t);
142                         }
143
144                         @Override
145                         public void finished(ReadGraphImpl graph) {
146                         }
147
148                 };
149
150                 provider.querySupport.getObjects(graph, id, instanceOf, directProc);
151                 provider.querySupport.getObjects(graph, id, inherits, indirectProc);
152                 provider.querySupport.getObjects(graph, id, subrelationOf, indirectProc);
153
154                 if(indirect.size() == 0) {
155                         int size = material.size(); 
156                         if(size == 0) {
157                                 procedure.finished(graph);
158                                 return null;
159                         } else if(size == 1) {
160                                 int single = material.single; 
161                                 procedure.execute(graph, single);
162                                 procedure.finished(graph);
163                                 return single;
164                         } else {
165                                 addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, parent, procedure);
166                                 return null;
167                         }
168                 }
169
170                 indirect.forEach(new TIntProcedure() {
171
172                         int finishes = 0;
173                         
174                         @Override
175                         public boolean execute(final int arg0) {
176                                 try {
177                                         return execute0(arg0);
178                                 } catch (DatabaseException e) {
179                                         Logger.defaultLogError(e);
180                                 }
181                                 return false;
182                         }
183                         
184                         public boolean execute0(final int arg0) throws DatabaseException {
185
186                                 // No self-loops!
187                                 if(arg0 == id) {
188                                         int current = (++finishes);
189                                         if(current == indirect.size()) {
190                                                 int size = material.size(); 
191                                                 if(size == 0) {
192                                                         procedure.finished(graph);
193                                                         return true;
194                                                 } else if(size == 1) {
195                                                         int single = material.single; 
196                                                         procedure.execute(graph, single);
197                                                         procedure.finished(graph);
198                                                         return true;
199                                                 } else {
200                                                         addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, parent, procedure);
201                                                         return true;
202                                                 }
203                                         }
204                                         return true;
205                                 }
206
207                                 QueryCache.runnerPrincipalTypes(graph, arg0, parent, null, new IntProcedure() {
208
209                                         @Override
210                                         public void execute(ReadGraphImpl graph, int i) {
211                                                 synchronized(material) {
212                                                         material.add(i);
213                                                 }
214                                         }
215
216                                         @Override
217                                         public void finished(ReadGraphImpl graph) throws DatabaseException {
218
219                                                 int current = (++finishes);
220                                                 if(current == indirect.size()) {
221                                                         int size = material.size(); 
222                                                         if(size == 0) {
223                                                                 procedure.finished(graph);
224                                                                 return;
225                                                         } else if(size == 1) {
226                                                                 int single = material.single; 
227                                                                 procedure.execute(graph, single);
228                                                                 procedure.finished(graph);
229                                                                 return;
230                                                         } else {
231                                                                 addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, parent, procedure);
232                                                                 return;
233                                                         }
234                                                 }
235
236                                         }
237
238                                         @Override
239                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
240                                                 procedure.exception(graph, t);
241                                         }
242
243                                 });
244
245                                 return true;
246
247                         }
248
249                 });
250                 
251                 return null;
252
253         }
254
255         private static void finish(ReadGraphImpl graph, final TIntHashSet rejects, final int[] material, final IntProcedure proc) throws DatabaseException {
256
257                 for(int i : material) {
258                         if(!rejects.contains(i)) {
259                                 proc.execute(graph, i);
260                         }
261                 }
262
263                 proc.finished(graph);
264
265                 return;
266
267         }
268
269         private static void addPrincipalType(final ReadGraphImpl graph, final TIntHashSet rejects, final int[] material, int index, final QueryProcessor provider, final PrincipalTypes parent, final IntProcedure proc) throws DatabaseException {
270
271                 if(index == material.length) { 
272                         finish(graph, rejects, material, proc);
273                         return;
274                 }
275
276                 int type = material[index++];
277                 while(rejects.contains(type)) {
278                         if(index == material.length) { 
279                                 finish(graph, rejects, material, proc);
280                                 return;
281                         }
282                         type = material[index++];
283                 }
284                 
285                 final int nextIndex = index;
286
287                 QueryCache.runnerSuperTypes(graph, type, parent, null, new InternalProcedure<IntSet>() {
288
289                         @Override
290                         public void execute(ReadGraphImpl graph, IntSet supers) throws DatabaseException {
291
292                                 synchronized(rejects) {
293
294                                         supers.forEach(new TIntProcedure() {
295
296                                                 @Override
297                                                 public boolean execute(int arg0) {
298                                                         rejects.add(arg0);
299                                                         return true;
300                                                 }
301
302                                         });
303
304                                 }
305
306                                 addPrincipalType(graph, rejects, material, nextIndex, provider, parent, proc);
307
308                         }
309
310                         @Override
311                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
312                                 proc.exception(graph, t);
313                         }
314
315                 });
316
317         }
318
319         @Override
320         public String toString() {
321                 return "PrincipalTypes[" + id + "]";
322         }
323     
324     @Override
325     protected void fillImpliedParents(QueryProcessor processor, ArrayList<CacheEntry<?>> result) {
326     }
327
328 }