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