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