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