]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Objects.java
Fixed all line endings of the repository
[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 java.util.Collection;
15 import java.util.concurrent.Semaphore;
16
17 import org.simantics.databoard.Bindings;
18 import org.simantics.db.DevelopmentKeys;
19 import org.simantics.db.RelationInfo;
20 import org.simantics.db.Resource;
21 import org.simantics.db.common.exception.DebugException;
22 import org.simantics.db.exception.DatabaseException;
23 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
24 import org.simantics.db.impl.graph.ReadGraphImpl;
25 import org.simantics.db.impl.procedure.IntProcedureAdapter;
26 import org.simantics.db.impl.procedure.InternalProcedure;
27 import org.simantics.db.procedure.AsyncMultiProcedure;
28 import org.simantics.db.procedure.ListenerBase;
29 import org.simantics.db.request.RequestFlags;
30 import org.simantics.utils.Development;
31
32 /*
33  * Size analysis:
34  * java 8 byte
35  * id 8 byte
36  * statusOrException 4 byte
37  * p1 = 4 byte
38  * p2OrParents = 4 byte
39  * result = 4 byte 
40  * 
41  * total 32byte
42  * 
43  */
44
45 final public class Objects extends CollectionBinaryQuery<IntProcedure> {
46
47         public Objects(final int r1, final int r2) {
48                 super(r1, r2);
49         }
50
51         final static Objects entry(final QueryProcessor provider, final int r1, final int r2) {
52                 return (Objects)provider.objectsMap.get(r1,r2);
53         }
54
55         final static Collection<Objects> entries(final QueryProcessor processor, final int r1) {
56                 return processor.objectsMap.values(r1);
57         }
58
59         public final static void runner(ReadGraphImpl graph, final int r1, final int r2, CacheEntry parent, ListenerBase listener, final IntProcedure procedure) {
60
61                 if(parent == null && listener == null) {
62                         Objects.computeForEach(graph, r1, r2, null, procedure);
63                         return;
64                 }
65
66                 QueryProcessor processor = graph.processor;
67
68                 Objects entry = (Objects)processor.objectsMap.get(r1,r2);
69                 if(entry == null) {
70
71                         entry = new Objects(r1, r2);
72                         entry.setPending();
73                         entry.clearResult(processor.querySupport);
74                         entry.putEntry(processor);
75
76                         processor.performForEach(graph, entry, parent, listener, procedure);
77
78                 } else {
79
80                         if(entry.isPending()) {
81                                 synchronized(entry) {
82                                         if(entry.isPending()) {
83                                                 processor.registerDependencies(graph, entry, parent, listener, procedure, false);
84                                                 computeForEach(graph, r1, r2, null, procedure);
85                                                 return;
86                                         }
87                                 }
88                         }
89
90                         processor.performForEach(graph, entry, parent, listener, procedure);
91
92                 }
93
94         }
95
96         static class Runner2Procedure implements IntProcedure {
97             
98             public int single = 0;
99             public Throwable t = null;
100
101             public void clear() {
102                 single = 0;
103                 t = null;
104             }
105             
106         @Override
107         public void execute(ReadGraphImpl graph, int i) {
108             if(single == 0) single = i;
109             else single = -1;
110         }
111
112         @Override
113         public void finished(ReadGraphImpl graph) {
114             if(single == -1) single = 0;
115         }
116
117         @Override
118         public void exception(ReadGraphImpl graph, Throwable throwable) {
119             single = 0;
120             this.t = throwable;
121         }
122         
123         public int get() throws DatabaseException {
124             if(t != null) {
125                 if(t instanceof DatabaseException) throw (DatabaseException)t;
126                 else throw new DatabaseException(t);
127             }
128             return single;
129         }
130             
131         }
132         
133         static final Runner2Procedure runner2Procedure = new Runner2Procedure();
134         
135     public final static int runner2(ReadGraphImpl graph, final int r1, final int r2, CacheEntry parent) throws DatabaseException {
136
137         runner2Procedure.clear();
138
139         if(parent == null) {
140             Objects.computeForEach(graph, r1, r2, null, runner2Procedure);
141             return runner2Procedure.get();
142         }
143
144         QueryProcessor processor = graph.processor;
145
146         Objects entry = (Objects)processor.objectsMap.get(r1,r2);
147         if(entry == null) {
148
149             entry = new Objects(r1, r2);
150             entry.setPending();
151             entry.clearResult(processor.querySupport);
152             entry.putEntry(processor);
153
154             processor.performForEach(graph, entry, parent, null, runner2Procedure);
155             return runner2Procedure.get();
156
157         } else {
158
159             if(entry.isPending()) throw new IllegalStateException();
160
161             processor.performForEach(graph, entry, parent, null, runner2Procedure);
162             return runner2Procedure.get();
163
164         }
165
166     }
167         
168         @Override
169         public BinaryQuery<IntProcedure> getEntry(QueryProcessor provider) {
170                 return provider.objectsMap.get(id);
171         }
172
173         @Override
174         public void putEntry(QueryProcessor provider) {
175                 if(Development.DEVELOPMENT) {
176                         if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_PUT, Bindings.BOOLEAN)) {
177                                 System.err.println("put " + this);
178                         }
179                 }
180                 provider.objectsMap.put(id, this);
181         }
182
183         @Override
184         final public void removeEntry(QueryProcessor provider) {
185                 provider.objectsMap.remove(id);
186         }
187
188         final static private IntArray getAssertionMap(ReadGraphImpl graph, final int r1, final int r2, final Objects entry) {
189
190                 class AssertionMapProc implements IntProcedure {
191
192                         boolean first = true;
193
194                         private IntArray result;
195
196                         public void addStatement(int s, int p, int o) {
197
198                                 if(result.size() == 0) {
199                                         result.add(s);
200                                         result.add(p);
201                                         result.add(o);
202                                 } else {
203                                         for(int i = 0;i < result.sizeOrData ; i+=3) {
204                                                 int existingP = result.data[i+1];
205                                                 if(p == existingP) {
206                                                         int existingO = result.data[i+2];
207                                                         if(existingO == o) return;
208                                                 }
209                                         }
210                                         result.add(s);
211                                         result.add(p);
212                                         result.add(o);
213                                 }
214
215                         }
216
217                         @Override
218                         public void execute(ReadGraphImpl graph, int type) {
219                                 AssertedStatements stms = AssertedStatements.queryEach(graph, type, r2, graph.processor, entry, null, NOPT);
220                                 if(result == null) {
221                                         result = stms.getResult();
222                                 } else {
223                                         if (first) {
224                                                 IntArray ia = result;
225                                                 result = new IntArray();
226                                                 if(ia.data != null) {
227                                                         for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
228                                                 }
229                                                 first = false;
230                                         }
231                                         IntArray ia = stms.getResult();
232                                         if(ia.data != null) {
233                                                 for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
234                                         }
235                                 }
236                         }
237
238                         @Override
239                         public void finished(ReadGraphImpl graph) {
240                         }
241
242                         @Override
243                         public void exception(ReadGraphImpl graph, Throwable throwable) {
244                         }
245
246                 }
247
248                 AssertionMapProc amp = new AssertionMapProc();
249
250                 // This dependency could be cut
251                 PrincipalTypes.queryEach(graph, r1, graph.processor, entry, null, amp);
252
253                 return amp.result;
254
255         }
256
257         final static private void forSingleAssertion(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure) {
258
259                 IntArray map = getAssertionMap(graph, r1, r2, entry);
260                 if(map == null) {
261                         if(entry != null) entry.finish(graph, procedure);
262                         else procedure.finished(graph);
263                         return;
264                 }
265
266                 int size = map.size();
267                 if(size == 3) {
268
269                         int value = map.data[2];
270
271                         if(entry != null) {
272                                 entry.addOrSetFunctional(value);
273                                 entry.finish(graph, procedure);
274                         } else {
275                                 procedure.execute(graph, value);
276                                 procedure.finished(graph);
277                         }
278
279                 } else if(size == 0) {
280
281                         if(entry != null) entry.finish(graph, procedure);
282                         else procedure.finished(graph);
283
284                 } else {
285
286                         int candidateS = map.data[0];
287                         int candidateO = map.data[2];
288
289                         SuperTypes candidate = SuperTypes.queryEach(graph, candidateS, graph.processor, entry, null, NOP);
290                         if(candidate.isExcepted()) {
291                                 if(entry != null) entry.except((Throwable)candidate.getResult());
292                                 procedure.exception(graph, (Throwable)candidate.getResult());
293                                 return;
294                         }
295                         IntSet candidateIs = candidate.getResult();
296
297                         for(int i=3;i<map.size();i+=3) {
298
299                                 int nextS = map.data[i];
300                                 int nextO = map.data[i+2];
301
302                                 if(nextS != candidateS) {
303
304                                         if(candidateIs.contains(nextS)) {
305
306                                                 // Next is a super type of candidate => ignore next
307
308                                         } else {
309
310                                                 SuperTypes next = SuperTypes.queryEach(graph, nextS, graph.processor, entry, null, NOP);
311                                                 if(next.isExcepted()) {
312                                                         if(entry != null) entry.except((Throwable)next.getResult());
313                                                         procedure.exception(graph, (Throwable)next.getResult());
314                                                         return;
315                                                 }
316                                                 IntSet nextIs = next.getResult();
317
318                                                 if(nextIs.contains(candidateS)) {
319
320                                                         // Candidate is a super type of next => next is the new candidate
321
322                                                         candidateS = nextS;
323                                                         candidateO = nextO;
324                                                         candidateIs = nextIs;
325
326                                                 } else {
327
328                                                         // candidate and next are unrelated => error
329                                                         ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions " + r1 + ", " + r2 + " " + map , r1);
330
331                                                         if(entry != null) entry.except(exception);
332                                                         procedure.exception(graph, exception);
333                                                         return;                                         
334
335                                                 }
336
337                                         }
338
339                                 }
340
341                         }
342
343                         if(entry != null) {
344                                 entry.addOrSetFunctional(candidateO);
345                                 entry.finish(graph, procedure);
346                         } else {
347                                 procedure.execute(graph, candidateO);
348                                 procedure.finished(graph);
349                         }
350
351                 }
352
353         }
354
355         final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
356
357                 @Override
358                 public void execute(ReadGraphImpl graph, IntSet result) {
359                 }
360
361                 @Override
362                 public void exception(ReadGraphImpl graph, Throwable throwable) {
363                 }
364
365         };
366
367         final static TripleIntProcedure NOPT = new TripleIntProcedure() {
368
369
370                 @Override
371                 public void exception(ReadGraphImpl graph, Throwable throwable) {
372                 }
373
374                 @Override
375                 public void execute(ReadGraphImpl graph, int s, int p, int o) {
376                 }
377
378                 @Override
379                 public void finished(ReadGraphImpl graph) {
380                 }
381
382         };
383
384         // Search for one statement
385         final public void computeFunctionalIndex(ReadGraphImpl graph, final QueryProcessor provider, final RelationInfo ri, final IntProcedure procedure) {
386                 computeFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
387         }
388
389         // Search for one statement
390         final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final RelationInfo ri, final IntProcedure procedure) {
391
392                 if(ri.isFinal) {
393
394                         int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
395
396                         if(result == 0) {
397
398                                 // Check for assertions
399                                 forSingleAssertion(graph, r1, r2, entry, procedure);
400
401                         } else if (result == -1) {
402
403                                 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
404
405                                         @Override
406                                         public void execute(ReadGraphImpl graph, int i) {
407                                                 if(entry != null) entry.addOrSetFunctional(i);
408                                                 else procedure.execute(graph, i);
409                                         }
410
411                                         @Override
412                                         public void exception(ReadGraphImpl graph, Throwable t) {
413                                                 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
414                                         }
415
416                                         @Override
417                                         public void finished(ReadGraphImpl graph) {
418                                         }
419
420                                 });
421
422                                 // Check for assertions
423                                 forSingleAssertion(graph, r1, r2, entry, procedure);
424
425                         } else {
426
427                                 // If functional relation was found there is no need to check assertions
428                                 if(entry != null) {
429                                         entry.addOrSetFunctional(result);
430                                         entry.finish(graph, procedure);
431                                 } else {
432                                         procedure.execute(graph, result);
433                                         procedure.finished(graph);
434                                 }
435
436                                 
437                         }
438
439                 } else {
440
441                         // Note! The dependency is intentionally cut!
442                         DirectPredicates.queryEach(graph, r1, graph.processor, null, null, new SyncIntProcedure() {
443
444                                 boolean found = false;
445
446                                 @Override
447                                 public void run(ReadGraphImpl graph) {
448
449                                         if(found) {
450                                                 if(entry != null) entry.finish(graph, procedure);
451                                                 else procedure.finished(graph);
452                                         } else {
453
454                                                 // Check for assertions
455                                                 forSingleAssertion(graph, r1, r2, entry, procedure);
456
457                                         }
458
459                                 }
460
461                                 @Override
462                                 public void execute(ReadGraphImpl graph, final int pred) {
463
464                                         if(found) return;
465
466                                         if(pred == r2) {
467
468                                                 // Note! The dependency is intentionally cut!
469                                                 DirectObjects.queryEach(graph, r1, pred, graph.processor, null, null, new IntProcedure() {
470
471                                                         @Override
472                                                         public void execute(ReadGraphImpl graph, int i) {
473
474                                                                 if(!found) {
475
476                                                                         if(entry != null) entry.addOrSetFunctional(i);
477                                                                         else procedure.execute(graph, i);
478
479                                                                         found = true;
480
481                                                                 } else {
482
483                                                                         ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
484                                                                         if(entry != null) entry.except(exception);
485                                                                         procedure.exception(graph, exception);
486
487                                                                 }
488
489                                                         }
490
491                                                         @Override
492                                                         public void finished(ReadGraphImpl graph) {
493                                                         }
494
495                                                         @Override
496                                                         public void exception(ReadGraphImpl graph, Throwable t) {
497                                                                 procedure.exception(graph, t);
498                                                         }
499
500                                                 });
501
502                                         } else {
503
504                                                 SuperRelations.queryEach(graph, pred, graph.processor, entry, null, new InternalProcedure<IntSet>() {
505
506                                                         @Override
507                                                         public void execute(ReadGraphImpl graph, IntSet result) {
508
509                                                                 if(found) return;
510
511                                                                 if(result.contains(r2)) {
512
513                                                                         // Note! The dependency is intentionally cut!
514                                                                         DirectObjects.queryEach(graph, r1, pred, graph.processor, null, null, new IntProcedure() {
515
516                                                                                 @Override
517                                                                                 public void execute(ReadGraphImpl graph, int i) {
518
519                                                                                         if(!found) {
520
521                                                                                                 if(entry != null) entry.addOrSetFunctional(i);
522                                                                                                 else procedure.execute(graph, i);
523
524                                                                                                 found = true;
525
526                                                                                         } else {
527
528                                                                                                 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
529                                                                                                 if(entry != null) entry.except(exception);
530                                                                                                 procedure.exception(graph, exception);
531
532                                                                                         }
533
534                                                                                 }
535
536                                                                                 @Override
537                                                                                 public void finished(ReadGraphImpl graph) {
538                                                                                 }
539
540                                                                                 @Override
541                                                                                 public void exception(ReadGraphImpl graph, Throwable t) {
542                                                                                         procedure.exception(graph, t);
543                                                                                 }
544
545                                                                         });
546
547                                                                 }
548
549                                                         }
550
551                                                         @Override
552                                                         public void exception(ReadGraphImpl graph, Throwable t) {
553                                                                 procedure.exception(graph, t);
554                                                         }
555
556                                                 });
557
558                                         }
559
560                                 }
561
562                                 @Override
563                                 public void finished(ReadGraphImpl graph) {
564
565                                         dec(graph);
566
567                                 }
568
569                         });
570
571
572                 }
573
574         }
575
576         final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure) {
577
578                 // Note! The dependency is intentionally cut!
579                 PrincipalTypes.queryEach(graph, r1, graph.processor, null, null, new SyncIntProcedure() {
580
581                         @Override
582                         public void run(ReadGraphImpl graph) {
583
584                                 if(entry != null) entry.finish(graph, procedure);
585                                 else procedure.finished(graph);
586
587                         }
588
589                         TripleIntProcedure proc = new TripleIntProcedure() {
590
591                                 @Override
592                                 public void execute(ReadGraphImpl graph, int s, int p, int o) {
593                                         if(entry != null) entry.addOrSet(o);
594                                         else procedure.execute(graph, o);
595                                 }
596
597                                 @Override
598                                 public void finished(ReadGraphImpl graph) {
599                                         dec(graph);
600                                 }
601
602                                 @Override
603                                 public void exception(ReadGraphImpl graph, Throwable t) {
604                                         if(DebugException.DEBUG) new DebugException(t).printStackTrace();
605                                         procedure.exception(graph, t);
606                                         dec(graph);
607                                 }
608
609                         };
610
611                         @Override
612                         public void execute(ReadGraphImpl graph, int type) {
613
614                                 inc();
615
616                                 AssertedStatements.queryEach(graph, type, r2, graph.processor, entry, null, proc);
617
618                         }
619
620                         @Override
621                         public void finished(ReadGraphImpl graph) {
622                                 dec(graph);
623                         }
624
625                 });
626
627
628         }
629
630         final public static void computeNotFunctionalFinalIndex(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, RelationInfo ri, AsyncMultiProcedure<Resource> procedure) {
631
632                 throw new Error();
633
634         }
635
636         final public void computeNotFunctionalIndex(ReadGraphImpl graph, RelationInfo ri, final IntProcedure procedure) {
637                 computeNotFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
638         }
639
640         final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, RelationInfo ri, final IntProcedure procedure) {
641
642                 if(ri.isFinal) {
643
644                         graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
645
646                                 @Override
647                                 public void execute(ReadGraphImpl graph, int i) {
648                                         if(entry != null) entry.addOrSet(i);
649                                         else procedure.execute(graph, i);
650                                 }
651
652                                 @Override
653                                 public void exception(ReadGraphImpl graph, Throwable t) {
654                                         if(DebugException.DEBUG) new DebugException(t).printStackTrace();
655                                         procedure.exception(graph, t);
656                                 }
657
658                                 @Override
659                                 public void finished(ReadGraphImpl graph) {
660                                 }
661
662                         });
663
664                         if(ri.isAsserted) {
665                                 forAssertions(graph, r1, r2, entry, procedure);
666                         } else {
667                                 if(entry != null) entry.finish(graph, procedure);
668                                 else procedure.finished(graph);
669                         }
670
671                 } else {
672
673                         // Note! The dependency is intentionally cut!
674                         DirectPredicates.queryEach(graph, r1, graph.processor, null, null, new SyncIntProcedure() {
675
676                                 @Override
677                                 public void run(ReadGraphImpl graph) {
678
679                                         forAssertions(graph, r1, r2, entry, procedure);
680
681                                 }
682
683                                 @Override
684                                 public void execute(ReadGraphImpl graph, final int pred) {
685
686                                         if(pred == r2) {
687
688                                                 inc();
689
690                                                 // Note! The dependency is intentionally cut!
691                                                 DirectObjects.queryEach(graph, r1, pred, graph.processor, null, null, new IntProcedure() {
692
693                                                         @Override
694                                                         public void execute(ReadGraphImpl graph, int i) {
695                                                                 if(entry != null) entry.addOrSet(i);
696                                                                 else procedure.execute(graph, i);
697                                                         }
698
699                                                         @Override
700                                                         public void finished(ReadGraphImpl graph) {
701                                                                 dec(graph);
702                                                         }
703
704                                                         @Override
705                                                         public void exception(ReadGraphImpl graph, Throwable t) {
706                                                                 procedure.exception(graph, t);
707                                                                 dec(graph);
708                                                         }
709
710                                                 });
711
712                                         } else {
713
714                                                 inc();
715
716                                                 SuperRelations.queryEach(graph, pred, graph.processor, entry, null, new InternalProcedure<IntSet>() {
717
718                                                         @Override
719                                                         public void execute(ReadGraphImpl graph, IntSet result) {
720
721                                                                 if(result.contains(r2)) {
722
723                                                                         inc();
724
725                                                                         // Note! The dependency is intentionally cut!
726                                                                         DirectObjects.queryEach(graph, r1, pred, graph.processor, null, null, new IntProcedure() {
727
728                                                                                 @Override
729                                                                                 public void execute(ReadGraphImpl graph, int i) {
730                                                                                         if(entry != null) entry.addOrSet(i);
731                                                                                         else procedure.execute(graph, i);
732                                                                                 }
733
734                                                                                 @Override
735                                                                                 public void finished(ReadGraphImpl graph) {
736                                                                                         dec(graph);
737                                                                                 }
738
739                                                                                 @Override
740                                                                                 public void exception(ReadGraphImpl graph, Throwable t) {
741                                                                                         if(DebugException.DEBUG) new DebugException(t).printStackTrace();
742                                                                                         procedure.exception(graph, t);
743                                                                                         dec(graph);
744                                                                                 }
745
746                                                                         });
747
748                                                                 }
749
750                                                                 dec(graph);
751
752                                                         }
753
754                                                         @Override
755                                                         public void exception(ReadGraphImpl graph, Throwable t) {
756                                                                 procedure.exception(graph, t);
757                                                                 dec(graph);
758                                                         }
759
760                                                 });
761
762                                         }
763
764                                 }
765
766                                 @Override
767                                 public void finished(ReadGraphImpl graph) {
768                                         dec(graph);
769                                 }
770
771                         });
772
773                 }
774
775         }
776
777         @Override
778         public void computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final IntProcedure procedure, final boolean store) {
779                 computeForEach(graph, r1(), r2(), this, procedure);
780         }
781
782         public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure) {
783
784                 RelationInfo ri = RelationInfoQuery.queryEach(graph, r2, graph.processor, entry, null, ip);
785                 graph.ensureLoaded(r1, r2);       
786                 if(ri.isFunctional) {
787                         computeFunctionalIndex(graph, r1, r2, entry, ri, procedure);
788                 } else {
789                         computeNotFunctionalIndex(graph, r1, r2, entry, ri, procedure);
790                 }
791
792         }
793
794         final static InternalProcedure<RelationInfo> ip = new InternalProcedure<RelationInfo>() {
795
796                 @Override
797                 public void execute(ReadGraphImpl graph, RelationInfo result) {
798                 }
799
800                 @Override
801                 public void exception(ReadGraphImpl graph, Throwable throwable) {
802                 }
803
804         };
805
806         @Override
807         public String toString() {
808                 return "Objects[" + r1() + " - " + r2() + "]";
809         }
810
811         final private void finish(ReadGraphImpl graph, IntProcedure procedure) {
812
813                 assert(assertPending());
814
815                 synchronized(this) {
816                         setReady();
817                 }
818
819                 IntArray v = (IntArray)getResult();
820
821                 if(v.data == null) {
822                         if(v.sizeOrData != IntArray.NO_DATA) {
823                                 procedure.execute(graph, v.sizeOrData);
824                         }
825                 } else {
826                         for(int i = 0;i < v.sizeOrData ; i++) {
827                                 procedure.execute(graph, v.data[i]);
828                         }
829                 }
830
831                 procedure.finished(graph);
832
833         }
834
835         final public void addOrSet(int add) {
836
837                 assert(assertPending());
838
839                 IntArray value = (IntArray)getResult();
840                 synchronized(value) {
841                         value.add(add);
842                 }
843
844         }
845
846         final public void addOrSetFunctional(int add) {
847
848                 assert(isPending());
849
850                 IntArray value = (IntArray)getResult();
851                 value.add(add);
852
853         }
854
855         @Override
856         public void performFromCache(ReadGraphImpl graph, QueryProcessor provider, final IntProcedure procedure) {
857
858                 assert(isReady());
859
860                 if(handleException(graph, procedure)) return;
861
862                 final IntArray value = (IntArray)getResult();
863                 if(value.data == null) {
864                         if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
865                 } else {
866                         for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
867                 }
868
869                 procedure.finished(graph);
870
871         }
872
873         @Override
874         public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
875
876                 final Semaphore s = new Semaphore(0);
877
878                 computeForEach(graph, provider, new IntProcedureAdapter() {
879
880                         @Override
881                         public void finished(ReadGraphImpl graph) {
882                                 s.release();
883                         }
884
885                         @Override
886                         public void exception(ReadGraphImpl graph, Throwable t) {
887                                 s.release();
888                                 new Error("Error in recompute.", t).printStackTrace();
889                         }
890
891                 }, true);
892
893                 while(!s.tryAcquire()) {
894                         provider.resume(graph);
895                 }
896
897         }
898
899         @Override
900         public int type() {
901                 return RequestFlags.IMMEDIATE_UPDATE;
902         }
903
904         @Override
905         boolean isImmutable(ReadGraphImpl graph) {
906                 return graph.processor.isImmutable(r1());
907         }
908
909 }