]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Objects.java
Trying to remove synchronization problems
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / Objects.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 org.simantics.db.RelationInfo;
15 import org.simantics.db.Resource;
16 import org.simantics.db.common.exception.DebugException;
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.IntProcedureAdapter;
21 import org.simantics.db.impl.procedure.InternalProcedure;
22 import org.simantics.db.procedure.AsyncMultiProcedure;
23 import org.simantics.db.request.RequestFlags;
24
25 /*
26  * Size analysis:
27  * java 8 byte
28  * id 8 byte
29  * statusOrException 4 byte
30  * p1 = 4 byte
31  * p2OrParents = 4 byte
32  * result = 4 byte 
33  * 
34  * total 32byte
35  * 
36  */
37
38 final public class Objects extends CollectionBinaryQuery<IntProcedure> implements IntProcedure {
39
40         public Objects(final int r1, final int r2) {
41                 super(r1, r2);
42         }
43
44         @Override
45         final public void removeEntry(QueryProcessor provider) {
46                 provider.cache.remove(this);
47         }
48
49         final static private IntArray getAssertionMap(ReadGraphImpl graph, final int r1, final int r2, final Objects entry) throws DatabaseException {
50
51                 class AssertionMapProc implements IntProcedure {
52
53                         boolean first = true;
54
55                         private IntArray result;
56
57                         public void addStatement(int s, int p, int o) {
58
59                                 if(result.size() == 0) {
60                                         result.add(s);
61                                         result.add(p);
62                                         result.add(o);
63                                 } else {
64                                         for(int i = 0;i < result.sizeOrData ; i+=3) {
65                                                 int existingP = result.data[i+1];
66                                                 if(p == existingP) {
67                                                         int existingO = result.data[i+2];
68                                                         if(existingO == o) return;
69                                                 }
70                                         }
71                                         result.add(s);
72                                         result.add(p);
73                                         result.add(o);
74                                 }
75
76                         }
77
78                         @Override
79                         public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
80                                 if(result == null) {
81                                         result = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
82                                 } else {
83                                         if (first) {
84                                                 IntArray ia = result;
85                                                 result = new IntArray();
86                                                 if(ia.data != null) {
87                                                         for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
88                                                 }
89                                                 first = false;
90                                         }
91                                         IntArray ia = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
92                                         if(ia.data != null) {
93                                                 for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
94                                         }
95                                 }
96                         }
97
98                         @Override
99                         public void finished(ReadGraphImpl graph) {
100                         }
101
102                         @Override
103                         public void exception(ReadGraphImpl graph, Throwable throwable) {
104                         }
105
106                 }
107
108                 AssertionMapProc amp = new AssertionMapProc();
109
110                 // This dependency could be cut
111                 QueryCache.runnerPrincipalTypes(graph, r1, entry, null, amp);
112
113                 return amp.result;
114
115         }
116
117         final static private void forSingleAssertion(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
118
119                 IntArray map = getAssertionMap(graph, r1, r2, parent);
120                 if(map == null) {
121                         procedure.finished(graph);
122                         return;
123                 }
124
125                 int size = map.size();
126                 if(size == 3) {
127                     int value = map.data[2];
128                     procedure.execute(graph, value);
129                     procedure.finished(graph);
130                 } else if(size == 0) {
131                         procedure.finished(graph);
132                 } else {
133
134                         int candidateS = map.data[0];
135                         int candidateO = map.data[2];
136
137                         IntSet candidateIs = null;
138                         try {
139                                 candidateIs = QueryCache.resultSuperTypes(graph, candidateS, parent, null);
140                         } catch (DatabaseException e) {
141                                 procedure.exception(graph, e);
142                                 return;
143                         }
144
145                         for(int i=3;i<map.size();i+=3) {
146
147                                 int nextS = map.data[i];
148                                 int nextO = map.data[i+2];
149
150                                 if(nextS != candidateS) {
151
152                                         if(candidateIs.contains(nextS)) {
153
154                                                 // Next is a super type of candidate => ignore next
155
156                                         } else {
157
158                                                 IntSet nextIs = null;
159                                                 try {
160                                                         nextIs = QueryCache.resultSuperTypes(graph, nextS, parent, null);
161                                                 } catch (DatabaseException e) {
162                                                         procedure.exception(graph, e);
163                                                         return;
164                                                 }
165                                                 
166 //                                              SuperTypes next = SuperTypes.queryEach(graph, nextS, graph.processor, entry, null, NOP);
167 //                                              if(next.isExcepted()) {
168 //                                                      if(entry != null) entry.except((Throwable)next.getResult());
169 //                                                      procedure.exception(graph, (Throwable)next.getResult());
170 //                                                      return;
171 //                                              }
172 //                                              IntSet nextIs = next.getResult();
173
174                                                 if(nextIs.contains(candidateS)) {
175
176                                                         // Candidate is a super type of next => next is the new candidate
177
178                                                         candidateS = nextS;
179                                                         candidateO = nextO;
180                                                         candidateIs = nextIs;
181
182                                                 } else {
183
184                                                         // candidate and next are unrelated => error
185                                                         ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions " + r1 + ", " + r2 + " " + map , r1);
186                                                         procedure.exception(graph, exception);
187                                                         return;                                         
188
189                                                 }
190
191                                         }
192
193                                 }
194
195                         }
196
197                         procedure.execute(graph, candidateO);
198                         procedure.finished(graph);
199
200                 }
201
202         }
203
204         final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
205
206                 @Override
207                 public void execute(ReadGraphImpl graph, IntSet result) {
208                 }
209
210                 @Override
211                 public void exception(ReadGraphImpl graph, Throwable throwable) {
212                 }
213
214         };
215
216         final static TripleIntProcedure NOPT = new TripleIntProcedure() {
217
218
219                 @Override
220                 public void exception(ReadGraphImpl graph, Throwable throwable) {
221                 }
222
223                 @Override
224                 public void execute(ReadGraphImpl graph, int s, int p, int o) {
225                 }
226
227                 @Override
228                 public void finished(ReadGraphImpl graph) {
229                 }
230
231         };
232
233         // Search for one statement
234         final public void computeFunctionalIndex(ReadGraphImpl graph, final QueryProcessor provider, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
235                 computeFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
236         }
237
238         // Search for one statement
239         final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
240
241                 if(ri.isFinal) {
242
243                         int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
244
245                         if(result == 0) {
246
247                                 // Check for assertions
248                                 forSingleAssertion(graph, r1, r2, parent, procedure);
249
250                         } else if (result == -1) {
251
252                                 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
253
254                                         @Override
255                                         public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
256                                             procedure.execute(graph, i);
257                                         }
258
259                                         @Override
260                                         public void exception(ReadGraphImpl graph, Throwable t) {
261                                                 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
262                                         }
263
264                                         @Override
265                                         public void finished(ReadGraphImpl graph) {
266                                         }
267
268                                 });
269
270                                 // Check for assertions
271                                 forSingleAssertion(graph, r1, r2, parent, procedure);
272
273                         } else {
274
275                                 // If functional relation was found there is no need to check assertions
276                 procedure.execute(graph, result);
277                 procedure.finished(graph);
278
279                                 
280                         }
281
282                 } else {
283
284                         // Note! The dependency is intentionally cut!
285             IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
286             direct.forEach(graph, new SyncIntProcedure() {
287
288                                 boolean found = false;
289
290                                 @Override
291                                 public void run(ReadGraphImpl graph) throws DatabaseException {
292
293                                         if(found) {
294                                                 procedure.finished(graph);
295                                         } else {
296
297                                                 // Check for assertions
298                                                 forSingleAssertion(graph, r1, r2, parent, procedure);
299
300                                         }
301
302                                 }
303
304                                 @Override
305                                 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
306
307                                         if(found) return;
308
309                                         if(pred == r2) {
310
311                                                 // Note! The dependency is intentionally cut!
312                                                 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
313
314                                                         @Override
315                                                         public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
316
317                                                                 if(!found) {
318
319                                                                         procedure.execute(graph, i);
320                                                                         found = true;
321
322                                                                 } else {
323
324                                                                         ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
325                                                                         procedure.exception(graph, exception);
326
327                                                                 }
328
329                                                         }
330
331                                                         @Override
332                                                         public void finished(ReadGraphImpl graph) {
333                                                         }
334
335                                                         @Override
336                                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
337                                                                 procedure.exception(graph, t);
338                                                         }
339
340                                                 });
341
342                                         } else {
343
344                                                 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
345
346                                                         @Override
347                                                         public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
348
349                                                                 if(found) return;
350
351                                                                 if(result.contains(r2)) {
352
353                                                                         // Note! The dependency is intentionally cut!
354                                                                         QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
355
356                                                                                 @Override
357                                                                                 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
358
359                                                                                         if(!found) {
360
361                                                                                                 procedure.execute(graph, i);
362                                                                                                 found = true;
363
364                                                                                         } else {
365
366                                                                                                 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
367                                                                                                 procedure.exception(graph, exception);
368
369                                                                                         }
370
371                                                                                 }
372
373                                                                                 @Override
374                                                                                 public void finished(ReadGraphImpl graph) {
375                                                                                 }
376
377                                                                                 @Override
378                                                                                 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
379                                                                                         procedure.exception(graph, t);
380                                                                                 }
381
382                                                                         });
383
384                                                                 }
385
386                                                         }
387
388                                                         @Override
389                                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
390                                                                 procedure.exception(graph, t);
391                                                         }
392
393                                                 });
394
395                                         }
396
397                                 }
398
399                                 @Override
400                                 public void finished(ReadGraphImpl graph) throws DatabaseException {
401
402                                         dec(graph);
403
404                                 }
405
406                         });
407
408
409                 }
410
411         }
412
413         final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
414
415                 // Note! The dependency is intentionally cut!
416                 QueryCache.runnerPrincipalTypes(graph, r1, null, null, new SyncIntProcedure() {
417
418                         @Override
419                         public void run(ReadGraphImpl graph) throws DatabaseException {
420                                 procedure.finished(graph);
421                         }
422
423                         TripleIntProcedure proc = new TripleIntProcedure() {
424
425                                 @Override
426                                 public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
427                                         procedure.execute(graph, o);
428                                 }
429
430                                 @Override
431                                 public void finished(ReadGraphImpl graph) throws DatabaseException {
432                                         dec(graph);
433                                 }
434
435                                 @Override
436                                 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
437                                         if(DebugException.DEBUG) new DebugException(t).printStackTrace();
438                                         procedure.exception(graph, t);
439                                         dec(graph);
440                                 }
441
442                         };
443
444                         @Override
445                         public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
446
447                                 inc();
448                                 QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
449
450                         }
451
452                         @Override
453                         public void finished(ReadGraphImpl graph) throws DatabaseException {
454                                 dec(graph);
455                         }
456
457                 });
458
459
460         }
461
462         final public static void computeNotFunctionalFinalIndex(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, RelationInfo ri, AsyncMultiProcedure<Resource> procedure) {
463                 throw new Error();
464         }
465
466         final public void computeNotFunctionalIndex(ReadGraphImpl graph, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
467                 computeNotFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
468         }
469
470         final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
471
472                 if(ri.isFinal) {
473
474                         graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
475
476                                 @Override
477                                 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
478                                         procedure.execute(graph, i);
479                                 }
480
481                                 @Override
482                                 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
483                                         if(DebugException.DEBUG) new DebugException(t).printStackTrace();
484                                         procedure.exception(graph, t);
485                                 }
486
487                                 @Override
488                                 public void finished(ReadGraphImpl graph) {
489                                 }
490
491                         });
492
493                         if(ri.isAsserted) {
494                                 forAssertions(graph, r1, r2, parent, procedure);
495                         } else {
496                                 procedure.finished(graph);
497                         }
498
499                 } else {
500
501                         // Note! The dependency is intentionally cut!
502             IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
503             direct.forEach(graph, new SyncIntProcedure() {
504
505                                 @Override
506                                 public void run(ReadGraphImpl graph) throws DatabaseException {
507                                         forAssertions(graph, r1, r2, parent, procedure);
508                                 }
509
510                                 @Override
511                                 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
512
513                                         if(pred == r2) {
514
515                                                 inc();
516
517                                                 // Note! The dependency is intentionally cut!
518                                                 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
519
520                                                         @Override
521                                                         public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
522                                                                 procedure.execute(graph, i);
523                                                         }
524
525                                                         @Override
526                                                         public void finished(ReadGraphImpl graph) throws DatabaseException {
527                                                                 dec(graph);
528                                                         }
529
530                                                         @Override
531                                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
532                                                                 procedure.exception(graph, t);
533                                                                 dec(graph);
534                                                         }
535
536                                                 });
537
538                                         } else {
539
540                                                 inc();
541
542                                                 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
543
544                                                         @Override
545                                                         public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
546
547                                                                 if(result.contains(r2)) {
548
549                                                                         inc();
550
551                                                                         // Note! The dependency is intentionally cut!
552                                                                         QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
553
554                                                                                 @Override
555                                                                                 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
556                                                                                         procedure.execute(graph, i);
557                                                                                 }
558
559                                                                                 @Override
560                                                                                 public void finished(ReadGraphImpl graph) throws DatabaseException {
561                                                                                         dec(graph);
562                                                                                 }
563
564                                                                                 @Override
565                                                                                 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
566                                                                                         if(DebugException.DEBUG) new DebugException(t).printStackTrace();
567                                                                                         procedure.exception(graph, t);
568                                                                                         dec(graph);
569                                                                                 }
570
571                                                                         });
572
573                                                                 }
574
575                                                                 dec(graph);
576
577                                                         }
578
579                                                         @Override
580                                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
581                                                                 procedure.exception(graph, t);
582                                                                 dec(graph);
583                                                         }
584
585                                                 });
586
587                                         }
588
589                                 }
590
591                                 @Override
592                                 public void finished(ReadGraphImpl graph) throws DatabaseException {
593                                         dec(graph);
594                                 }
595
596                         });
597
598                 }
599
600         }
601
602         //@Override
603         public Object compute(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
604                 computeForEach(graph, r1(), r2(), this, procedure);
605                 return getResult();
606         }
607
608         public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure_) throws DatabaseException {
609
610             IntProcedure procedure = entry != null ? entry : procedure_;
611             
612         RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
613         graph.ensureLoaded(r1, r2);
614         if(ri.isFunctional) {
615             computeFunctionalIndex(graph, r1, r2, entry, ri, procedure);
616         } else {
617             computeNotFunctionalIndex(graph, r1, r2, entry, ri, procedure);
618         }
619                 
620                 if(entry != null) entry.performFromCache(graph, procedure_);
621
622         }
623
624         @Override
625         public String toString() {
626                 return "Objects[" + r1() + " - " + r2() + "]";
627         }
628
629 //      final private void finish(ReadGraphImpl graph, IntProcedure procedure) throws DatabaseException {
630 //
631 //              assert(assertPending());
632 //
633 //              synchronized(this) {
634 //                      setReady();
635 //              }
636 //
637 //              IntArray v = (IntArray)getResult();
638 //
639 //              if(v.data == null) {
640 //                      if(v.sizeOrData != IntArray.NO_DATA) {
641 //                              procedure.execute(graph, v.sizeOrData);
642 //                      }
643 //              } else {
644 //                      for(int i = 0;i < v.sizeOrData ; i++) {
645 //                              procedure.execute(graph, v.data[i]);
646 //                      }
647 //              }
648 //
649 //              procedure.finished(graph);
650 //
651 //      }
652
653 //      final public void addOrSet(int add) {
654 //
655 //              assert(assertPending());
656 //
657 //              IntArray value = (IntArray)getResult();
658 //              synchronized(value) {
659 //                      value.add(add);
660 //              }
661 //
662 //      }
663
664 //      final public void addOrSetFunctional(int add) {
665 //
666 //              assert(isPending());
667 //
668 //              IntArray value = (IntArray)getResult();
669 //              value.add(add);
670 //
671 //      }
672
673         @Override
674         public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
675
676                 assert(isReady());
677
678                 if(handleException(graph, procedure)) return getResult();
679
680                 final IntArray value = (IntArray)getResult();
681                 if(value.data == null) {
682                         if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
683                 } else {
684                         for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
685                 }
686
687                 procedure.finished(graph);
688                 
689                 return value;
690
691         }
692
693         @Override
694         public void recompute(ReadGraphImpl graph) throws DatabaseException {
695
696                 compute(graph, new IntProcedureAdapter() {
697
698                         @Override
699                         public void finished(ReadGraphImpl graph) {
700                         }
701
702                         @Override
703                         public void exception(ReadGraphImpl graph, Throwable t) {
704                                 new Error("Error in recompute.", t).printStackTrace();
705                         }
706
707                 });
708
709         }
710
711         @Override
712         public int type() {
713                 return RequestFlags.IMMEDIATE_UPDATE;
714         }
715
716         @Override
717         boolean isImmutable(ReadGraphImpl graph) {
718                 return graph.processor.isImmutable(r1());
719         }
720
721     @Override
722     public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
723       IntArray value = (IntArray)getResult();
724       synchronized(value) {
725           value.add(i);
726       }
727     }
728
729     @Override
730     public void finished(ReadGraphImpl graph) throws DatabaseException {
731         setReady();
732     }
733
734     @Override
735     public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
736         except(throwable);
737     }
738
739 }