--- /dev/null
+package org.simantics.db.procore.cluster;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ExternalValueException;\r
+import org.simantics.db.impl.ClusterI;\r
+import org.simantics.db.impl.ClusterSupport;\r
+import org.simantics.db.impl.ClusterTraitsBase;\r
+import org.simantics.db.impl.Modifier;\r
+import org.simantics.db.impl.ResourceImpl;\r
+import org.simantics.db.impl.graph.ReadGraphImpl;\r
+import org.simantics.db.procedure.AsyncContextMultiProcedure;\r
+import org.simantics.db.procedure.AsyncMultiProcedure;\r
+\r
+\r
+public final class ResourceElementSmall {\r
+ private static final boolean DEBUG = ClusterImpl.DEBUG;\r
+ // Descriptor = type & complete object reference & value index & predicate index. \r
+ private static final int DESCRIPTOR_OFFSET = 0; // descriptor\r
+ private static final int STM_OFFSET = 1; // two statements\r
+ private static final int SIZE_OF = 2;\r
+\r
+ static void construct(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ table[i++] = 0; // descriptor\r
+ table[i++] = 0; // stm1 & 2\r
+ }\r
+\r
+ static void destruct(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ table[i++] = 0; // descriptor\r
+ table[i++] = 0; // stm1 & 2\r
+ }\r
+\r
+ static boolean isUsed(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ if (table[i++] != 0)\r
+ return true;\r
+ if (table[i++] != 0)\r
+ return true;\r
+ return false;\r
+ }\r
+\r
+ static int getSizeOf() {\r
+ return SIZE_OF;\r
+ }\r
+\r
+ static ClusterI.CompleteTypeEnum getCompleteType(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ byte bits = (byte)BitUtility.getMiddle(table[i], 62, 2);\r
+ return ClusterI.CompleteTypeEnum.make(bits);\r
+ }\r
+\r
+ static void setCompleteType(long[] table, int index, byte data) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 62, 2, data);\r
+ }\r
+\r
+ static short getCompleteObjectRef(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ return (short)BitUtility.getMiddle(table[i], 46, 16);\r
+ }\r
+\r
+ static void setCompleteObjectRef(long[] table, int index, int ref) {\r
+ if (ref > (1<<16)-1)\r
+ throw new IllegalArgumentException();\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 46, 16, ref);\r
+ }\r
+\r
+ static boolean completeHasMultiple(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ int completeRefAndType= BitUtility.getMiddle(table[i], 46, 18); \r
+ boolean complete = (completeRefAndType >>> 16) != 0;\r
+ return !complete && (completeRefAndType != 0);\r
+ }\r
+\r
+ static boolean completeIsFirstStatement(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ int completeRefAndType = BitUtility.getMiddle(table[i], 46, 18); \r
+ return completeRefAndType == 0;\r
+ }\r
+ \r
+ static boolean completeIsSameStatement(long[] table, int index, int refAndType) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ int completeRefAndType = BitUtility.getMiddle(table[i], 46, 18); \r
+ return completeRefAndType == refAndType;\r
+ }\r
+ \r
+ static int completeGetRefAndType(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ return BitUtility.getMiddle(table[i], 46, 18);\r
+ }\r
+ \r
+ static void completeSetRefAndType(long[] table, int index, int refAndType) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 46, 18, refAndType); \r
+ }\r
+ \r
+ static int completeMakeObjectRefAndType(short oRef, ClusterI.CompleteTypeEnum completeType) {\r
+ return oRef & (1<<16)-1 | completeType.getValue()<<16;\r
+ }\r
+ \r
+ static short completeGetObjectSetIndex(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ return (short)BitUtility.getMiddle(table[i], 46, 16);\r
+ }\r
+ \r
+ static int completeGetStatementCountApproximation(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ int cType = BitUtility.getMiddle(table[i], 62, 2);\r
+ if (cType != 0)\r
+ return 1;\r
+ int cRef = BitUtility.getMiddle(table[i], 46, 16);\r
+ if (cRef != 0)\r
+ return 2; // Can be bigger, hence the approximation. \r
+ return 0;\r
+ }\r
+ \r
+ static int getValueIndex(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ int valueIndex = BitUtility.getMiddle(table[i], 24, 22);\r
+ return valueIndex;\r
+ }\r
+\r
+ static void setValueIndex(long[] table, int index, int valueIndex) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 24, 22, valueIndex);\r
+ }\r
+\r
+ static int getPredicateIndex(long[] table, int index) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ int predicateIndex = BitUtility.getMiddle(table[i], 0, 24);\r
+ return predicateIndex;\r
+ }\r
+\r
+ static void setPredicateIndex(long[] table, int index, int predicateIndex) {\r
+ int i = DESCRIPTOR_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 0, 24, predicateIndex);\r
+ }\r
+\r
+ static short getStm1Predicate(long[] table, int index) {\r
+ int i = STM_OFFSET + index;\r
+ short predicateIndex = BitUtility.getLowShort(table[i]);\r
+ return predicateIndex;\r
+ }\r
+\r
+ static void setStm1Predicate(long[] table, int index, short predicateIndex) {\r
+ int i = STM_OFFSET + index;\r
+ table[i] = BitUtility.setLowShort(table[i], predicateIndex);\r
+ }\r
+ \r
+ static short getStm1Object(long[] table, int index) {\r
+ int i = STM_OFFSET + index;\r
+ short objectIndex = (short)BitUtility.getMiddle(table[i], 16, 16);\r
+ return objectIndex;\r
+ }\r
+\r
+ static void setStm1Object(long[] table, int index, short objectIndex) {\r
+ int i = STM_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 16, 16, objectIndex);\r
+ }\r
+ \r
+ static short getStm2Predicate(long[] table, int index) {\r
+ int i = STM_OFFSET + index;\r
+ short predicateIndex = (short)BitUtility.getMiddle(table[i], 32, 16);\r
+ return predicateIndex;\r
+ }\r
+\r
+ static void setStm2Predicate(long[] table, int index, short predicateIndex) {\r
+ int i = STM_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 32, 16, predicateIndex);\r
+ }\r
+\r
+ static short getStm2Object(long[] table, int index) {\r
+ int i = STM_OFFSET + index;\r
+ short objectIndex = (short)BitUtility.getMiddle(table[i], 48, 16);\r
+ return objectIndex;\r
+ }\r
+\r
+ static void setStm2Object(long[] table, int index, short objectIndex) {\r
+ int i = STM_OFFSET + index;\r
+ table[i] = BitUtility.setMiddle(table[i], 48, 16, objectIndex);\r
+ }\r
+\r
+ public static byte[] getValue(ValueTableSmall valueTable, long[] table, int index)\r
+ throws DatabaseException {\r
+ int valueIndex = getValueIndex(table, index);\r
+ if (0 == valueIndex)\r
+ return null; // no value\r
+ else if (ClusterTraitsSmall.VALUE_INDEX_EX == valueIndex)\r
+ throw new ExternalValueException("Value stored externally. index=" + index);\r
+ return valueTable.getValue(valueIndex);\r
+ }\r
+//KRAA:\r
+// static char[] getString(ValueTableSmall valueTable, long[] table, int index) {\r
+// int valueIndex = getValueIndex(table, index);\r
+// if (0 == valueIndex)\r
+// return null; // no value\r
+//// else if (ClusterTraitsSmall.VALUE_INDEX_MAX == valueIndex)\r
+//// throw new Error("Not implemented! //KRAA:");\r
+// return valueTable.getString(valueIndex);\r
+// }\r
+\r
+ static boolean hasValue(long[] table, int index) {\r
+ int valueIndex = getValueIndex(table, index);\r
+ return 0 != valueIndex;\r
+ }\r
+\r
+// static boolean hasValue(ValueTable valueTable, long[] table, int index, byte[] value) {\r
+// int valueIndex = getValueIndex(table, index);\r
+// if (0 == valueIndex)\r
+// return false;\r
+// return valueTable.isEqual(valueIndex, value, 0, value.length);\r
+// }\r
+\r
+ static boolean removeValue(ValueTableSmall valueTable, long[] table, int index) {\r
+ int valueIndex = getValueIndex(table, index);\r
+ if (0 == valueIndex)\r
+ return false; // not removed\r
+ else if (ClusterTraitsSmall.VALUE_INDEX_EX != valueIndex)\r
+ valueTable.removeValue(valueIndex);\r
+ setValueIndex(table, index, 0);\r
+ return true;\r
+ }\r
+\r
+ public static void setValue(ValueTableSmall valueTable, long[] table, int index, byte[] value, int length)\r
+ throws OutOfSpaceException {\r
+ int oldIndex = getValueIndex(table, index);\r
+ if (ClusterTraitsSmall.VALUE_INDEX_EX == oldIndex)\r
+ oldIndex = 0;\r
+ if (length > ClusterTraitsSmall.VALUE_SIZE_MAX)\r
+ throw new OutOfSpaceException("Out of space for value. size=" + length);\r
+ int newIndex = valueTable.setValue(oldIndex, value, 0, length);\r
+ if (newIndex != oldIndex) {\r
+ if (newIndex > ClusterTraitsSmall.VALUE_INDEX_MAX) {\r
+ setValueIndex(table, index, 0);\r
+ throw new OutOfSpaceException("Out of space for values. index=" + newIndex);\r
+ }\r
+ setValueIndex(table, index, newIndex);\r
+ }\r
+ return;\r
+ }\r
+\r
+ public static boolean isValueEx(ValueTableSmall valueTable, long[] table, int index) {\r
+ int vIndex = getValueIndex(table, index);\r
+ if (ClusterTraitsSmall.VALUE_INDEX_EX == vIndex)\r
+ return true;\r
+ else\r
+ return false;\r
+ }\r
+\r
+ public static void setValueEx(ValueTableSmall valueTable, long[] table, int index) {\r
+ setValueIndex(table, index, ClusterTraitsSmall.VALUE_INDEX_EX);\r
+ }\r
+\r
+ public static <Context> boolean foreachPredicate(long[] table, int index,\r
+ ClusterI.PredicateProcedure<Context> procedure,\r
+ Context context, ClusterSupport support, Modifier modifier,\r
+ CompleteTable ct)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: 1");\r
+ int completeRef = ResourceElementSmall.getCompleteObjectRef(table, index);\r
+ if (0 != completeRef) {\r
+ if (ResourceElementSmall.completeHasMultiple(table, index)) { // multiple complete objects\r
+ // CompleteRef is a complete object set index.\r
+ boolean broken = ct.foreachPredicate(completeRef, procedure, context, support, modifier);\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: multi-complete ci=" + completeRef + " break=" + broken);\r
+ if (broken)\r
+ return true; // loop broken by procedure\r
+ } else { // We have zero or one complete statement.\r
+ ClusterI.CompleteTypeEnum completeType = ResourceElementSmall.getCompleteType(table, index);\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != completeType) {\r
+ int key = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType);\r
+ boolean broken = procedure.execute(context, key, 0);\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: complete rk=" + key + " break=" + broken);\r
+ if (broken)\r
+ return true; // loop broken by procedure\r
+ }\r
+ }\r
+ }\r
+ // If predicate set is in use it will contain also these statements.\r
+ if (0 != ResourceElementSmall.getPredicateIndex(table, index)) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: more than 2 objects");\r
+ return false;\r
+ }\r
+ int p1 = getStm1Predicate(table, index);\r
+ if (0 == p1) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: empty cache");\r
+ return false; // loop finished, no statements\r
+ }\r
+ int externalRef;\r
+ if (null == modifier)\r
+ externalRef = p1;\r
+ else\r
+ externalRef = modifier.execute(p1);\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: cache1 pk=" + externalRef);\r
+ if (procedure.execute(context, externalRef, 0))\r
+ return true; // loop broken by procedure\r
+ int p2 = getStm2Predicate(table, index);\r
+ if (0 == p2 || p1 == p2) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: cache2 empty");\r
+ return false; // loop finished, one predicate\r
+ }\r
+ if (null == modifier)\r
+ externalRef = p2;\r
+ else\r
+ externalRef = modifier.execute(p2);\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachPredicate: cache2 pk=" + externalRef);\r
+ return procedure.execute(context, externalRef, 0);\r
+ }\r
+\r
+ public static int getSingleObject(long[] table, int index, ClusterSupport support, final short pRef,\r
+ final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.getSingleObject: index=" + index);\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
+ int completeRef = getCompleteObjectRef(table, index);\r
+ if (0 == completeRef)\r
+ return 0; // no objects for given complete type\r
+ if (ResourceElementSmall.completeHasMultiple(table, index)) {\r
+ // Multiple complete type statements.\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.was complete 2");\r
+ ClusterI.ObjectProcedure<Short> proc = new ClusterI.ObjectProcedure<Short>() {\r
+ @Override\r
+ public boolean execute(Short context, int completeRefAndType)\r
+ throws DatabaseException {\r
+ ClusterI.CompleteTypeEnum ct = ClusterTraitsSmall.completeRefAndTypeGetType(completeRefAndType);\r
+ if (ct == pCompleteType) { // we have a match\r
+ if (context != 0) { // we have an old match\r
+ context = 0; // multiple objects for given type\r
+ return true; // break loop\r
+ }\r
+ context = ClusterTraitsSmall.completeRefAndTypeGetRef(completeRefAndType);\r
+ }\r
+ return true; // continue looping\r
+ }\r
+ };\r
+ Short objectRef = 0;\r
+ // CompleteRef is complete object set index.\r
+ ct.foreachComplete(completeRef, proc, objectRef, support, modifier);\r
+ return modifier.execute(objectRef);\r
+ } // One complete type statement.\r
+ ClusterI.CompleteTypeEnum rCompleteType = ResourceElementSmall.getCompleteType(table, index);\r
+ if (pCompleteType != rCompleteType)\r
+ return 0; // no objects for given complete type\r
+ // CompleteRef is object resource reference.\r
+ return modifier.execute(completeRef);\r
+ }\r
+ int p1 = getStm1Predicate(table, index);\r
+ if (0 == p1)\r
+ return 0; // loop finished, no statements\r
+ int result = 0;\r
+ if (pRef == p1) {\r
+ short o1 = getStm1Object(table, index);\r
+ result = modifier.execute(o1);\r
+// procedure.execute(graph, new ResourceImpl(null, modifier.execute(o1)));\r
+// int externalRef;\r
+// if (null == modifier)\r
+// externalRef = o1;\r
+// else\r
+// externalRef = modifier.execute(callerThread, o1);\r
+// if (procedure.execute(callerThread, context, externalRef))\r
+// return true; // loop broken by procedure\r
+ }\r
+ int p2 = getStm2Predicate(table, index);\r
+ if (0 == p2 || pRef != p2)\r
+ return result; // loop finished, one statements\r
+\r
+ // Many statements\r
+ if (result != 0) return -1;\r
+ \r
+ short o2 = getStm2Object(table, index);\r
+ return modifier.execute(o2);\r
+// int externalRef;\r
+// if (null == modifier)\r
+// externalRef = o2;\r
+// else\r
+// externalRef = modifier.execute(callerThread, o2);\r
+// if (procedure.execute(callerThread, context, externalRef))\r
+// return true; // loop broken by procedure\r
+// return false; // loop finished\r
+// procedure.execute(graph, new ResourceImpl(null, modifier.execute(o2)));\r
+ }\r
+\r
+ public static void foreachObject(long[] table, int index,\r
+ final ReadGraphImpl graph, final AsyncMultiProcedure<Resource> procedure,\r
+ ClusterSupport support, final int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachObject1: index=" + index);\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
+ int completeRef = getCompleteObjectRef(table, index);\r
+ if (0 == completeRef) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // no objects for given complete type\r
+ }\r
+ if (ResourceElementSmall.completeHasMultiple(table, index)) {// multiple objects\r
+ ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {\r
+ @Override\r
+ public boolean execute(Object _context, int objectRef)\r
+ throws DatabaseException {\r
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(objectRef)));\r
+ return false; // continue looping\r
+ }\r
+ \r
+ };\r
+ // CompleteRef is complete object set index.\r
+ ct.foreachComplete(completeRef, proc, null, support, modifier);\r
+ } else { // One complete type element. CompleteRef is resource reference.\r
+ ClusterI.CompleteTypeEnum rCompleteType = ResourceElementSmall.getCompleteType(table, index);\r
+ if (pCompleteType != rCompleteType) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // Complete predicate does not match.\r
+ }\r
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(completeRef)));\r
+ }\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // loop finished\r
+ }\r
+ short p1 = getStm1Predicate(table, index);\r
+ if (0 == p1) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // loop finished, no statements\r
+ }\r
+ if (pRef == p1) {\r
+ short o1 = getStm1Object(table, index);\r
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1)));\r
+// int externalRef;\r
+// if (null == modifier)\r
+// externalRef = o1;\r
+// else\r
+// externalRef = modifier.execute(callerThread, o1);\r
+// if (procedure.execute(callerThread, context, externalRef))\r
+// return true; // loop broken by procedure\r
+ }\r
+ short p2 = getStm2Predicate(table, index);\r
+ if (0 == p2 || pRef != p2) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // loop finished, one statements\r
+ }\r
+ int o2 = getStm2Object(table, index);\r
+// int externalRef;\r
+// if (null == modifier)\r
+// externalRef = o2;\r
+// else\r
+// externalRef = modifier.execute(callerThread, o2);\r
+// if (procedure.execute(callerThread, context, externalRef))\r
+// return true; // loop broken by procedure\r
+// return false; // loop finished\r
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2)));\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ }\r
+ \r
+ public static <C> void foreachObject(long[] table, int index,\r
+ final ReadGraphImpl graph, final C context, final AsyncContextMultiProcedure<C, Resource> procedure,\r
+ ClusterSupport support, final int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElement.foreachObject1: index=" + index);\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
+ int completeRef = getCompleteObjectRef(table, index);\r
+ if (0 == completeRef) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // no objects for given complete type\r
+ }\r
+ if (ResourceElementSmall.completeHasMultiple(table, index)) {// multiple objects\r
+ ClusterI.ObjectProcedure<Object> proc = new ClusterI.ObjectProcedure<Object>() {\r
+ @Override\r
+ public boolean execute(Object _context, int objectRef)\r
+ throws DatabaseException {\r
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(objectRef)));\r
+ return false; // continue looping\r
+ }\r
+ \r
+ };\r
+ // CompleteRef is complete object set index.\r
+ ct.foreachComplete(completeRef, proc, null, support, modifier);\r
+ } else { // One complete type element. CompleteRef is resource reference.\r
+ ClusterI.CompleteTypeEnum rCompleteType = ResourceElementSmall.getCompleteType(table, index);\r
+ if (pCompleteType != rCompleteType) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // Complete predicate does not match.\r
+ }\r
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(completeRef)));\r
+ }\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // loop finished\r
+ }\r
+ short p1 = getStm1Predicate(table, index);\r
+ if (0 == p1) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // loop finished, no statements\r
+ }\r
+ if (pRef == p1) {\r
+ short o1 = getStm1Object(table, index);\r
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1)));\r
+// int externalRef;\r
+// if (null == modifier)\r
+// externalRef = o1;\r
+// else\r
+// externalRef = modifier.execute(callerThread, o1);\r
+// if (procedure.execute(callerThread, context, externalRef))\r
+// return true; // loop broken by procedure\r
+ }\r
+ short p2 = getStm2Predicate(table, index);\r
+ if (0 == p2 || pRef != p2) {\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ return; // loop finished, one statements\r
+ }\r
+ int o2 = getStm2Object(table, index);\r
+// int externalRef;\r
+// if (null == modifier)\r
+// externalRef = o2;\r
+// else\r
+// externalRef = modifier.execute(callerThread, o2);\r
+// if (procedure.execute(callerThread, context, externalRef))\r
+// return true; // loop broken by procedure\r
+// return false; // loop finished\r
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2)));\r
+ procedure.finished(graph);\r
+// graph.state.dec(0);\r
+ }\r
+\r
+ public static <Context> boolean foreachObject(long[] table, int index\r
+ , ClusterI.ObjectProcedure<Context> procedure\r
+ , Context context, ClusterSupport support, Modifier modifier\r
+ , final short pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: 1");\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
+ int completeRef = getCompleteObjectRef(table, index);\r
+ if (0 == completeRef) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: no complete");\r
+ return false; // no objects for given complete type\r
+ } if (ResourceElementSmall.completeHasMultiple(table, index)) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: multi-complete ci=" + completeRef);\r
+ // CompleteRef is complete object set index.\r
+ return ct.foreachObject(completeRef, procedure, context, support, modifier, pCompleteType);\r
+ }\r
+ // One complete type statement at most.\r
+ ClusterI.CompleteTypeEnum completeType = ResourceElementSmall.getCompleteType(table, index);\r
+ if (pCompleteType != completeType) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: complete different predicate");\r
+ return false; // Loop finished. No objects for given complete predicate type.\r
+ }\r
+ int externalRef = completeRef;\r
+ if (null != modifier)\r
+ externalRef = modifier.execute(externalRef);\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: complete ok=" + externalRef);\r
+ return procedure.execute(context, externalRef);\r
+ }\r
+ int p1 = getStm1Predicate(table, index);\r
+ if (0 == p1) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: empty cache=");\r
+ return false; // loop finished, no statements\r
+ }\r
+ if (pRef == p1) {\r
+ int o1 = getStm1Object(table, index);\r
+ int externalRef;\r
+ if (null == modifier)\r
+ externalRef = o1;\r
+ else\r
+ externalRef = modifier.execute(o1);\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: cache1 ok=" + externalRef);\r
+ if (procedure.execute(context, externalRef))\r
+ return true; // loop broken by procedure\r
+ }\r
+ int p2 = getStm2Predicate(table, index);\r
+ if (0 == p2 || pRef != p2) {\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: not in cache1");\r
+ return false; // loop finished, one statements\r
+ }\r
+ int o2 = getStm2Object(table, index);\r
+ int externalRef;\r
+ if (null == modifier)\r
+ externalRef = o2;\r
+ else\r
+ externalRef = modifier.execute(o2);\r
+ if (DEBUG)\r
+ System.out.println("ResourceElementSmall.foreachObject2: cache2 ok=" + externalRef);\r
+ return procedure.execute(context, externalRef);\r
+ }\r
+ static boolean isEmpty(long[] table, int index) {\r
+ return getStatementCountApproximation(table, index) == 0 && !hasValue(table, index);\r
+ }\r
+ static int getStatementCountApproximation(long[] table, int index) {\r
+ int n = ResourceElementSmall.completeGetStatementCountApproximation(table, index);\r
+ short p1 = getStm1Predicate(table, index);\r
+ if (0 == p1)\r
+ return n;\r
+ short p2 = getStm2Predicate(table, index);\r
+ if (0 == p2)\r
+ return n+1;\r
+ int predicateIndex = getPredicateIndex(table, index);\r
+ if (0 == predicateIndex)\r
+ return n + 2;\r
+ return n + 3; // Can be bigger, hence the approximation.\r
+ }\r
+ static int addStatement(long[] table, int index, short pRef, short oRef\r
+ , PredicateTable pt, ObjectTable ot\r
+ , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
+ throws DatabaseException {\r
+ assert (0 != pRef);\r
+ assert (0 != oRef);\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != completeType) { // predicate is complete type\r
+ int coRefAndType = completeMakeObjectRefAndType(oRef, completeType);\r
+ if (completeIsFirstStatement(table, index))\r
+ completeSetRefAndType(table, index, coRefAndType);\r
+ else { // old complete statements exist\r
+ if (completeIsSameStatement(table, index, coRefAndType))\r
+ return -1; // old complete\r
+ int nRef;\r
+ if (completeHasMultiple(table, index)) { // nth statement\r
+ int coSetIndex = completeGetObjectSetIndex(table, index) & 0xFFFF;\r
+ nRef = ct.addComplete(coSetIndex, coRefAndType);\r
+ if (0 == nRef)\r
+ return -1; // old complete\r
+ else if (nRef >= 1<<16) {\r
+ ct.removeComplete(coSetIndex, coRefAndType);\r
+ throw new OutOfSpaceException("Out of space for complete objects. index=" + nRef);\r
+ }\r
+ } else { // second statement\r
+ int coRefAndTypeOld = ResourceElementSmall.completeGetRefAndType(table, index);\r
+ nRef = ct.createCompleteArraySet(coRefAndTypeOld, coRefAndType);\r
+ if (nRef >= 1<<16)\r
+ throw new OutOfSpaceException("Out of space for complete objects. index=" + nRef);\r
+ ResourceElementSmall.setCompleteType(table, index, (byte)0);\r
+ }\r
+ setCompleteObjectRef(table, index, nRef);\r
+ }\r
+ return 0; // added to complete\r
+ }\r
+ short p1 = getStm1Predicate(table, index);\r
+ short o1 = getStm1Object(table, index);\r
+ if (0 == p1) {\r
+ setStm1Predicate(table, index, pRef);\r
+ setStm1Object(table, index, oRef);\r
+ return 0; // added to stm cache\r
+ } else if (p1 == pRef && o1 == oRef)\r
+ return -1; // same statement\r
+ short p2 = getStm2Predicate(table, index);\r
+ short o2 = getStm2Object(table, index);\r
+ if (0 == p2) {\r
+ setStm2Predicate(table, index, pRef);\r
+ setStm2Object(table, index, oRef);\r
+ return 0; // added to stm cache\r
+ } else if (p2 == pRef && o2 == oRef)\r
+ return -1; // same statement\r
+ int predicateIndex = getPredicateIndex(table, index);\r
+ if (0 == predicateIndex) {\r
+ if (p1 == p2) {\r
+ int objectIndex = ot.createObjectSet(o1 & 0xFFFF, o2 & 0xFFFF);\r
+ assert (0 != objectIndex);\r
+ int[] os = new int[1];\r
+ os[0] = ClusterTraits.statementIndexMake(objectIndex);\r
+ int[] ps = new int[1];\r
+ ps[0] = p1 & 0xFFFF;\r
+ predicateIndex = pt.createPredicateSet(ps, os);\r
+ } else {\r
+ int[] os = new int[2];\r
+ os[0] = o1 & 0xFFFF; \r
+ os[1] = o2 & 0xFFFF;\r
+ int[] ps = new int[2];\r
+ ps[0] = p1 & 0xFFFF;\r
+ ps[1] = p2 & 0xFFFF;\r
+ predicateIndex = pt.createPredicateSet(ps, os);\r
+ }\r
+ assert (0 != predicateIndex);\r
+ setPredicateIndex(table, index, predicateIndex);\r
+ }\r
+ assert (0 != predicateIndex);\r
+ return predicateIndex;\r
+ }\r
+\r
+ static boolean removeStatement(long[] table, int index, short pRef, short oRef,\r
+ ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
+ throws DatabaseException {\r
+ assert (0 != pRef);\r
+ assert (0 != oRef);\r
+ if (completeType != ClusterI.CompleteTypeEnum.NotComplete) {\r
+ int completeRef = ResourceElementSmall.getCompleteObjectRef(table, index);\r
+ if (0 == completeRef)\r
+ return false; // Statement not removed because it doesn't exist.\r
+ int refAndType = ResourceElementSmall.completeMakeObjectRefAndType(oRef, completeType);\r
+ if (ResourceElementSmall.completeIsSameStatement(table, index, refAndType)) {\r
+ ResourceElementSmall.completeSetRefAndType(table, index, 0);\r
+ return true; // statement removed\r
+ } else if (ResourceElementSmall.completeHasMultiple(table, index)) {\r
+ // CompleteRef is index to complete table.\r
+ int oldSize = ct.getCompleteSetSize(completeRef);\r
+ int newSize = ct.removeComplete(completeRef, refAndType);\r
+ if (oldSize == newSize)\r
+ return false; // not removed\r
+ else if (newSize == 1) {\r
+ int cRef = ct.removeLast(completeRef);\r
+ ResourceElementSmall.completeSetRefAndType(table, index, cRef);\r
+ }\r
+ return true; \r
+ }\r
+ return false; // Statement not removed because it doesn't exist.\r
+ }\r
+ short p1 = getStm1Predicate(table, index);\r
+ short o1 = getStm1Object(table, index);\r
+ if (0 == p1)\r
+ return false; // no statements cached\r
+ short p2 = getStm2Predicate(table, index);\r
+ short o2 = getStm2Object(table, index);\r
+ if (p1 == pRef && o1 == oRef) {\r
+ setStm1Predicate(table, index, p2);\r
+ setStm1Object(table, index, o2);\r
+ setStm2Predicate(table, index, (short)0);\r
+ setStm2Object(table, index, (short)0);\r
+ return true; // statement removed\r
+ }\r
+ if (0 == p2)\r
+ return false; // no match\r
+ else if (p2 == pRef && o2 == oRef) {\r
+ setStm2Predicate(table, index, (short)0);\r
+ setStm2Object(table, index, (short)0);\r
+ return true; // statement removed\r
+ }\r
+ return false;\r
+ }\r
+}\r