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