Merge "Multiple reader thread support for db client"
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / AssertedStatements.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2018 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.RelationInfo;
17 import org.simantics.db.exception.DatabaseException;
18 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
19 import org.simantics.db.impl.graph.ReadGraphImpl;
20 import org.simantics.db.impl.procedure.InternalProcedure;
21 import org.simantics.db.impl.procedure.TripleIntProcedureAdapter;
22 import org.simantics.db.request.RequestFlags;
23
24
25 final public class AssertedStatements extends CollectionBinaryQuery<TripleIntProcedure> {
26     
27     public AssertedStatements(final int r1, final int r2) {
28         super(r1, r2);
29     }
30
31     public static AssertedStatements newInstance(final int r1, final int r2) {
32         return new AssertedStatements(r1, r2);
33     }
34
35         @Override
36         final public void removeEntry(QueryProcessor provider) {
37             provider.cache.remove(this);
38         }
39         
40         static void computeInheritedAssertions(ReadGraphImpl graph, int type, final int predicate, final RelationInfo ri, final AssertedStatements entry, final TripleIntProcedure proc) throws DatabaseException {
41             
42         QueryProcessor processor = graph.processor;
43
44         QueryCache.runnerDirectObjects(graph, type, processor.getInherits(), entry, null, new SyncIntProcedure() {
45
46             @Override
47             public void run(ReadGraphImpl graph) throws DatabaseException {
48
49 //                if(ri.isFunctional && found.get() == 1) {
50 //
51 //                    ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has assertions from multiple inherited types.");
52 //                    except(exception);
53 //                    proc.exception(graph, exception);
54 //                    return;
55 //                    
56 //                }
57
58                 finish(graph, entry);
59                 proc.finished(graph);
60                 
61             }
62
63             @Override
64             public void execute(ReadGraphImpl graph, int inh) throws DatabaseException {
65                 
66 //                if(ri.isFunctional && found.get() == 1) return;
67
68                 inc();
69                 
70                 QueryCache.runnerAssertedStatements(graph, inh, predicate, entry, null, new TripleIntProcedureAdapter() {
71
72                     @Override
73                     public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
74
75 //                        if(ri.isFunctional) {
76 //                            
77 ////                            if(found.get() == 1) return;
78 //
79 //                            if(found.compareAndSet(0, o)) {
80                                 if(addOrSet(s,p,o, entry))
81                                         proc.execute(graph, s, p, o);
82 //                            }
83 //                            // If this was a duplicate, we can ignore this
84 //                            else if (found.compareAndSet(o, o)) {
85 //                                //System.err.println("duplicates!");
86 //                            }
87 //                            // Otherwise we have error
88 //                            else {
89 //                                found.set(1);
90 //                            }
91 //                            
92 //                        } else {
93 //                            
94 //                            addOrSet(s, p, o);
95 //                            proc.execute(graph, s, p, o);
96 //                            
97 //                        }
98                         
99                     }
100
101                     @Override
102                     public void finished(ReadGraphImpl graph) throws DatabaseException {
103                         dec(graph);
104                     }
105                                 
106                                 @Override
107                                 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
108                                         proc.exception(graph, t);
109                                         dec(graph);
110                     }
111                     
112                 });
113                 
114             }
115
116             @Override
117             public void finished(ReadGraphImpl graph) throws DatabaseException {
118                 dec(graph);
119             }
120             
121         });
122
123         }
124
125     static void computeLocalAssertions(ReadGraphImpl graph, final int type, final int predicate, final RelationInfo ri, final AssertedStatements entry, final TripleIntProcedure proc) throws DatabaseException {
126         
127         
128     }
129
130         //@Override
131         public Object compute(ReadGraphImpl graph, final TripleIntProcedure procedure) throws DatabaseException {
132                 computeForEach(graph, r1(), r2(), this, procedure);
133                 return getResult();
134         }
135
136     public static void computeForEach(ReadGraphImpl graph, final int type, final int predicate, final AssertedStatements entry, final TripleIntProcedure procedure) throws DatabaseException {
137
138         RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, predicate, entry, null);
139         
140         final AtomicInteger found = new AtomicInteger(0);
141
142         QueryProcessor processor = graph.processor;
143         
144         QueryCache.runnerDirectObjects(graph, type, processor.getAsserts(), entry, null, new SyncIntProcedure() {
145
146             @Override
147             public void run(ReadGraphImpl graph) throws DatabaseException {
148                 
149                 if(ri.isFunctional && found.get() > 1) {
150
151                     ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one asserted statement.");
152                     except(exception, entry);
153                     procedure.exception(graph, exception);
154                     return;
155                     
156                 }
157
158                 if(ri.isFunctional && found.get() == 1) {
159                                         
160                     finish(graph, entry);
161                     procedure.finished(graph);
162                     return;
163                     
164                 }
165
166                 computeInheritedAssertions(graph, type, predicate, ri, entry, procedure);
167                 
168             }
169
170             @Override
171             public void execute(ReadGraphImpl graph, final int ass) throws DatabaseException {
172                 
173                 if(ri.isFunctional && found.get() > 1) return;
174                 
175                 inc();
176                 
177                 QueryCache.runnerDirectObjects(graph, ass, processor.getHasPredicate(), entry, null, new IntProcedure() {
178
179                     @Override
180                     public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
181                         
182                         if(ri.isFunctional) {
183                             
184                             if(found.get() > 1) return;
185
186                             inc();
187
188                             QueryCache.runnerDirectObjects(graph, ass, processor.getHasObject(), entry, null, new IntProcedure() {
189
190                                 @Override
191                                 public void execute(ReadGraphImpl graph, final int object) throws DatabaseException {
192                                     
193                                     if(found.get() > 1) return;
194
195                                     if(pred == predicate) {
196
197                                         if(found.getAndIncrement() == 0) {
198                                                 if(addOrSet(type, pred, object, entry))
199                                                         procedure.execute(graph, type, pred, object);
200                                         }
201                                         
202                                         return;
203                                         
204                                     }
205                                     
206                                     if ( !ri.isFinal ) {
207
208                                         inc();
209
210                                         QueryCache.runnerSuperRelations(graph, pred, entry, null, new InternalProcedure<IntSet>() {
211                                             
212                                             @Override
213                                             public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
214                                                 
215                                                 if(found.get() > 1) {
216                                                     dec(graph);
217                                                     return;
218                                                 }
219
220                                                 if(result.contains(predicate)) {
221                     
222                                                     if(found.getAndIncrement() == 0) {
223                                                                 if(addOrSet(type, pred, object, entry))
224                                                                         procedure.execute(graph, type, pred, object);
225                                                         }
226                                                     
227                                                 }
228                                                 
229                                                 dec(graph);
230                                                 
231                                             }
232                                                         
233                                                         @Override
234                                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
235                                                             
236                                                                 procedure.exception(graph, t);
237                                                 dec(graph);
238                                                                 
239                                             }
240
241                                         });
242
243                                     }
244
245                                 }
246                                 
247                                 @Override
248                                 public void finished(ReadGraphImpl graph) throws DatabaseException {
249                                     dec(graph);
250                                 }
251                                         
252                                         @Override
253                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
254                                                 procedure.exception(graph, t);
255                                     dec(graph);
256                                 }
257
258                             });
259                             
260                         } else {
261
262                             inc();
263
264                             QueryCache.runnerDirectObjects(graph, ass, processor.getHasObject(), entry, null, new IntProcedure() {
265
266                                 @Override
267                                 public void execute(ReadGraphImpl graph, final int object) throws DatabaseException {
268                                     
269                                     if(pred == predicate) {
270
271                                         addOrSet(type, pred, object, entry);
272                                         procedure.execute(graph, type, pred, object);
273                                         return;
274                                         
275                                     }
276                                     
277                                     if ( !ri.isFinal ) {
278
279                                         inc();
280
281                                         QueryCache.runnerSuperRelations(graph, pred, entry, null, new InternalProcedure<IntSet>() {
282                                             
283                                             @Override
284                                             public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
285                                                 
286                                                 if(result.contains(predicate)) {
287                     
288                                                     addOrSet(type, pred, object, entry);
289                                                     procedure.execute(graph, type, pred, object);
290
291                                                 }
292                                                 
293                                                 dec(graph);
294                                                 
295                                             }
296                                                         
297                                                         @Override
298                                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
299                                                                 procedure.exception(graph, t);
300                                                 dec(graph);
301                                             }
302  
303                                         });
304
305                                     }
306
307                                 }
308                                 
309                                 @Override
310                                 public void finished(ReadGraphImpl graph) throws DatabaseException {
311                                     dec(graph);
312                                 }
313                                         
314                                         @Override
315                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
316                                                 procedure.exception(graph, t);
317                                     dec(graph);
318                                 }
319
320                             });
321
322                         }
323
324                     }
325
326                     @Override
327                     public void finished(ReadGraphImpl graph) throws DatabaseException {
328                         dec(graph);
329                     }
330                                 
331                                 @Override
332                                 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
333                                         procedure.exception(graph, t);
334                         dec(graph);
335                     }
336
337                 });
338                 
339             }
340
341             @Override
342             public void finished(ReadGraphImpl graph) throws DatabaseException {
343                 dec(graph);
344             }
345             
346         });
347         
348     }
349     
350     @Override
351     public String toString() {
352         return "AssertedStatements[" + r1() + " - " + r2() + "]";
353     }
354
355     private boolean addOrSet(int s, int p, int o) {
356         
357         assert(isPending());
358         
359         IntArray value = (IntArray)getResult();
360         if(value.data != null) {
361                         for(int i = 0;i < value.sizeOrData ; i+=3) {
362                                 int existingP = value.data[i+1];
363                                 if(p == existingP) {
364                                         int existingO = value.data[i+2];
365                                         if(existingO == o) return false;
366                                 }
367                         }
368                 value.add(s);
369                 value.add(p);
370                 value.add(o);
371         } else {
372                 value.add(s);
373                 value.add(p);
374                 value.add(o);
375         }
376         
377         return true;
378         
379     }
380     
381     static boolean addOrSet(int s, int p, int o, AssertedStatements entry) {
382         if(entry != null) {
383                 return entry.addOrSet(s, p, o);
384         } else {
385                 return true;
386         }
387     }
388     
389     static void finish(ReadGraphImpl graph, AssertedStatements entry) {
390         
391         assert(entry.isPending());
392         if(entry != null) {
393                 synchronized(entry) {
394                         entry.setReady();
395                 }
396         }
397
398     }
399     
400     static void except(Throwable t, AssertedStatements entry) {
401         if(entry != null) {
402                 synchronized(entry) {
403                         entry.except(t);
404                 }
405         }
406     }
407
408     @Override
409     public Object performFromCache(ReadGraphImpl graph, final TripleIntProcedure procedure) throws DatabaseException {
410         
411         assert(isReady());
412         
413         if(handleException(graph, procedure)) return getResult();
414         
415         final IntArray value = (IntArray)getResult();
416         for(int i=0;i<value.size();i+=3) {
417                 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
418         }
419
420         procedure.finished(graph);
421         
422         return value;
423         
424     }
425     
426     @Override
427     public void recompute(ReadGraphImpl graph) throws DatabaseException {
428         
429         compute(graph, new TripleIntProcedureAdapter() {
430
431             @Override
432             public void finished(ReadGraphImpl graph) {
433             }
434                         
435                         @Override
436                         public void exception(ReadGraphImpl graph, Throwable t) {
437                                 throw new Error("Error in recompute", t);
438             }
439     
440         });
441         
442     }
443     
444     @Override
445     public int type() {
446         return RequestFlags.IMMEDIATE_UPDATE;
447     }
448     
449
450     @Override
451     boolean isImmutable(ReadGraphImpl graph) {
452         return graph.processor.isImmutable(r1());
453     }
454     
455 }