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