]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ResourceElementSmall.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / ResourceElementSmall.java
1 package org.simantics.db.procore.cluster;\r
2 \r
3 import org.simantics.db.Resource;\r
4 import org.simantics.db.exception.DatabaseException;\r
5 import org.simantics.db.exception.ExternalValueException;\r
6 import org.simantics.db.impl.ClusterI;\r
7 import org.simantics.db.impl.ClusterSupport;\r
8 import org.simantics.db.impl.ClusterTraitsBase;\r
9 import org.simantics.db.impl.Modifier;\r
10 import org.simantics.db.impl.ResourceImpl;\r
11 import org.simantics.db.impl.graph.ReadGraphImpl;\r
12 import org.simantics.db.procedure.AsyncContextMultiProcedure;\r
13 import org.simantics.db.procedure.AsyncMultiProcedure;\r
14 \r
15 \r
16 public final class ResourceElementSmall {\r
17     private static final boolean DEBUG = ClusterImpl.DEBUG;\r
18     // Descriptor = type & complete object reference & value index & predicate index. \r
19     private static final int DESCRIPTOR_OFFSET = 0; // descriptor\r
20     private static final int STM_OFFSET        = 1; // two statements\r
21     private static final int SIZE_OF           = 2;\r
22 \r
23     static void construct(long[] table, int index) {\r
24         int i = DESCRIPTOR_OFFSET + index;\r
25         table[i++] = 0; // descriptor\r
26         table[i++] = 0; // stm1 & 2\r
27     }\r
28 \r
29     static void destruct(long[] table, int index) {\r
30         int i = DESCRIPTOR_OFFSET + index;\r
31         table[i++] = 0; // descriptor\r
32         table[i++] = 0; // stm1 & 2\r
33     }\r
34 \r
35     static boolean isUsed(long[] table, int index) {\r
36         int i = DESCRIPTOR_OFFSET + index;\r
37         if (table[i++] != 0)\r
38             return true;\r
39         if (table[i++] != 0)\r
40             return true;\r
41         return false;\r
42     }\r
43 \r
44     static int getSizeOf() {\r
45         return SIZE_OF;\r
46     }\r
47 \r
48     static ClusterI.CompleteTypeEnum getCompleteType(long[] table, int index) {\r
49         int i = DESCRIPTOR_OFFSET + index;\r
50         byte bits = (byte)BitUtility.getMiddle(table[i], 62, 2);\r
51         return ClusterI.CompleteTypeEnum.make(bits);\r
52     }\r
53 \r
54     static void setCompleteType(long[] table, int index, byte data) {\r
55         int i = DESCRIPTOR_OFFSET + index;\r
56         table[i] = BitUtility.setMiddle(table[i], 62, 2, data);\r
57     }\r
58 \r
59     static short getCompleteObjectRef(long[] table, int index) {\r
60         int i = DESCRIPTOR_OFFSET + index;\r
61         return (short)BitUtility.getMiddle(table[i], 46, 16);\r
62     }\r
63 \r
64     static void setCompleteObjectRef(long[] table, int index, int ref) {\r
65         if (ref > (1<<16)-1)\r
66             throw new IllegalArgumentException();\r
67         int i = DESCRIPTOR_OFFSET + index;\r
68         table[i] = BitUtility.setMiddle(table[i], 46, 16, ref);\r
69     }\r
70 \r
71     static boolean completeHasMultiple(long[] table, int index) {\r
72         int i = DESCRIPTOR_OFFSET + index;\r
73         int completeRefAndType= BitUtility.getMiddle(table[i], 46, 18); \r
74         boolean complete = (completeRefAndType >>> 16) != 0;\r
75         return !complete && (completeRefAndType != 0);\r
76     }\r
77 \r
78     static boolean completeIsFirstStatement(long[] table, int index) {\r
79         int i = DESCRIPTOR_OFFSET + index;\r
80         int completeRefAndType = BitUtility.getMiddle(table[i], 46, 18); \r
81         return completeRefAndType == 0;\r
82     }\r
83     \r
84     static boolean completeIsSameStatement(long[] table, int index, int refAndType) {\r
85         int i = DESCRIPTOR_OFFSET + index;\r
86         int completeRefAndType = BitUtility.getMiddle(table[i], 46, 18); \r
87         return completeRefAndType == refAndType;\r
88     }\r
89     \r
90     static int completeGetRefAndType(long[] table, int index) {\r
91         int i = DESCRIPTOR_OFFSET + index;\r
92         return BitUtility.getMiddle(table[i], 46, 18);\r
93     }\r
94     \r
95     static void completeSetRefAndType(long[] table, int index, int refAndType) {\r
96         int i = DESCRIPTOR_OFFSET + index;\r
97         table[i] = BitUtility.setMiddle(table[i], 46, 18, refAndType); \r
98     }\r
99     \r
100     static int completeMakeObjectRefAndType(short oRef, ClusterI.CompleteTypeEnum completeType) {\r
101         return oRef & (1<<16)-1 | completeType.getValue()<<16;\r
102     }\r
103     \r
104     static short completeGetObjectSetIndex(long[] table, int index) {\r
105         int i = DESCRIPTOR_OFFSET + index;\r
106         return (short)BitUtility.getMiddle(table[i], 46, 16);\r
107     }\r
108     \r
109     static int completeGetStatementCountApproximation(long[] table, int index) {\r
110         int i = DESCRIPTOR_OFFSET + index;\r
111         int cType = BitUtility.getMiddle(table[i], 62, 2);\r
112         if (cType != 0)\r
113             return 1;\r
114         int cRef = BitUtility.getMiddle(table[i], 46, 16);\r
115         if (cRef != 0)\r
116             return 2; // Can be bigger, hence the approximation. \r
117         return 0;\r
118     }\r
119     \r
120     static int getValueIndex(long[] table, int index) {\r
121         int i = DESCRIPTOR_OFFSET + index;\r
122         int valueIndex = BitUtility.getMiddle(table[i], 24, 22);\r
123         return valueIndex;\r
124     }\r
125 \r
126     static void setValueIndex(long[] table, int index, int valueIndex) {\r
127         int i = DESCRIPTOR_OFFSET + index;\r
128         table[i] = BitUtility.setMiddle(table[i], 24, 22, valueIndex);\r
129     }\r
130 \r
131     static int getPredicateIndex(long[] table, int index) {\r
132         int i = DESCRIPTOR_OFFSET + index;\r
133         int predicateIndex = BitUtility.getMiddle(table[i], 0, 24);\r
134         return predicateIndex;\r
135     }\r
136 \r
137     static void setPredicateIndex(long[] table, int index, int predicateIndex) {\r
138         int i = DESCRIPTOR_OFFSET + index;\r
139         table[i] = BitUtility.setMiddle(table[i], 0, 24, predicateIndex);\r
140     }\r
141 \r
142     static short getStm1Predicate(long[] table, int index) {\r
143         int i = STM_OFFSET + index;\r
144         short predicateIndex = BitUtility.getLowShort(table[i]);\r
145         return predicateIndex;\r
146     }\r
147 \r
148     static void setStm1Predicate(long[] table, int index, short predicateIndex) {\r
149         int i = STM_OFFSET + index;\r
150         table[i] = BitUtility.setLowShort(table[i], predicateIndex);\r
151     }\r
152     \r
153     static short getStm1Object(long[] table, int index) {\r
154         int i = STM_OFFSET + index;\r
155         short objectIndex = (short)BitUtility.getMiddle(table[i], 16, 16);\r
156         return objectIndex;\r
157     }\r
158 \r
159     static void setStm1Object(long[] table, int index, short objectIndex) {\r
160         int i = STM_OFFSET + index;\r
161         table[i] = BitUtility.setMiddle(table[i], 16, 16, objectIndex);\r
162     }\r
163     \r
164     static short getStm2Predicate(long[] table, int index) {\r
165         int i = STM_OFFSET + index;\r
166         short predicateIndex = (short)BitUtility.getMiddle(table[i], 32, 16);\r
167         return predicateIndex;\r
168     }\r
169 \r
170     static void setStm2Predicate(long[] table, int index, short predicateIndex) {\r
171         int i = STM_OFFSET + index;\r
172         table[i] = BitUtility.setMiddle(table[i], 32, 16, predicateIndex);\r
173     }\r
174 \r
175     static short getStm2Object(long[] table, int index) {\r
176         int i = STM_OFFSET + index;\r
177         short objectIndex = (short)BitUtility.getMiddle(table[i], 48, 16);\r
178         return objectIndex;\r
179     }\r
180 \r
181     static void setStm2Object(long[] table, int index, short objectIndex) {\r
182         int i = STM_OFFSET + index;\r
183         table[i] = BitUtility.setMiddle(table[i], 48, 16, objectIndex);\r
184     }\r
185 \r
186     public static byte[] getValue(ValueTableSmall valueTable, long[] table, int index)\r
187     throws DatabaseException {\r
188         int valueIndex = getValueIndex(table, index);\r
189         if (0 == valueIndex)\r
190             return null; // no value\r
191         else if (ClusterTraitsSmall.VALUE_INDEX_EX == valueIndex)\r
192             throw new ExternalValueException("Value stored externally. index=" + index);\r
193         return valueTable.getValue(valueIndex);\r
194     }\r
195 //KRAA:\r
196 //    static char[] getString(ValueTableSmall valueTable, long[] table, int index) {\r
197 //        int valueIndex = getValueIndex(table, index);\r
198 //        if (0 == valueIndex)\r
199 //            return null; // no value\r
200 ////        else if (ClusterTraitsSmall.VALUE_INDEX_MAX == valueIndex)\r
201 ////            throw new Error("Not implemented! //KRAA:");\r
202 //        return valueTable.getString(valueIndex);\r
203 //    }\r
204 \r
205     static boolean hasValue(long[] table, int index) {\r
206         int valueIndex = getValueIndex(table, index);\r
207         return 0 != valueIndex;\r
208     }\r
209 \r
210 //    static boolean hasValue(ValueTable valueTable, long[] table, int index, byte[] value) {\r
211 //        int valueIndex = getValueIndex(table, index);\r
212 //        if (0 == valueIndex)\r
213 //            return false;\r
214 //        return valueTable.isEqual(valueIndex, value, 0, value.length);\r
215 //    }\r
216 \r
217     static boolean removeValue(ValueTableSmall valueTable, long[] table, int index) {\r
218         int valueIndex = getValueIndex(table, index);\r
219         if (0 == valueIndex)\r
220             return false; // not removed\r
221         else if (ClusterTraitsSmall.VALUE_INDEX_EX != valueIndex)\r
222             valueTable.removeValue(valueIndex);\r
223         setValueIndex(table, index, 0);\r
224         return true;\r
225     }\r
226 \r
227     public static void setValue(ValueTableSmall valueTable, long[] table, int index, byte[] value, int length)\r
228     throws OutOfSpaceException {\r
229         int oldIndex = getValueIndex(table, index);\r
230         if (ClusterTraitsSmall.VALUE_INDEX_EX == oldIndex)\r
231             oldIndex = 0;\r
232         if (length > ClusterTraitsSmall.VALUE_SIZE_MAX)\r
233             throw new OutOfSpaceException("Out of space for value. size=" + length);\r
234         int newIndex = valueTable.setValue(oldIndex, value, 0, length);\r
235         if (newIndex != oldIndex) {\r
236             if (newIndex > ClusterTraitsSmall.VALUE_INDEX_MAX) {\r
237                 setValueIndex(table, index, 0);\r
238                 throw new OutOfSpaceException("Out of space for values. index=" + newIndex);\r
239             }\r
240             setValueIndex(table, index, newIndex);\r
241         }\r
242         return;\r
243     }\r
244 \r
245     public static boolean isValueEx(ValueTableSmall valueTable, long[] table, int index) {\r
246         int vIndex = getValueIndex(table, index);\r
247         if (ClusterTraitsSmall.VALUE_INDEX_EX == vIndex)\r
248             return true;\r
249         else\r
250             return false;\r
251     }\r
252 \r
253     public static void setValueEx(ValueTableSmall valueTable, long[] table, int index) {\r
254         setValueIndex(table, index, ClusterTraitsSmall.VALUE_INDEX_EX);\r
255     }\r
256 \r
257     public static <Context> boolean foreachPredicate(long[] table, int index,\r
258             ClusterI.PredicateProcedure<Context> procedure,\r
259             Context context, ClusterSupport support, Modifier modifier,\r
260             CompleteTable ct)\r
261     throws DatabaseException {\r
262         if (DEBUG)\r
263             System.out.println("ResourceElement.foreachPredicate: 1");\r
264         int completeRef = ResourceElementSmall.getCompleteObjectRef(table, index);\r
265         if (0 != completeRef) {\r
266             if (ResourceElementSmall.completeHasMultiple(table, index)) { // multiple complete objects\r
267                 // CompleteRef is a complete object set index.\r
268                 boolean broken = ct.foreachPredicate(completeRef, procedure, context, support, modifier);\r
269                 if (DEBUG)\r
270                     System.out.println("ResourceElement.foreachPredicate: multi-complete ci=" + completeRef + " break=" + broken);\r
271                 if (broken)\r
272                     return true; // loop broken by procedure\r
273             } else { // We have zero or one complete statement.\r
274                 ClusterI.CompleteTypeEnum completeType = ResourceElementSmall.getCompleteType(table, index);\r
275                 if (ClusterI.CompleteTypeEnum.NotComplete != completeType) {\r
276                     int key = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType);\r
277                     boolean broken = procedure.execute(context, key, 0);\r
278                     if (DEBUG)\r
279                         System.out.println("ResourceElement.foreachPredicate: complete rk=" + key + " break=" + broken);\r
280                     if (broken)\r
281                         return true; // loop broken by procedure\r
282                 }\r
283             }\r
284         }\r
285         // If predicate set is in use it will contain also these statements.\r
286         if (0 != ResourceElementSmall.getPredicateIndex(table, index)) {\r
287             if (DEBUG)\r
288                 System.out.println("ResourceElement.foreachPredicate: more than 2 objects");\r
289             return false;\r
290         }\r
291         int p1 = getStm1Predicate(table, index);\r
292         if (0 == p1) {\r
293             if (DEBUG)\r
294                 System.out.println("ResourceElement.foreachPredicate: empty cache");\r
295             return false; // loop finished, no statements\r
296         }\r
297         int externalRef;\r
298         if (null == modifier)\r
299             externalRef = p1;\r
300         else\r
301             externalRef = modifier.execute(p1);\r
302         if (DEBUG)\r
303             System.out.println("ResourceElement.foreachPredicate: cache1 pk=" + externalRef);\r
304         if (procedure.execute(context, externalRef, 0))\r
305             return true; // loop broken by procedure\r
306         int p2 = getStm2Predicate(table, index);\r
307         if (0 == p2 || p1 == p2) {\r
308             if (DEBUG)\r
309                 System.out.println("ResourceElement.foreachPredicate: cache2 empty");\r
310             return false; // loop finished, one predicate\r
311         }\r
312         if (null == modifier)\r
313             externalRef = p2;\r
314         else\r
315             externalRef = modifier.execute(p2);\r
316         if (DEBUG)\r
317             System.out.println("ResourceElement.foreachPredicate: cache2 pk=" + externalRef);\r
318         return procedure.execute(context, externalRef, 0);\r
319     }\r
320 \r
321     public static int getSingleObject(long[] table, int index, ClusterSupport support, final short pRef,\r
322             final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier)\r
323     throws DatabaseException {\r
324         if (DEBUG)\r
325             System.out.println("ResourceElement.getSingleObject: index=" + index);\r
326         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
327             int completeRef = getCompleteObjectRef(table, index);\r
328             if (0 == completeRef)\r
329                 return 0; // no objects for given complete type\r
330             if (ResourceElementSmall.completeHasMultiple(table, index)) {\r
331                 // Multiple complete type statements.\r
332                 if (DEBUG)\r
333                     System.out.println("ResourceElement.was complete 2");\r
334                 ClusterI.ObjectProcedure<Short> proc = new ClusterI.ObjectProcedure<Short>() {\r
335                     @Override\r
336                     public boolean execute(Short context, int completeRefAndType)\r
337                     throws DatabaseException {\r
338                         ClusterI.CompleteTypeEnum ct = ClusterTraitsSmall.completeRefAndTypeGetType(completeRefAndType);\r
339                         if (ct == pCompleteType) { // we have a match\r
340                             if (context != 0) { // we have an old match\r
341                                 context = 0; // multiple objects for given type\r
342                                 return true; // break loop\r
343                             }\r
344                             context = ClusterTraitsSmall.completeRefAndTypeGetRef(completeRefAndType);\r
345                         }\r
346                         return true; // continue looping\r
347                     }\r
348                 };\r
349                 Short objectRef = 0;\r
350                 // CompleteRef is complete object set index.\r
351                 ct.foreachComplete(completeRef, proc, objectRef, support, modifier);\r
352                 return modifier.execute(objectRef);\r
353             } // One complete type statement.\r
354             ClusterI.CompleteTypeEnum rCompleteType = ResourceElementSmall.getCompleteType(table, index);\r
355             if (pCompleteType != rCompleteType)\r
356                 return 0; // no objects for given complete type\r
357             // CompleteRef is object resource reference.\r
358             return modifier.execute(completeRef);\r
359         }\r
360         int p1 = getStm1Predicate(table, index);\r
361         if (0 == p1)\r
362             return 0; // loop finished, no statements\r
363         int result = 0;\r
364         if (pRef == p1) {\r
365             short o1 = getStm1Object(table, index);\r
366             result = modifier.execute(o1);\r
367 //            procedure.execute(graph, new ResourceImpl(null, modifier.execute(o1)));\r
368 //            int externalRef;\r
369 //            if (null == modifier)\r
370 //                externalRef = o1;\r
371 //            else\r
372 //                externalRef = modifier.execute(callerThread, o1);\r
373 //            if (procedure.execute(callerThread, context, externalRef))\r
374 //                return true; // loop broken by procedure\r
375         }\r
376         int p2 = getStm2Predicate(table, index);\r
377         if (0 == p2 || pRef != p2)\r
378             return result; // loop finished, one statements\r
379 \r
380         // Many statements\r
381         if (result != 0) return -1;\r
382         \r
383         short o2 = getStm2Object(table, index);\r
384         return modifier.execute(o2);\r
385 //        int externalRef;\r
386 //        if (null == modifier)\r
387 //            externalRef = o2;\r
388 //        else\r
389 //            externalRef = modifier.execute(callerThread, o2);\r
390 //        if (procedure.execute(callerThread, context, externalRef))\r
391 //            return true; // loop broken by procedure\r
392 //        return false; // loop finished\r
393 //        procedure.execute(graph, new ResourceImpl(null, modifier.execute(o2)));\r
394     }\r
395 \r
396     public static void foreachObject(long[] table, int index,\r
397             final ReadGraphImpl graph, final AsyncMultiProcedure<Resource> procedure,\r
398             ClusterSupport support, final int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier)\r
399     throws DatabaseException {\r
400         if (DEBUG)\r
401             System.out.println("ResourceElement.foreachObject1: index=" + index);\r
402         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
403             int completeRef = getCompleteObjectRef(table, index);\r
404             if (0 == completeRef) {\r
405                 procedure.finished(graph);\r
406 //                graph.state.dec(0);\r
407                 return; // no objects for given complete type\r
408             }\r
409             if (ResourceElementSmall.completeHasMultiple(table, index)) {// multiple objects\r
410                 ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {\r
411                     @Override\r
412                     public boolean execute(Object _context, int objectRef)\r
413                     throws DatabaseException {\r
414                         procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(objectRef)));\r
415                         return false; // continue looping\r
416                     }\r
417                     \r
418                 };\r
419                 // CompleteRef is complete object set index.\r
420                 ct.foreachComplete(completeRef, proc, null, support, modifier);\r
421             } else { // One complete type element. CompleteRef is resource reference.\r
422                 ClusterI.CompleteTypeEnum rCompleteType = ResourceElementSmall.getCompleteType(table, index);\r
423                 if (pCompleteType != rCompleteType) {\r
424                     procedure.finished(graph);\r
425 //                    graph.state.dec(0);\r
426                     return; // Complete predicate does not match.\r
427                 }\r
428                 procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(completeRef)));\r
429             }\r
430             procedure.finished(graph);\r
431 //            graph.state.dec(0);\r
432             return; // loop finished\r
433         }\r
434         short p1 = getStm1Predicate(table, index);\r
435         if (0 == p1) {\r
436             procedure.finished(graph);\r
437 //            graph.state.dec(0);\r
438             return; // loop finished, no statements\r
439         }\r
440         if (pRef == p1) {\r
441             short o1 = getStm1Object(table, index);\r
442             procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1)));\r
443 //            int externalRef;\r
444 //            if (null == modifier)\r
445 //                externalRef = o1;\r
446 //            else\r
447 //                externalRef = modifier.execute(callerThread, o1);\r
448 //            if (procedure.execute(callerThread, context, externalRef))\r
449 //                return true; // loop broken by procedure\r
450         }\r
451         short p2 = getStm2Predicate(table, index);\r
452         if (0 == p2 || pRef != p2) {\r
453             procedure.finished(graph);\r
454 //            graph.state.dec(0);\r
455             return; // loop finished, one statements\r
456         }\r
457         int o2 = getStm2Object(table, index);\r
458 //        int externalRef;\r
459 //        if (null == modifier)\r
460 //            externalRef = o2;\r
461 //        else\r
462 //            externalRef = modifier.execute(callerThread, o2);\r
463 //        if (procedure.execute(callerThread, context, externalRef))\r
464 //            return true; // loop broken by procedure\r
465 //        return false; // loop finished\r
466         procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2)));\r
467         procedure.finished(graph);\r
468 //        graph.state.dec(0);\r
469     }\r
470     \r
471     public static <C> void foreachObject(long[] table, int index,\r
472             final ReadGraphImpl graph, final C context, final AsyncContextMultiProcedure<C, Resource> procedure,\r
473             ClusterSupport support, final int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier)\r
474     throws DatabaseException {\r
475         if (DEBUG)\r
476             System.out.println("ResourceElement.foreachObject1: index=" + index);\r
477         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
478             int completeRef = getCompleteObjectRef(table, index);\r
479             if (0 == completeRef) {\r
480                 procedure.finished(graph);\r
481 //                graph.state.dec(0);\r
482                 return; // no objects for given complete type\r
483             }\r
484             if (ResourceElementSmall.completeHasMultiple(table, index)) {// multiple objects\r
485                 ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {\r
486                     @Override\r
487                     public boolean execute(Object _context, int objectRef)\r
488                     throws DatabaseException {\r
489                         procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(objectRef)));\r
490                         return false; // continue looping\r
491                     }\r
492                     \r
493                 };\r
494                 // CompleteRef is complete object set index.\r
495                 ct.foreachComplete(completeRef, proc, null, support, modifier);\r
496             } else { // One complete type element. CompleteRef is resource reference.\r
497                 ClusterI.CompleteTypeEnum rCompleteType = ResourceElementSmall.getCompleteType(table, index);\r
498                 if (pCompleteType != rCompleteType) {\r
499                     procedure.finished(graph);\r
500 //                    graph.state.dec(0);\r
501                     return; // Complete predicate does not match.\r
502                 }\r
503                 procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(completeRef)));\r
504             }\r
505             procedure.finished(graph);\r
506 //            graph.state.dec(0);\r
507             return; // loop finished\r
508         }\r
509         short p1 = getStm1Predicate(table, index);\r
510         if (0 == p1) {\r
511             procedure.finished(graph);\r
512 //            graph.state.dec(0);\r
513             return; // loop finished, no statements\r
514         }\r
515         if (pRef == p1) {\r
516             short o1 = getStm1Object(table, index);\r
517             procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1)));\r
518 //            int externalRef;\r
519 //            if (null == modifier)\r
520 //                externalRef = o1;\r
521 //            else\r
522 //                externalRef = modifier.execute(callerThread, o1);\r
523 //            if (procedure.execute(callerThread, context, externalRef))\r
524 //                return true; // loop broken by procedure\r
525         }\r
526         short p2 = getStm2Predicate(table, index);\r
527         if (0 == p2 || pRef != p2) {\r
528             procedure.finished(graph);\r
529 //            graph.state.dec(0);\r
530             return; // loop finished, one statements\r
531         }\r
532         int o2 = getStm2Object(table, index);\r
533 //        int externalRef;\r
534 //        if (null == modifier)\r
535 //            externalRef = o2;\r
536 //        else\r
537 //            externalRef = modifier.execute(callerThread, o2);\r
538 //        if (procedure.execute(callerThread, context, externalRef))\r
539 //            return true; // loop broken by procedure\r
540 //        return false; // loop finished\r
541         procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2)));\r
542         procedure.finished(graph);\r
543 //        graph.state.dec(0);\r
544     }\r
545 \r
546     public static <Context> boolean foreachObject(long[] table, int index\r
547             , ClusterI.ObjectProcedure<Context> procedure\r
548             , Context context, ClusterSupport support, Modifier modifier\r
549             , final short pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)\r
550     throws DatabaseException {\r
551         if (DEBUG)\r
552             System.out.println("ResourceElementSmall.foreachObject2: 1");\r
553         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
554             int completeRef = getCompleteObjectRef(table, index);\r
555             if (0 == completeRef) {\r
556                 if (DEBUG)\r
557                     System.out.println("ResourceElementSmall.foreachObject2: no complete");\r
558                 return false; // no objects for given complete type\r
559             } if (ResourceElementSmall.completeHasMultiple(table, index)) {\r
560                 if (DEBUG)\r
561                     System.out.println("ResourceElementSmall.foreachObject2: multi-complete ci=" + completeRef);\r
562                 // CompleteRef is complete object set index.\r
563                 return ct.foreachObject(completeRef, procedure, context, support, modifier, pCompleteType);\r
564             }\r
565             // One complete type statement at most.\r
566             ClusterI.CompleteTypeEnum completeType = ResourceElementSmall.getCompleteType(table, index);\r
567             if (pCompleteType != completeType) {\r
568                 if (DEBUG)\r
569                     System.out.println("ResourceElementSmall.foreachObject2: complete different predicate");\r
570                 return false; // Loop finished. No objects for given complete predicate type.\r
571             }\r
572             int externalRef = completeRef;\r
573             if (null != modifier)\r
574                 externalRef = modifier.execute(externalRef);\r
575             if (DEBUG)\r
576                 System.out.println("ResourceElementSmall.foreachObject2: complete ok=" + externalRef);\r
577             return procedure.execute(context, externalRef);\r
578         }\r
579         int p1 = getStm1Predicate(table, index);\r
580         if (0 == p1) {\r
581             if (DEBUG)\r
582                 System.out.println("ResourceElementSmall.foreachObject2: empty cache=");\r
583             return false; // loop finished, no statements\r
584         }\r
585         if (pRef == p1) {\r
586             int o1 = getStm1Object(table, index);\r
587             int externalRef;\r
588             if (null == modifier)\r
589                 externalRef = o1;\r
590             else\r
591                 externalRef = modifier.execute(o1);\r
592             if (DEBUG)\r
593                 System.out.println("ResourceElementSmall.foreachObject2: cache1 ok=" + externalRef);\r
594             if (procedure.execute(context, externalRef))\r
595                 return true; // loop broken by procedure\r
596         }\r
597         int p2 = getStm2Predicate(table, index);\r
598         if (0 == p2 || pRef != p2) {\r
599             if (DEBUG)\r
600                 System.out.println("ResourceElementSmall.foreachObject2: not in cache1");\r
601             return false; // loop finished, one statements\r
602         }\r
603         int o2 = getStm2Object(table, index);\r
604         int externalRef;\r
605         if (null == modifier)\r
606             externalRef = o2;\r
607         else\r
608             externalRef = modifier.execute(o2);\r
609         if (DEBUG)\r
610             System.out.println("ResourceElementSmall.foreachObject2: cache2 ok=" + externalRef);\r
611         return procedure.execute(context, externalRef);\r
612     }\r
613     static boolean isEmpty(long[] table, int index) {\r
614         return getStatementCountApproximation(table, index) == 0 && !hasValue(table, index);\r
615     }\r
616     static int getStatementCountApproximation(long[] table, int index) {\r
617         int n = ResourceElementSmall.completeGetStatementCountApproximation(table, index);\r
618         short p1 = getStm1Predicate(table, index);\r
619         if (0 == p1)\r
620             return n;\r
621         short p2 = getStm2Predicate(table, index);\r
622         if (0 == p2)\r
623             return n+1;\r
624         int predicateIndex = getPredicateIndex(table, index);\r
625         if (0 == predicateIndex)\r
626             return n + 2;\r
627         return n + 3; // Can be bigger, hence the approximation.\r
628     }\r
629     static int addStatement(long[] table, int index, short pRef, short oRef\r
630             , PredicateTable pt, ObjectTable ot\r
631             , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
632     throws DatabaseException {\r
633         assert (0 != pRef);\r
634         assert (0 != oRef);\r
635         if (ClusterI.CompleteTypeEnum.NotComplete != completeType) { // predicate is complete type\r
636             int coRefAndType = completeMakeObjectRefAndType(oRef, completeType);\r
637             if (completeIsFirstStatement(table, index))\r
638                 completeSetRefAndType(table, index, coRefAndType);\r
639             else { // old complete statements exist\r
640                 if (completeIsSameStatement(table, index, coRefAndType))\r
641                     return -1; // old complete\r
642                 int nRef;\r
643                 if (completeHasMultiple(table, index)) { // nth statement\r
644                     int coSetIndex = completeGetObjectSetIndex(table, index) & 0xFFFF;\r
645                     nRef = ct.addComplete(coSetIndex, coRefAndType);\r
646                     if (0 == nRef)\r
647                         return -1; // old complete\r
648                     else if (nRef >= 1<<16) {\r
649                         ct.removeComplete(coSetIndex, coRefAndType);\r
650                         throw new OutOfSpaceException("Out of space for complete objects. index=" + nRef);\r
651                     }\r
652                 } else { // second statement\r
653                     int coRefAndTypeOld = ResourceElementSmall.completeGetRefAndType(table, index);\r
654                     nRef = ct.createCompleteArraySet(coRefAndTypeOld, coRefAndType);\r
655                     if (nRef >= 1<<16)\r
656                         throw new OutOfSpaceException("Out of space for complete objects. index=" + nRef);\r
657                     ResourceElementSmall.setCompleteType(table, index, (byte)0);\r
658                 }\r
659                 setCompleteObjectRef(table, index, nRef);\r
660             }\r
661             return 0; // added to complete\r
662         }\r
663         short p1 = getStm1Predicate(table, index);\r
664         short o1 = getStm1Object(table, index);\r
665         if (0 == p1) {\r
666             setStm1Predicate(table, index, pRef);\r
667             setStm1Object(table, index, oRef);\r
668             return 0; // added to stm cache\r
669         } else if (p1 == pRef && o1 == oRef)\r
670             return -1; // same statement\r
671         short p2 = getStm2Predicate(table, index);\r
672         short o2 = getStm2Object(table, index);\r
673         if (0 == p2) {\r
674             setStm2Predicate(table, index, pRef);\r
675             setStm2Object(table, index, oRef);\r
676             return 0; // added to stm cache\r
677         } else if (p2 == pRef && o2 == oRef)\r
678             return -1; // same statement\r
679         int predicateIndex = getPredicateIndex(table, index);\r
680         if (0 == predicateIndex) {\r
681             if (p1 == p2) {\r
682                 int objectIndex = ot.createObjectSet(o1 & 0xFFFF, o2 & 0xFFFF);\r
683                 assert (0 != objectIndex);\r
684                 int[] os = new int[1];\r
685                 os[0] = ClusterTraits.statementIndexMake(objectIndex);\r
686                 int[] ps = new int[1];\r
687                 ps[0] = p1 & 0xFFFF;\r
688                 predicateIndex = pt.createPredicateSet(ps, os);\r
689             } else {\r
690                 int[] os = new int[2];\r
691                 os[0] = o1 & 0xFFFF; \r
692                 os[1] = o2 & 0xFFFF;\r
693                 int[] ps = new int[2];\r
694                 ps[0] = p1 & 0xFFFF;\r
695                 ps[1] = p2 & 0xFFFF;\r
696                 predicateIndex = pt.createPredicateSet(ps, os);\r
697             }\r
698             assert (0 != predicateIndex);\r
699             setPredicateIndex(table, index, predicateIndex);\r
700         }\r
701         assert (0 != predicateIndex);\r
702         return predicateIndex;\r
703     }\r
704 \r
705     static boolean removeStatement(long[] table, int index, short pRef, short oRef,\r
706             ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
707     throws DatabaseException {\r
708         assert (0 != pRef);\r
709         assert (0 != oRef);\r
710         if (completeType != ClusterI.CompleteTypeEnum.NotComplete) {\r
711             int completeRef = ResourceElementSmall.getCompleteObjectRef(table, index);\r
712             if (0 == completeRef)\r
713                 return false; // Statement not removed because it doesn't exist.\r
714             int refAndType = ResourceElementSmall.completeMakeObjectRefAndType(oRef, completeType);\r
715             if (ResourceElementSmall.completeIsSameStatement(table, index, refAndType)) {\r
716                 ResourceElementSmall.completeSetRefAndType(table, index, 0);\r
717                 return true; // statement removed\r
718             } else if (ResourceElementSmall.completeHasMultiple(table, index)) {\r
719                 // CompleteRef is index to complete table.\r
720                 int oldSize = ct.getCompleteSetSize(completeRef);\r
721                 int newSize = ct.removeComplete(completeRef, refAndType);\r
722                 if (oldSize == newSize)\r
723                     return false; // not removed\r
724                 else if (newSize == 1) {\r
725                     int cRef = ct.removeLast(completeRef);\r
726                     ResourceElementSmall.completeSetRefAndType(table, index, cRef);\r
727                 }\r
728                 return true; \r
729             }\r
730             return false; // Statement not removed because it doesn't exist.\r
731         }\r
732         short p1 = getStm1Predicate(table, index);\r
733         short o1 = getStm1Object(table, index);\r
734         if (0 == p1)\r
735             return false; // no statements cached\r
736         short p2 = getStm2Predicate(table, index);\r
737         short o2 = getStm2Object(table, index);\r
738         if (p1 == pRef && o1 == oRef) {\r
739             setStm1Predicate(table, index, p2);\r
740             setStm1Object(table, index, o2);\r
741             setStm2Predicate(table, index, (short)0);\r
742             setStm2Object(table, index, (short)0);\r
743             return true; // statement removed\r
744         }\r
745         if (0 == p2)\r
746             return false; // no match\r
747         else if (p2 == pRef && o2 == oRef) {\r
748             setStm2Predicate(table, index, (short)0);\r
749             setStm2Object(table, index, (short)0);\r
750             return true; // statement removed\r
751         }\r
752         return false;\r
753     }\r
754 }\r