-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.db.procore.cluster;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.ExternalValueException;\r
-import org.simantics.db.exception.ValidationException;\r
-import org.simantics.db.impl.ClusterBase;\r
-import org.simantics.db.impl.ClusterI;\r
-import org.simantics.db.impl.ClusterI.CompleteTypeEnum;\r
-import org.simantics.db.impl.ClusterI.ObjectProcedure;\r
-import org.simantics.db.impl.ClusterI.PredicateProcedure;\r
-import org.simantics.db.impl.ClusterI.Procedure;\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.Table;\r
-import org.simantics.db.impl.TableFactory;\r
-import org.simantics.db.impl.TableSizeListener;\r
-import org.simantics.db.impl.graph.ReadGraphImpl;\r
-import org.simantics.db.procedure.AsyncContextMultiProcedure;\r
-import org.simantics.db.procedure.AsyncMultiProcedure;\r
-import org.simantics.db.procore.cluster.PredicateTable.Status;\r
-\r
-\r
-final class ResourceElement {\r
- private static final boolean DEBUG = ClusterImpl.DEBUG;\r
- private static final int DESCRIPTOR_OFFSET = 0; // predicate descriptor\r
- private static final int VALUE_OFFSET = 1; // value descriptor\r
- private static final int STM_OFFSET = 2; // first statement\r
- private static final int SIZE_OF = 4;\r
-\r
- static void construct(long[] table, int index) {\r
- int i = DESCRIPTOR_OFFSET + index;\r
- table[i++] = 0; // predicate capacity & index\r
- table[i++] = 0; // value capacity & index\r
- table[i++] = 0; // stm1\r
- table[i++] = 0; // stm2\r
- }\r
-\r
- static void destruct(long[] table, int index) {\r
- int i = DESCRIPTOR_OFFSET + index;\r
- table[i++] = 0; // predicate capacity & index\r
- table[i++] = 0; // value capacity & index\r
- table[i++] = 0; // stm1\r
- table[i++] = 0; // stm2\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
- 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 int getCompleteObjectRef(long[] table, int index) {\r
- int i = DESCRIPTOR_OFFSET + index;\r
- return BitUtility.getHighInt(table[i]);\r
- }\r
-\r
- static void setCompleteObjectRef(long[] table, int index, int ref) {\r
- int i = DESCRIPTOR_OFFSET + index;\r
- table[i] = BitUtility.setHighInt(table[i], ref);\r
- }\r
-\r
- static int getPredicateIndex(long[] table, int index) {\r
- int i = DESCRIPTOR_OFFSET + index;\r
- int predicateIndex = BitUtility.getLowInt(table[i]);\r
- assert (predicateIndex >= 0);\r
- return predicateIndex;\r
- }\r
-\r
- static void setPredicateIndex(long[] table, int index, int predicateIndex) {\r
- assert (predicateIndex >= 0);\r
- int i = DESCRIPTOR_OFFSET + index;\r
- table[i] = BitUtility.setLowInt(table[i], predicateIndex);\r
- }\r
-\r
- static int copyValue(ValueTable valueTable, long[] table, int index, byte[] byteTable, int byteSize, int byteBase,\r
- int byteCurrent) {\r
- int i = VALUE_OFFSET + index;\r
- if (0 == table[i] || -1 == table[i])\r
- return byteCurrent; // no value or external value\r
- // getValueCapacity call optimized away\r
- int capacity = BitUtility.getLowInt(table[i]);\r
- int valueIndex = getValueIndex(table, index);\r
- if (0 == valueIndex)\r
- return byteCurrent;\r
- valueTable.getValue(valueIndex, byteTable, byteCurrent, capacity);\r
- valueIndex = byteCurrent - byteBase;\r
- setValueIndex(table, index, valueIndex);\r
- byteCurrent += capacity;\r
- return byteCurrent;\r
- }\r
-\r
- static byte[] getValue(ValueTable valueTable, long[] table, int index)\r
- throws DatabaseException {\r
- int i = VALUE_OFFSET + index;\r
- if (0 == table[i])\r
- return null; // no value\r
- if (-1 == table[i])\r
- throw new ExternalValueException("Value stored externally.");\r
- // getValueCapacity call optimized away\r
- int capacity = BitUtility.getLowInt(table[i]);\r
- byte[] t = new byte[capacity];\r
- int valueIndex = getValueIndex(table, index);\r
- valueTable.getValue(valueIndex, t, 0, capacity);\r
- return t;\r
- }\r
-\r
-// static int getString(ValueTable valueTable, long[] table, int index, char[] t)\r
-// throws DatabaseException {\r
-// long l = table[index + VALUE_OFFSET];\r
-// if (-1 == l)\r
-// throw new ExternalValueException("String stored externally.");\r
-// int capacity = (int)l;\r
-// int valueIndex = (int) (l >>> 32);\r
-//// char[] t = new char[capacity-1];\r
-// valueTable.getString(valueIndex, t, 0, capacity-1);\r
-// return capacity-1;\r
-// \r
-// }\r
-\r
- static boolean hasValue(long[] table, int index) {\r
- int i = VALUE_OFFSET + index;\r
- return 0 != table[i];\r
- }\r
-//KRAA:\r
-// static boolean hasValue(ValueTable valueTable, long[] table, int index, byte[] value) {\r
-// int i = VALUE_OFFSET + index;\r
-// if (0 == table[i])\r
-// return false;\r
-// // getValueCapacity call optimized away\r
-// int capacity = BitUtility.getLowInt(table[i]);\r
-// if (capacity != value.length)\r
-// return false;\r
-// int valueIndex = getValueIndex(table, index);\r
-// return valueTable.isEqual(valueIndex, value);\r
-// }\r
-\r
- static boolean removeValue(ValueTable valueTable, long[] table, int index) {\r
- int i = VALUE_OFFSET + index;\r
- if (0 == table[i])\r
- return false;\r
- else if (-1 != table[i]) {\r
- // getValueCapacity call optimized away\r
- int capacity = BitUtility.getLowInt(table[i]);\r
- int valueIndex = getValueIndex(table, index);\r
- valueTable.removeValue(valueIndex, capacity);\r
- }\r
- //setValueCapacityAndIndex(table, index, 0, 0); optimized away\r
- table[i] = 0;\r
- return true;\r
- }\r
-\r
- public static void setValue(ValueTable valueTable, long[] table, int index, byte[] value, int length) {\r
- int i = VALUE_OFFSET + index;\r
- // getValueCapacity call optimized away\r
- int capacity = BitUtility.getLowInt(table[i]); \r
- int valueIndex = getValueIndex(table, index);\r
- if (length <= capacity) {\r
- valueTable.setValue(valueIndex, value, length);\r
- // we "leak" memory TODO: add value size member to\r
- // resource entry or value entry\r
- setValueCapacity(table, index, length);\r
- } else {\r
- if (valueIndex != 0 && capacity > 0)\r
- valueTable.removeValue(valueIndex, capacity);\r
- valueIndex = valueTable.createValue(value, 0, length);\r
- capacity = length;\r
- setValueCapacityAndIndex(table, index, capacity, valueIndex);\r
- }\r
- return;\r
- }\r
- public static boolean isValueEx(ValueTable valueTable, long[] table, int index) {\r
- int i = VALUE_OFFSET + index;\r
- if (-1 == table[i])\r
- return true;\r
- else\r
- return false;\r
- }\r
- public static void setValueEx(ValueTable valueTable, long[] table, int index) {\r
- int i = VALUE_OFFSET + index;\r
- if (-1 == table[i])\r
- return;\r
- else if (0 != table[i]) {\r
- int capacity = BitUtility.getLowInt(table[i]);\r
- int valueIndex = getValueIndex(table, index);\r
- valueTable.removeValue(valueIndex, capacity);\r
- }\r
- //setValueCapacityAndIndex(table, index, 0, 0); optimized away\r
- table[i] = -1;\r
- }\r
- static class ValueData {\r
- int capacity;\r
- int index;\r
-// ValueData(int capacity, int index) {\r
-// this.capacity = capacity;\r
-// this.index = index;\r
-// }\r
- }\r
- static void getValueCapacityAndIndex(ValueData vd, long[] table, int index) {\r
- int i = VALUE_OFFSET + index;\r
- // getValueCapacity call optimized away\r
- vd.capacity = BitUtility.getLowInt(table[i]); \r
- vd.index = getValueIndex(table, index);\r
- \r
- }\r
- private static int getValueIndex(long[] table, int index) {\r
- int i = VALUE_OFFSET + index;\r
- return BitUtility.getHighInt(table[i]);\r
- }\r
-\r
- private static void setValueIndex(long[] table, int index, int valueIndex) {\r
- int i = VALUE_OFFSET + index;\r
- table[i] = BitUtility.setHighInt(table[i], valueIndex);\r
- }\r
-\r
- private static void setValueCapacity(long[] table, int index, int capacity) {\r
- int i = VALUE_OFFSET + index;\r
- table[i] = BitUtility.setLowInt(table[i], capacity);\r
- }\r
-\r
- private static void setValueCapacityAndIndex(long[] table, int index, int capacity, int valueIndex) {\r
- int i = VALUE_OFFSET + index;\r
- table[i] = BitUtility.setLowAndHighInt(table[i], capacity, valueIndex);\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 = ResourceElement.getCompleteObjectRef(table, index);\r
- if (0 != completeRef) {\r
- if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements\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 {\r
- ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);\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 != ResourceElement.getPredicateIndex(table, index)) {\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachPredicate: more than 2 objects");\r
- return false;\r
- }\r
- int i = STM_OFFSET + index;\r
- int p1 = BitUtility.getHighInt(table[i]);\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 = BitUtility.getHighInt(table[++i]);\r
- if (0 == p2 || p1 == p2) {\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachPredicate: cache2 empty");\r
- return false; // loop finished, one statement\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
- if (procedure.execute(context, externalRef, 0))\r
- return true; // loop broken by procedure\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachPredicate: not in cache");\r
- return false; // loop finished, two statements\r
- }\r
-\r
- public static int getSingleObject(long[] table, int index, ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final 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 (ClusterTraits.completeReferenceIsMultiple(completeRef)) {\r
- // Multiple complete type elements.\r
- if (DEBUG)\r
- System.out.println("ResourceElement.getSingleObject was complete 2");\r
- class ForeachObject\r
- implements ClusterI.ObjectProcedure<Integer> {\r
- @Override\r
- public boolean execute(Integer context, int completeRef)\r
- throws DatabaseException {\r
- ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (pCompleteType == oCompleteType) { // 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
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- context = modifier.execute(resourceIndex);\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- context = modifier.execute(externalRef);\r
- }\r
- }\r
- return true; // continue looping\r
- }\r
- \r
- }\r
- ForeachObject t = new ForeachObject();\r
- // CompleteRef is complete object set index.\r
- Integer c = 0;\r
- ct.foreachComplete(completeRef, t, c, support, modifier);\r
- return c;\r
- }\r
- // one complete type element\r
- ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (pCompleteType != completeType)\r
- return 0;\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- return modifier.execute(resourceIndex);\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- return modifier.execute(externalRef);\r
- }\r
- }\r
- int i = STM_OFFSET + index;\r
- int p1 = BitUtility.getHighInt(table[i]);\r
- if (0 == p1)\r
- return 0; // loop finished, no statements\r
- int result = 0;\r
- if (pRef == p1) {\r
- int o1 = BitUtility.getLowInt(table[i]);\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 = BitUtility.getHighInt(table[++i]);\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
- int o2 = BitUtility.getLowInt(table[i]);\r
- return modifier.execute(o2);\r
- \r
-// return 0;\r
-// int o2 = BitUtility.getLowInt(table[i]);\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
- final ClusterSupport support, final int pRef, final 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 (ClusterTraits.completeReferenceIsMultiple(completeRef)) {\r
- // Multiple complete type statements.\r
- if (DEBUG)\r
- System.out.println("ResourceElement.was complete 2");\r
- class ForeachObject implements ClusterI.ObjectProcedure<Object> {\r
- @Override\r
- public boolean execute(Object context, int completeRef) throws DatabaseException {\r
- ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (pCompleteType == oCompleteType) {\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));\r
- }\r
- }\r
- return false; // continue looping\r
- }\r
- \r
- }\r
- ForeachObject t = new ForeachObject();\r
- // CompleteRef is complete object set index.\r
- ct.foreachComplete(completeRef, t, null, support, modifier);\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return; // loop finished\r
- }\r
- // one complete type element\r
- ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (pCompleteType != completeType) {\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return;\r
- }\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));\r
- }\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return; // loop finished\r
- }\r
- int i = STM_OFFSET + index;\r
- long l = table[i];\r
- int p1 = (int) (l >>> 32);\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
- int o1 = (int)l;\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
- long l2 = table[++i];\r
- int p2 = (int) (l2 >>> 32);\r
- if (pRef != p2) {\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return; // loop finished, one statements\r
- }\r
- int o2 = (int)l2;\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
- final ClusterSupport support, final int pRef, final 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 (ClusterTraits.completeReferenceIsMultiple(completeRef)) {\r
- // Multiple complete type statements.\r
- if (DEBUG)\r
- System.out.println("ResourceElement.was complete 2");\r
- class ForeachObject implements ClusterI.ObjectProcedure<Object> {\r
- @Override\r
- public boolean execute(Object _context, int completeRef) throws DatabaseException {\r
- ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (pCompleteType == oCompleteType) {\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));\r
- }\r
- }\r
- return false; // continue looping\r
- }\r
- \r
- }\r
- ForeachObject t = new ForeachObject();\r
- // CompleteRef is complete object set index.\r
- ct.foreachComplete(completeRef, t, null, support, modifier);\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return; // loop finished\r
- }\r
- // one complete type element\r
- ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (pCompleteType != completeType) {\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return;\r
- }\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));\r
- }\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return; // loop finished\r
- }\r
- int i = STM_OFFSET + index;\r
- long l = table[i];\r
- int p1 = (int) (l >>> 32);\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
- int o1 = (int)l;\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
- long l2 = table[++i];\r
- int p2 = (int) (l2 >>> 32);\r
- if (pRef != p2) {\r
- procedure.finished(graph);\r
-// graph.state.dec(0);\r
- return; // loop finished, one statements\r
- }\r
- int o2 = (int)l2;\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 int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)\r
- throws DatabaseException {\r
- if (DEBUG)\r
- System.out.println("ResourceElement.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("ResourceElement.foreachObject2: no complete");\r
- return false; // no objects for given complete type\r
- }\r
- if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: multi-complete ci=" + completeRef);\r
- return ct.foreachObject(completeRef, procedure, context, support, modifier, pCompleteType);\r
- }\r
- // one complete type element\r
- ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (pCompleteType != completeType) {\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: complete different predicate");\r
- return false;\r
- }\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- int externalRef;\r
- if (null == modifier)\r
- externalRef = resourceIndex;\r
- else\r
- externalRef = modifier.execute(resourceIndex);\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef);\r
- if (procedure.execute(context, externalRef))\r
- return true; // loop broken by procedure\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- if (null != modifier)\r
- externalRef = modifier.execute(externalRef);\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef);\r
- if (procedure.execute(context, externalRef))\r
- return true; // loop broken by procedure\r
- }\r
- return false; // loop finished\r
- }\r
- int i = STM_OFFSET + index;\r
- int p1 = BitUtility.getHighInt(table[i]);\r
- if (0 == p1) {\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: empty cache=");\r
- return false; // loop finished, no statements\r
- }\r
- if (pRef == p1) {\r
- int o1 = BitUtility.getLowInt(table[i]);\r
- int externalRef;\r
- if (null == modifier)\r
- externalRef = o1;\r
- else\r
- externalRef = modifier.execute(o1);\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: cache1 ok=" + externalRef);\r
- if (procedure.execute(context, externalRef))\r
- return true; // loop broken by procedure\r
- }\r
- int p2 = BitUtility.getHighInt(table[++i]);\r
- if (0 == p2 || pRef != p2) {\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: not in cache1");\r
- return false; // loop finished, one statements\r
- }\r
- int o2 = BitUtility.getLowInt(table[i]);\r
- int externalRef;\r
- if (null == modifier)\r
- externalRef = o2;\r
- else\r
- externalRef = modifier.execute(o2);\r
- if (DEBUG)\r
- System.out.println("ResourceElement.foreachObject2: cache2 ok=" + externalRef);\r
- return procedure.execute(context, externalRef);\r
- }\r
- static boolean isEmpty(long[] table, int index) {\r
- return getStatementCount(table, index) == 0 && !hasValue(table, index);\r
- }\r
- static int getStatementCount(long[] table, int index) {\r
- int i = STM_OFFSET + index;\r
- int p1 = BitUtility.getHighInt(table[i]);\r
- int p2 = BitUtility.getLowInt(table[++i]);\r
- if (0 == p1)\r
- return 0;\r
- else if (0 == p2)\r
- return 1;\r
- int predicateIndex = getPredicateIndex(table, index);\r
- if (0 == predicateIndex)\r
- return 2;\r
- return 3;\r
- }\r
- private static int makeCompleteObjectRef(int oRef, ClusterI.CompleteTypeEnum completeType) {\r
- int ref;\r
- if (oRef > 0) {\r
- int resourceIndex = oRef; \r
- int clusterIndex = 0;\r
- ref = ClusterTraits.completeReferenceMake(completeType.getValue(), resourceIndex, clusterIndex);\r
- } else {\r
- assert(oRef < 0);\r
- assert(!ClusterTraits.isFlat(oRef));\r
- ref = (completeType.getValue() <<30) | (oRef & 0x3FFFFFFF);\r
- }\r
- return ref;\r
- }\r
- static int addStatement(long[] table, int index, int pRef, int 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) {\r
- int cRef = makeCompleteObjectRef(oRef, completeType);\r
- int ctr = getCompleteObjectRef(table, index);\r
- if (0 == ctr)\r
- setCompleteObjectRef(table, index, cRef);\r
- else {\r
- int nRef;\r
- if (ctr == cRef)\r
- return -1; // old complete\r
- else if (ClusterTraits.completeReferenceIsMultiple(ctr)) {\r
- nRef = ct.addComplete(ctr, cRef);\r
- if (0 == nRef)\r
- return -1; // old complete\r
- } else {\r
- nRef = ct.createCompleteArraySet(ctr, cRef);\r
- }\r
- setCompleteObjectRef(table, index, nRef);\r
- }\r
- return 0; // added to complete\r
- }\r
- int i = STM_OFFSET + index;\r
- int p1 = BitUtility.getHighInt(table[i]);\r
- int o1 = BitUtility.getLowInt(table[i]);\r
- if (0 == p1) {\r
- table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef);\r
- return 0; // added to stm cache\r
- } else if (p1 == pRef && o1 == oRef)\r
- return -1; // same statement\r
- int p2 = BitUtility.getHighInt(table[++i]);\r
- int o2 = BitUtility.getLowInt(table[i]);\r
- if (0 == p2) {\r
- table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef);\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, o2);\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;\r
- predicateIndex = pt.createPredicateSet(ps, os);\r
- } else {\r
- int[] os = new int[2];\r
- os[0] = o1; \r
- os[1] = o2;\r
- int[] ps = new int[2];\r
- ps[0] = p1;\r
- ps[1] = p2;\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, int pRef, int 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 = ResourceElement.getCompleteObjectRef(table, index);\r
- if (0 != completeRef) {\r
- ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (completeType == completeType2) {\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- if (oRef == resourceIndex) {\r
- ResourceElement.setCompleteObjectRef(table, index, 0);\r
- return true; // statement removed\r
- }\r
- } else {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- if (oRef == externalRef) {\r
- ResourceElement.setCompleteObjectRef(table, index, 0);\r
- return true; // statement removed\r
- }\r
- }\r
- } else if (completeType2 == ClusterI.CompleteTypeEnum.NotComplete) { // multiple complete type references \r
- int cRef = makeCompleteObjectRef(oRef, completeType);\r
- int oldSize = ct.getCompleteSetSize(completeRef);\r
- int newSize = ct.removeComplete(completeRef, cRef);\r
- if (oldSize == newSize)\r
- return false; // not removed\r
- else if (newSize == 1) {\r
- cRef = ct.removeLast(completeRef);\r
- ResourceElement.setCompleteObjectRef(table, index, cRef);\r
- }\r
- return true; \r
- }\r
- }\r
- }\r
- int i = STM_OFFSET + index;\r
- int p1 = BitUtility.getHighInt(table[i]);\r
- int o1 = BitUtility.getLowInt(table[i]);\r
- if (0 == p1)\r
- return false; // no statements cached\r
- else if (p1 == pRef && o1 == oRef) {\r
- table[i] = table[i + 1];\r
- // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away\r
- table[i + 1] = 0;\r
- return true; // statement removed\r
- }\r
- int p2 = BitUtility.getHighInt(table[++i]);\r
- int o2 = BitUtility.getLowInt(table[i]);\r
- if (0 == p2)\r
- return false; // no match\r
- else if (p2 == pRef && o2 == oRef) {\r
- // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away\r
- table[i] = 0;\r
- return true; // statement removed\r
- }\r
- return false;\r
- }\r
-}\r
-\r
-public final class ResourceTable extends Table<long[]> {\r
- public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase) {\r
- super(TableFactory.getLongFactory(), sizeListener, header, headerBase);\r
- }\r
-\r
- public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {\r
- super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);\r
- }\r
-\r
- public int getUsedSize() {\r
- return getTableCount();\r
- }\r
-\r
- public short createResource() {\r
- final int INDEX = getTableCount();\r
- final int SIZE = ResourceElement.getSizeOf();\r
- int resourceIndex = createNewElement(SIZE);\r
- assert (0 != resourceIndex);\r
- final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);\r
- ResourceElement.construct(getTable(), REAL_INDEX);\r
- incResourceCount();\r
- return (short)(INDEX + ZERO_SHIFT);\r
- }\r
-\r
- void createResource(int resourceIndex) {\r
- final int tableCount = getTableCount();\r
- if (resourceIndex <= tableCount) { // old index\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- if (ResourceElement.isEmpty(getTable(), realIndex))\r
- return;\r
- } if (resourceIndex == tableCount+1) {\r
- createResource();\r
- return;\r
- }\r
- throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);\r
- }\r
-\r
-// void deleteResource(int resourceIndex) {\r
-// int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-// ResourceElement.destruct(getTable(), realIndex);\r
-// decResourceCount();\r
-// }\r
-\r
- public int getCompleteObjectRef(int resourceIndex) {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- return ResourceElement.getCompleteObjectRef(getTable(), realIndex);\r
- }\r
- \r
- public int getPredicateIndex(int resourceIndex) {\r
- int i = (resourceIndex<<2) - 3 + offset;\r
- return (int)table[i];\r
- }\r
-\r
- public void setPredicateIndex(int resourceIndex, int predicateIndex) {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- ResourceElement.setPredicateIndex(getTable(), realIndex, predicateIndex);\r
- }\r
-\r
- public byte[] getValue(ValueTable valueTable, int resourceIndex)\r
- throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- return ResourceElement.getValue(valueTable, getTable(), realIndex);\r
- }\r
-\r
-//KRAA:\r
-// int getString(ValueTable valueTable, int resourceIndex, char[] chars)\r
-// throws DatabaseException {\r
-// //int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-// return ResourceElement.getString(valueTable, getTable(), 4 * resourceIndex - 3 + offset, chars);\r
-// }\r
-\r
- public boolean hasValue(int resourceIndex) {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- return ResourceElement.hasValue(getTable(), realIndex);\r
- }\r
-\r
-// boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {\r
-// int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-// return ResourceElement.hasValue(valueTable, getTable(), realIndex, value);\r
-// }\r
-\r
- public boolean removeValue(ValueTable valueTable, int resourceIndex) {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- boolean ret = ResourceElement.removeValue(valueTable, getTable(), realIndex);\r
-// if (ret && !ResourceElement.isUsed(getTable(), realIndex))\r
-// decResourceCount();\r
- return ret;\r
- }\r
-\r
- public void setValue(ValueTable valueTable, int resourceIndex, byte[] value, int length) {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- ResourceElement.setValue(valueTable, getTable(), realIndex, value, length);\r
- }\r
-\r
- public boolean isValueEx(ValueTable valueTable, int resourceIndex) {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- return ResourceElement.isValueEx(valueTable, getTable(), realIndex);\r
- }\r
-\r
- public void setValueEx(ValueTable valueTable, int resourceIndex) {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- ResourceElement.setValueEx(valueTable, getTable(), realIndex);\r
- }\r
-\r
- static final int RESOURCE_COUNT_INDEX = 0;\r
- static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.\r
- static final int CLUSTER_STATUS_INDEX = 2;\r
-\r
- int incResourceCount() {\r
- int count = getExtra(RESOURCE_COUNT_INDEX) + 1;\r
- setExtra(RESOURCE_COUNT_INDEX, count);\r
- return count;\r
- }\r
-\r
-// int decResourceCount() {\r
-// int count = getExtra(RESOURCE_COUNT_INDEX) - 1;\r
-// setExtra(RESOURCE_COUNT_INDEX, count);\r
-// return count;\r
-// }\r
-\r
- public int getResourceCount() {\r
- return getExtra(RESOURCE_COUNT_INDEX);\r
- }\r
- public int getClusterStatus() {\r
- return getExtra(CLUSTER_STATUS_INDEX);\r
- }\r
- public void setClusterStatus(int value) {\r
- setExtra(CLUSTER_STATUS_INDEX, value);\r
- }\r
- void analyse() {\r
-\r
- final int tsize = getTableSize();\r
- final int esize = ResourceElement.getSizeOf();\r
- long[] table = getTable();\r
- for (int i = getTableBase(); i < getTableBase() + tsize; i += esize) {\r
- if (ResourceElement.isUsed(getTable(), i)) {\r
- System.out.println(" -" + Long.toHexString(table[i]) + " " + Long.toHexString(table[i+1]) + " " + Long.toHexString(table[i+2]) + " " + Long.toHexString(table[i+3]));\r
- }\r
- }\r
-\r
- }\r
- \r
- public <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,\r
- ClusterSupport support, Modifier modifier) throws DatabaseException {\r
- final int tsize = getTableSize();\r
-// final int rsize = getResourceCount();\r
- final int esize = ResourceElement.getSizeOf();\r
- //int count = 0;\r
- int key = ZERO_SHIFT;\r
- for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {\r
- if (ResourceElement.isUsed(getTable(), i)) {\r
- int ref;\r
- if (null == modifier)\r
- ref = key;\r
- else\r
- ref = modifier.execute(key);\r
- if (procedure.execute(context, ref))\r
- return true; // loop was broken by procedure\r
-// if (rsize == ++count)\r
-// return false; // loop finished\r
- }\r
- }\r
- //assert(rsize == count);\r
- return false; // loop finished\r
- }\r
-\r
- public <Context> boolean foreachPredicate(int resourceIndex\r
- , ClusterI.PredicateProcedure<Context> procedure, Context context\r
- , ClusterSupport support, Modifier modifier, CompleteTable ct)\r
- throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- return ResourceElement.foreachPredicate(getTable(), realIndex\r
- , procedure, context, support, modifier, ct);\r
- }\r
-\r
- public int getSingleObject(int resourceIndex, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {\r
-// return ResourceElement.getSingleObject(table, realIndex, support, pRef, pCompleteType, ct, modifier);\r
- return ResourceElement.getSingleObject(table, 4 * resourceIndex - 3 + offset, support, pRef, pCompleteType, ct, modifier);\r
- }\r
-\r
- public void foreachObject(int resourceIndex, ReadGraphImpl graph,\r
- AsyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- ResourceElement.foreachObject(table, realIndex, graph, procedure, support,\r
- pRef, pCompleteType, ct, modifier);\r
- }\r
-\r
- public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,\r
- AsyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- ResourceElement.foreachObject(table, realIndex, graph, context, procedure, support,\r
- pRef, pCompleteType, ct, modifier);\r
- }\r
- \r
- public <Context> boolean foreachObject(int resourceIndex\r
- , ClusterI.ObjectProcedure<Context> procedure, Context context\r
- , ClusterSupport support, Modifier modifier,\r
- int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
- throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- return ResourceElement.foreachObject(table, realIndex\r
- , procedure, context, support, modifier\r
- , pRef, completeType, ct);\r
- }\r
- public int addStatement(int resourceIndex, int pRef, int oRef, PredicateTable pt, ObjectTable ot\r
- , ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)\r
- throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- return ResourceElement.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, pCompleteType, ct);\r
- }\r
-\r
- public boolean removeStatementFromCache(int resourceIndex, int pRef, int oRef,\r
- ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)\r
- throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- boolean ret = ResourceElement.removeStatement(getTable(), realIndex, pRef, oRef, pCompleteType, ct);\r
-// if (ret && !ResourceElement.isUsed(getTable(), realIndex))\r
-// decResourceCount();\r
- return ret;\r
- }\r
- \r
- public void removeStatement(int resourceIndex, int pRef, int oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,\r
- PredicateTable pt, ObjectTable ot, ClusterBase cluster, ClusterSupport support)\r
- throws DatabaseException {\r
- int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
- boolean removed = ResourceElement.removeStatement(getTable(), realIndex,\r
- pRef, oRef, pCompleteType, ct);\r
- if (!removed)\r
- return;\r
- int predicateIndex = ResourceElement.getPredicateIndex(getTable(), realIndex);\r
- if (0 == predicateIndex) {\r
-// if (!ResourceElement.isUsed(getTable(), realIndex))\r
-// decResourceCount();\r
- return;\r
- }\r
- GetStatements gs = new GetStatements(ot);\r
- pt.foreachPredicate(predicateIndex, gs, null, null, null);\r
- ArrayList<Statement> stms = gs.getStatements();\r
-\r
- final int SIZE = stms.size();\r
- if (SIZE < 3) {\r
- for (int i = 0; i < SIZE; ++i) {\r
- Statement stm = stms.get(i);\r
- PredicateTable.Status ret = pt.removePredicate(predicateIndex,\r
- stm.pRef, stm.oIndex, ot);\r
- if (ret == Status.NothingRemoved)\r
- throw new DatabaseException("Internal error during statement cache fix (2).");\r
- int predicateKey = cluster.makeResourceKey(stm.pRef);\r
- int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);\r
- ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt);\r
- int pi = ResourceElement.addStatement(getTable(), realIndex, stm.pRef, stm.oIndex,\r
- pt, ot, completeType, ct);\r
- assert(0 >= pi);\r
- }\r
- assert(0 == pt.getPredicateSetSize(predicateIndex));\r
- ResourceElement.setPredicateIndex(getTable(), realIndex, 0);\r
- } else {\r
- for (int i = 0; i < SIZE; ++i) {\r
- Statement stm = stms.get(i);\r
- int predicateKey = cluster.makeResourceKey(stm.pRef);\r
- int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);\r
- ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt);\r
- int pIndex = ResourceElement.addStatement(getTable(), realIndex,\r
- stm.pRef, stm.oIndex, pt, ot, completeType, ct);\r
- if (pIndex > 0)\r
- return; // cache fixed and full, p and o sets in use\r
- }\r
- throw new DatabaseException("Internal error during statement cache fix (3).");\r
- }\r
-// if (!ResourceElement.isUsed(getTable(), realIndex))\r
-// decResourceCount();\r
- }\r
-\r
- //(i-1)*4+1 + 4\r
- private int checkIndexAndGetRealIndex(final int INDEX) {\r
- assert(INDEX > 0);\r
- assert(INDEX <= getTableCount());\r
-// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT;\r
-// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT;\r
-// return checkIndexAndGetRealIndex(TABLE_INDEX, ResourceElement.getSizeOf());\r
- return 4 * INDEX - 3 + offset;\r
- }\r
- public void check(ClusterBase cluster)\r
- throws DatabaseException {\r
-// int count = 0;\r
- cluster.checkValueInit();\r
- long[] table = getTable();\r
- int ps = getHeader().getOffset() + ZERO_SHIFT;\r
- final int TABLE_SIZE = getTableSize();\r
- int pe = ps + TABLE_SIZE;\r
- for (int p=ps; p<pe; p+=ResourceElement.getSizeOf()) {\r
- if (!ResourceElement.isUsed(table, p))\r
- continue;\r
- int cr = ResourceElement.getCompleteObjectRef(table, p);\r
- if (0 != cr) {\r
- if (ClusterTraits.completeReferenceIsMultiple(cr))\r
- cluster.checkCompleteSetReference(cr);\r
- else {\r
- int fi = ClusterTraits.completeReferenceGetForeignIndex(cr);\r
- int ri = ClusterTraits.completeReferenceGetResourceIndex(cr);\r
- if (0 != fi)\r
- cluster.checkForeingIndex(fi);\r
- else if (ri < 1 || ri > TABLE_SIZE)\r
- throw new ValidationException("Illegal resource index=" + ri);\r
- }\r
- }\r
- int pi = ResourceElement.getPredicateIndex(table, p);\r
- if (0 != pi) {\r
- cluster.checkPredicateIndex(pi);\r
- }\r
- ResourceElement.ValueData vd = new ResourceElement.ValueData();\r
- ResourceElement.getValueCapacityAndIndex(vd, table, p);\r
- cluster.checkValue(vd.capacity, vd.index);\r
- }\r
- cluster.checkValueFini();\r
- }\r
-\r
- @Override\r
- public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,\r
- ClusterSupport support, Modifier modifier) throws DatabaseException {\r
- throw new UnsupportedOperationException();\r
- }\r
-}\r
-\r
-class Statement {\r
- Statement(int pRef, int oIndex) {\r
- this.pRef = pRef;\r
- this.oIndex = oIndex;\r
- }\r
- final int pRef;\r
- final int oIndex;\r
-}\r
-\r
-class CalculateStatements\r
-implements ClusterI.PredicateProcedure<CalculateStatements> {\r
- private ObjectTable ot;\r
- private final int sRef;\r
-\r
- CalculateStatements(int sRef, ObjectTable ot) {\r
- this.sRef = sRef;\r
- this.ot = ot;\r
- }\r
-\r
- @Override\r
- public boolean execute(final CalculateStatements context\r
- , final int pKey, int oIndex) {\r
- if (ClusterTraits.statementIndexIsDirect(oIndex))\r
- return false; // osize = 1\r
- try {\r
- oIndex = ClusterTraits.statementIndexGet(oIndex);\r
- } catch (DatabaseException e) {\r
- Logger.getDefault().logError("Missing object set for s="\r
- + sRef + " p=" + pKey, null);\r
- return false; // continue looping\r
- }\r
- int osize = ot.getObjectSetSize(oIndex);\r
- if (osize == 3 || osize > 9)\r
- System.out.println("Resource " + sRef + " predicate " + pKey + " has "\r
- + osize + " objects.");\r
- return true; // break loop\r
- }\r
-}\r
-\r
-class GetStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {\r
- private ObjectTable ot;\r
- private final ArrayList<Statement> stms = new ArrayList<Statement>(); \r
- GetStatements(ObjectTable ot) {\r
- this.ot = ot;\r
- }\r
- ArrayList<Statement> getStatements() {\r
- return stms;\r
- }\r
- @Override\r
- public boolean execute(Object context, int pRef, int oIndex) {\r
- try {\r
- ot.foreachObject(oIndex, this, pRef, null, null);\r
- } catch (DatabaseException e) {\r
- e.printStackTrace();\r
- return false; // continue looping\r
- }\r
- if (stms.size() > 2)\r
- return true; // break loop\r
- return false; // continue looping\r
- }\r
-\r
- @Override\r
- public boolean execute(Integer pRef, int oRef) {\r
- stms.add(new Statement(pRef, oRef));\r
- if (stms.size() > 2)\r
- return true; // break loop\r
- return false; // continue looping\r
- }\r
- \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.procore.cluster;
+
+import java.util.ArrayList;
+
+import org.simantics.db.Resource;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ExternalValueException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.db.impl.ClusterBase;
+import org.simantics.db.impl.ClusterI;
+import org.simantics.db.impl.ClusterI.CompleteTypeEnum;
+import org.simantics.db.impl.ClusterI.ObjectProcedure;
+import org.simantics.db.impl.ClusterI.PredicateProcedure;
+import org.simantics.db.impl.ClusterI.Procedure;
+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.Table;
+import org.simantics.db.impl.TableFactory;
+import org.simantics.db.impl.TableSizeListener;
+import org.simantics.db.impl.graph.ReadGraphImpl;
+import org.simantics.db.procedure.AsyncContextMultiProcedure;
+import org.simantics.db.procedure.AsyncMultiProcedure;
+import org.simantics.db.procore.cluster.PredicateTable.Status;
+
+
+final class ResourceElement {
+ private static final boolean DEBUG = ClusterImpl.DEBUG;
+ private static final int DESCRIPTOR_OFFSET = 0; // predicate descriptor
+ private static final int VALUE_OFFSET = 1; // value descriptor
+ private static final int STM_OFFSET = 2; // first statement
+ private static final int SIZE_OF = 4;
+
+ static void construct(long[] table, int index) {
+ int i = DESCRIPTOR_OFFSET + index;
+ table[i++] = 0; // predicate capacity & index
+ table[i++] = 0; // value capacity & index
+ table[i++] = 0; // stm1
+ table[i++] = 0; // stm2
+ }
+
+ static void destruct(long[] table, int index) {
+ int i = DESCRIPTOR_OFFSET + index;
+ table[i++] = 0; // predicate capacity & index
+ table[i++] = 0; // value capacity & index
+ table[i++] = 0; // stm1
+ table[i++] = 0; // stm2
+ }
+
+ static boolean isUsed(long[] table, int index) {
+ int i = DESCRIPTOR_OFFSET + index;
+ if (table[i++] != 0)
+ return true;
+ if (table[i++] != 0)
+ return true;
+ if (table[i++] != 0)
+ return true;
+ if (table[i++] != 0)
+ return true;
+ return false;
+ }
+
+ static int getSizeOf() {
+ return SIZE_OF;
+ }
+
+ static int getCompleteObjectRef(long[] table, int index) {
+ int i = DESCRIPTOR_OFFSET + index;
+ return BitUtility.getHighInt(table[i]);
+ }
+
+ static void setCompleteObjectRef(long[] table, int index, int ref) {
+ int i = DESCRIPTOR_OFFSET + index;
+ table[i] = BitUtility.setHighInt(table[i], ref);
+ }
+
+ static int getPredicateIndex(long[] table, int index) {
+ int i = DESCRIPTOR_OFFSET + index;
+ int predicateIndex = BitUtility.getLowInt(table[i]);
+ assert (predicateIndex >= 0);
+ return predicateIndex;
+ }
+
+ static void setPredicateIndex(long[] table, int index, int predicateIndex) {
+ assert (predicateIndex >= 0);
+ int i = DESCRIPTOR_OFFSET + index;
+ table[i] = BitUtility.setLowInt(table[i], predicateIndex);
+ }
+
+ static int copyValue(ValueTable valueTable, long[] table, int index, byte[] byteTable, int byteSize, int byteBase,
+ int byteCurrent) {
+ int i = VALUE_OFFSET + index;
+ if (0 == table[i] || -1 == table[i])
+ return byteCurrent; // no value or external value
+ // getValueCapacity call optimized away
+ int capacity = BitUtility.getLowInt(table[i]);
+ int valueIndex = getValueIndex(table, index);
+ if (0 == valueIndex)
+ return byteCurrent;
+ valueTable.getValue(valueIndex, byteTable, byteCurrent, capacity);
+ valueIndex = byteCurrent - byteBase;
+ setValueIndex(table, index, valueIndex);
+ byteCurrent += capacity;
+ return byteCurrent;
+ }
+
+ static byte[] getValue(ValueTable valueTable, long[] table, int index)
+ throws DatabaseException {
+ int i = VALUE_OFFSET + index;
+ if (0 == table[i])
+ return null; // no value
+ if (-1 == table[i])
+ throw new ExternalValueException("Value stored externally.");
+ // getValueCapacity call optimized away
+ int capacity = BitUtility.getLowInt(table[i]);
+ byte[] t = new byte[capacity];
+ int valueIndex = getValueIndex(table, index);
+ valueTable.getValue(valueIndex, t, 0, capacity);
+ return t;
+ }
+
+// static int getString(ValueTable valueTable, long[] table, int index, char[] t)
+// throws DatabaseException {
+// long l = table[index + VALUE_OFFSET];
+// if (-1 == l)
+// throw new ExternalValueException("String stored externally.");
+// int capacity = (int)l;
+// int valueIndex = (int) (l >>> 32);
+//// char[] t = new char[capacity-1];
+// valueTable.getString(valueIndex, t, 0, capacity-1);
+// return capacity-1;
+//
+// }
+
+ static boolean hasValue(long[] table, int index) {
+ int i = VALUE_OFFSET + index;
+ return 0 != table[i];
+ }
+//KRAA:
+// static boolean hasValue(ValueTable valueTable, long[] table, int index, byte[] value) {
+// int i = VALUE_OFFSET + index;
+// if (0 == table[i])
+// return false;
+// // getValueCapacity call optimized away
+// int capacity = BitUtility.getLowInt(table[i]);
+// if (capacity != value.length)
+// return false;
+// int valueIndex = getValueIndex(table, index);
+// return valueTable.isEqual(valueIndex, value);
+// }
+
+ static boolean removeValue(ValueTable valueTable, long[] table, int index) {
+ int i = VALUE_OFFSET + index;
+ if (0 == table[i])
+ return false;
+ else if (-1 != table[i]) {
+ // getValueCapacity call optimized away
+ int capacity = BitUtility.getLowInt(table[i]);
+ int valueIndex = getValueIndex(table, index);
+ valueTable.removeValue(valueIndex, capacity);
+ }
+ //setValueCapacityAndIndex(table, index, 0, 0); optimized away
+ table[i] = 0;
+ return true;
+ }
+
+ public static void setValue(ValueTable valueTable, long[] table, int index, byte[] value, int length) {
+ int i = VALUE_OFFSET + index;
+ // getValueCapacity call optimized away
+ int capacity = BitUtility.getLowInt(table[i]);
+ int valueIndex = getValueIndex(table, index);
+ if (length <= capacity) {
+ valueTable.setValue(valueIndex, value, length);
+ // we "leak" memory TODO: add value size member to
+ // resource entry or value entry
+ setValueCapacity(table, index, length);
+ } else {
+ if (valueIndex != 0 && capacity > 0)
+ valueTable.removeValue(valueIndex, capacity);
+ valueIndex = valueTable.createValue(value, 0, length);
+ capacity = length;
+ setValueCapacityAndIndex(table, index, capacity, valueIndex);
+ }
+ return;
+ }
+ public static boolean isValueEx(ValueTable valueTable, long[] table, int index) {
+ int i = VALUE_OFFSET + index;
+ if (-1 == table[i])
+ return true;
+ else
+ return false;
+ }
+ public static void setValueEx(ValueTable valueTable, long[] table, int index) {
+ int i = VALUE_OFFSET + index;
+ if (-1 == table[i])
+ return;
+ else if (0 != table[i]) {
+ int capacity = BitUtility.getLowInt(table[i]);
+ int valueIndex = getValueIndex(table, index);
+ valueTable.removeValue(valueIndex, capacity);
+ }
+ //setValueCapacityAndIndex(table, index, 0, 0); optimized away
+ table[i] = -1;
+ }
+ static class ValueData {
+ int capacity;
+ int index;
+// ValueData(int capacity, int index) {
+// this.capacity = capacity;
+// this.index = index;
+// }
+ }
+ static void getValueCapacityAndIndex(ValueData vd, long[] table, int index) {
+ int i = VALUE_OFFSET + index;
+ // getValueCapacity call optimized away
+ vd.capacity = BitUtility.getLowInt(table[i]);
+ vd.index = getValueIndex(table, index);
+
+ }
+ private static int getValueIndex(long[] table, int index) {
+ int i = VALUE_OFFSET + index;
+ return BitUtility.getHighInt(table[i]);
+ }
+
+ private static void setValueIndex(long[] table, int index, int valueIndex) {
+ int i = VALUE_OFFSET + index;
+ table[i] = BitUtility.setHighInt(table[i], valueIndex);
+ }
+
+ private static void setValueCapacity(long[] table, int index, int capacity) {
+ int i = VALUE_OFFSET + index;
+ table[i] = BitUtility.setLowInt(table[i], capacity);
+ }
+
+ private static void setValueCapacityAndIndex(long[] table, int index, int capacity, int valueIndex) {
+ int i = VALUE_OFFSET + index;
+ table[i] = BitUtility.setLowAndHighInt(table[i], capacity, valueIndex);
+ }
+
+ 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 = ResourceElement.getCompleteObjectRef(table, index);
+ if (0 != completeRef) {
+ if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements
+ 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 {
+ ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
+ 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 != ResourceElement.getPredicateIndex(table, index)) {
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachPredicate: more than 2 objects");
+ return false;
+ }
+ int i = STM_OFFSET + index;
+ int p1 = BitUtility.getHighInt(table[i]);
+ 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 = BitUtility.getHighInt(table[++i]);
+ if (0 == p2 || p1 == p2) {
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachPredicate: cache2 empty");
+ return false; // loop finished, one statement
+ } if (null == modifier)
+ externalRef = p2;
+ else
+ externalRef = modifier.execute(p2);
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachPredicate: cache2 pk=" + externalRef);
+ if (procedure.execute(context, externalRef, 0))
+ return true; // loop broken by procedure
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachPredicate: not in cache");
+ return false; // loop finished, two statements
+ }
+
+ public static int getSingleObject(long[] table, int index, ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final 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 (ClusterTraits.completeReferenceIsMultiple(completeRef)) {
+ // Multiple complete type elements.
+ if (DEBUG)
+ System.out.println("ResourceElement.getSingleObject was complete 2");
+ class ForeachObject
+ implements ClusterI.ObjectProcedure<Integer> {
+ @Override
+ public boolean execute(Integer context, int completeRef)
+ throws DatabaseException {
+ ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (pCompleteType == oCompleteType) { // we have a match
+ if (context != 0) { // we have an old match
+ context = 0; // multiple objects for given type
+ return true; // break loop
+ }
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ context = modifier.execute(resourceIndex);
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ context = modifier.execute(externalRef);
+ }
+ }
+ return true; // continue looping
+ }
+
+ }
+ ForeachObject t = new ForeachObject();
+ // CompleteRef is complete object set index.
+ Integer c = 0;
+ ct.foreachComplete(completeRef, t, c, support, modifier);
+ return c;
+ }
+ // one complete type element
+ ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (pCompleteType != completeType)
+ return 0;
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ return modifier.execute(resourceIndex);
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ return modifier.execute(externalRef);
+ }
+ }
+ int i = STM_OFFSET + index;
+ int p1 = BitUtility.getHighInt(table[i]);
+ if (0 == p1)
+ return 0; // loop finished, no statements
+ int result = 0;
+ if (pRef == p1) {
+ int o1 = BitUtility.getLowInt(table[i]);
+ 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 = BitUtility.getHighInt(table[++i]);
+ if (0 == p2 || pRef != p2)
+ return result; // loop finished, one statements
+
+ // Many statements
+ if (result != 0) return -1;
+
+ int o2 = BitUtility.getLowInt(table[i]);
+ return modifier.execute(o2);
+
+// return 0;
+// int o2 = BitUtility.getLowInt(table[i]);
+// 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,
+ final ClusterSupport support, final int pRef, final 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 (ClusterTraits.completeReferenceIsMultiple(completeRef)) {
+ // Multiple complete type statements.
+ if (DEBUG)
+ System.out.println("ResourceElement.was complete 2");
+ class ForeachObject implements ClusterI.ObjectProcedure<Object> {
+ @Override
+ public boolean execute(Object context, int completeRef) throws DatabaseException {
+ ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (pCompleteType == oCompleteType) {
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
+ }
+ }
+ return false; // continue looping
+ }
+
+ }
+ ForeachObject t = new ForeachObject();
+ // CompleteRef is complete object set index.
+ ct.foreachComplete(completeRef, t, null, support, modifier);
+ procedure.finished(graph);
+// graph.state.dec(0);
+ return; // loop finished
+ }
+ // one complete type element
+ ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (pCompleteType != completeType) {
+ procedure.finished(graph);
+// graph.state.dec(0);
+ return;
+ }
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
+ }
+ procedure.finished(graph);
+// graph.state.dec(0);
+ return; // loop finished
+ }
+ int i = STM_OFFSET + index;
+ long l = table[i];
+ int p1 = (int) (l >>> 32);
+ if (0 == p1) {
+ procedure.finished(graph);
+// graph.state.dec(0);
+ return; // loop finished, no statements
+ }
+ if (pRef == p1) {
+ int o1 = (int)l;
+ 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
+ }
+ long l2 = table[++i];
+ int p2 = (int) (l2 >>> 32);
+ if (pRef != p2) {
+ procedure.finished(graph);
+// graph.state.dec(0);
+ return; // loop finished, one statements
+ }
+ int o2 = (int)l2;
+ 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,
+ final ClusterSupport support, final int pRef, final 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 (ClusterTraits.completeReferenceIsMultiple(completeRef)) {
+ // Multiple complete type statements.
+ if (DEBUG)
+ System.out.println("ResourceElement.was complete 2");
+ class ForeachObject implements ClusterI.ObjectProcedure<Object> {
+ @Override
+ public boolean execute(Object _context, int completeRef) throws DatabaseException {
+ ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (pCompleteType == oCompleteType) {
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
+ }
+ }
+ return false; // continue looping
+ }
+
+ }
+ ForeachObject t = new ForeachObject();
+ // CompleteRef is complete object set index.
+ ct.foreachComplete(completeRef, t, null, support, modifier);
+ procedure.finished(graph, context);
+// graph.state.dec(0);
+ return; // loop finished
+ }
+ // one complete type element
+ ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (pCompleteType != completeType) {
+ procedure.finished(graph, context);
+// graph.state.dec(0);
+ return;
+ }
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
+ }
+ procedure.finished(graph, context);
+// graph.state.dec(0);
+ return; // loop finished
+ }
+ int i = STM_OFFSET + index;
+ long l = table[i];
+ int p1 = (int) (l >>> 32);
+ if (0 == p1) {
+ procedure.finished(graph, context);
+// graph.state.dec(0);
+ return; // loop finished, no statements
+ }
+ if (pRef == p1) {
+ int o1 = (int)l;
+ 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
+ }
+ long l2 = table[++i];
+ int p2 = (int) (l2 >>> 32);
+ if (pRef != p2) {
+ procedure.finished(graph, context);
+// graph.state.dec(0);
+ return; // loop finished, one statements
+ }
+ int o2 = (int)l2;
+ 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 int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)
+ throws DatabaseException {
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: 1 ");
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
+ int completeRef = getCompleteObjectRef(table, index);
+ if (0 == completeRef) {
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: no complete");
+ return false; // no objects for given complete type
+ }
+ if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: multi-complete ci=" + completeRef);
+ return ct.foreachObject(completeRef, procedure, context, support, modifier, pCompleteType);
+ }
+ // one complete type element
+ ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (pCompleteType != completeType) {
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: complete different predicate");
+ return false;
+ }
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ int externalRef;
+ if (null == modifier)
+ externalRef = resourceIndex;
+ else
+ externalRef = modifier.execute(resourceIndex);
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef);
+ if (procedure.execute(context, externalRef))
+ return true; // loop broken by procedure
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ if (null != modifier)
+ externalRef = modifier.execute(externalRef);
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef);
+ if (procedure.execute(context, externalRef))
+ return true; // loop broken by procedure
+ }
+ return false; // loop finished
+ }
+ int i = STM_OFFSET + index;
+ int p1 = BitUtility.getHighInt(table[i]);
+ if (0 == p1) {
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: empty cache=");
+ return false; // loop finished, no statements
+ }
+ if (pRef == p1) {
+ int o1 = BitUtility.getLowInt(table[i]);
+ int externalRef;
+ if (null == modifier)
+ externalRef = o1;
+ else
+ externalRef = modifier.execute(o1);
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: cache1 ok=" + externalRef);
+ if (procedure.execute(context, externalRef))
+ return true; // loop broken by procedure
+ }
+ int p2 = BitUtility.getHighInt(table[++i]);
+ if (0 == p2 || pRef != p2) {
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: not in cache1");
+ return false; // loop finished, one statements
+ }
+ int o2 = BitUtility.getLowInt(table[i]);
+ int externalRef;
+ if (null == modifier)
+ externalRef = o2;
+ else
+ externalRef = modifier.execute(o2);
+ if (DEBUG)
+ System.out.println("ResourceElement.foreachObject2: cache2 ok=" + externalRef);
+ return procedure.execute(context, externalRef);
+ }
+ static boolean isEmpty(long[] table, int index) {
+ return getStatementCount(table, index) == 0 && !hasValue(table, index);
+ }
+ static int getStatementCount(long[] table, int index) {
+ int i = STM_OFFSET + index;
+ int p1 = BitUtility.getHighInt(table[i]);
+ int p2 = BitUtility.getLowInt(table[++i]);
+ if (0 == p1)
+ return 0;
+ else if (0 == p2)
+ return 1;
+ int predicateIndex = getPredicateIndex(table, index);
+ if (0 == predicateIndex)
+ return 2;
+ return 3;
+ }
+ private static int makeCompleteObjectRef(int oRef, ClusterI.CompleteTypeEnum completeType) {
+ int ref;
+ if (oRef > 0) {
+ int resourceIndex = oRef;
+ int clusterIndex = 0;
+ ref = ClusterTraits.completeReferenceMake(completeType.getValue(), resourceIndex, clusterIndex);
+ } else {
+ assert(oRef < 0);
+ assert(!ClusterTraits.isFlat(oRef));
+ ref = (completeType.getValue() <<30) | (oRef & 0x3FFFFFFF);
+ }
+ return ref;
+ }
+ static int addStatement(long[] table, int index, int pRef, int oRef
+ , PredicateTable pt, ObjectTable ot
+ , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
+ throws DatabaseException {
+ assert (0 != pRef);
+ assert (0 != oRef);
+ if (ClusterI.CompleteTypeEnum.NotComplete != completeType) {
+ int cRef = makeCompleteObjectRef(oRef, completeType);
+ int ctr = getCompleteObjectRef(table, index);
+ if (0 == ctr)
+ setCompleteObjectRef(table, index, cRef);
+ else {
+ int nRef;
+ if (ctr == cRef)
+ return -1; // old complete
+ else if (ClusterTraits.completeReferenceIsMultiple(ctr)) {
+ nRef = ct.addComplete(ctr, cRef);
+ if (0 == nRef)
+ return -1; // old complete
+ } else {
+ nRef = ct.createCompleteArraySet(ctr, cRef);
+ }
+ setCompleteObjectRef(table, index, nRef);
+ }
+ return 0; // added to complete
+ }
+ int i = STM_OFFSET + index;
+ int p1 = BitUtility.getHighInt(table[i]);
+ int o1 = BitUtility.getLowInt(table[i]);
+ if (0 == p1) {
+ table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef);
+ return 0; // added to stm cache
+ } else if (p1 == pRef && o1 == oRef)
+ return -1; // same statement
+ int p2 = BitUtility.getHighInt(table[++i]);
+ int o2 = BitUtility.getLowInt(table[i]);
+ if (0 == p2) {
+ table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef);
+ 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, o2);
+ assert (0 != objectIndex);
+ int[] os = new int[1];
+ os[0] = ClusterTraits.statementIndexMake(objectIndex);
+ int[] ps = new int[1];
+ ps[0] = p1;
+ predicateIndex = pt.createPredicateSet(ps, os);
+ } else {
+ int[] os = new int[2];
+ os[0] = o1;
+ os[1] = o2;
+ int[] ps = new int[2];
+ ps[0] = p1;
+ ps[1] = p2;
+ predicateIndex = pt.createPredicateSet(ps, os);
+ }
+ assert (0 != predicateIndex);
+ setPredicateIndex(table, index, predicateIndex);
+ }
+ assert (0 != predicateIndex);
+ return predicateIndex;
+ }
+
+ static boolean removeStatement(long[] table, int index, int pRef, int oRef,
+ ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
+ throws DatabaseException {
+ assert (0 != pRef);
+ assert (0 != oRef);
+ if (completeType != ClusterI.CompleteTypeEnum.NotComplete) {
+ int completeRef = ResourceElement.getCompleteObjectRef(table, index);
+ if (0 != completeRef) {
+ ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef);
+ if (completeType == completeType2) {
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ if (oRef == resourceIndex) {
+ ResourceElement.setCompleteObjectRef(table, index, 0);
+ return true; // statement removed
+ }
+ } else {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ if (oRef == externalRef) {
+ ResourceElement.setCompleteObjectRef(table, index, 0);
+ return true; // statement removed
+ }
+ }
+ } else if (completeType2 == ClusterI.CompleteTypeEnum.NotComplete) { // multiple complete type references
+ int cRef = makeCompleteObjectRef(oRef, completeType);
+ int oldSize = ct.getCompleteSetSize(completeRef);
+ int newSize = ct.removeComplete(completeRef, cRef);
+ if (oldSize == newSize)
+ return false; // not removed
+ else if (newSize == 1) {
+ cRef = ct.removeLast(completeRef);
+ ResourceElement.setCompleteObjectRef(table, index, cRef);
+ }
+ return true;
+ }
+ }
+ }
+ int i = STM_OFFSET + index;
+ int p1 = BitUtility.getHighInt(table[i]);
+ int o1 = BitUtility.getLowInt(table[i]);
+ if (0 == p1)
+ return false; // no statements cached
+ else if (p1 == pRef && o1 == oRef) {
+ table[i] = table[i + 1];
+ // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away
+ table[i + 1] = 0;
+ return true; // statement removed
+ }
+ int p2 = BitUtility.getHighInt(table[++i]);
+ int o2 = BitUtility.getLowInt(table[i]);
+ if (0 == p2)
+ return false; // no match
+ else if (p2 == pRef && o2 == oRef) {
+ // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away
+ table[i] = 0;
+ return true; // statement removed
+ }
+ return false;
+ }
+}
+
+public final class ResourceTable extends Table<long[]> {
+ public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase) {
+ super(TableFactory.getLongFactory(), sizeListener, header, headerBase);
+ }
+
+ public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {
+ super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);
+ }
+
+ public int getUsedSize() {
+ return getTableCount();
+ }
+
+ public short createResource() {
+ final int INDEX = getTableCount();
+ final int SIZE = ResourceElement.getSizeOf();
+ int resourceIndex = createNewElement(SIZE);
+ assert (0 != resourceIndex);
+ final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);
+ ResourceElement.construct(getTable(), REAL_INDEX);
+ incResourceCount();
+ return (short)(INDEX + ZERO_SHIFT);
+ }
+
+ void createResource(int resourceIndex) {
+ final int tableCount = getTableCount();
+ if (resourceIndex <= tableCount) { // old index
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ if (ResourceElement.isEmpty(getTable(), realIndex))
+ return;
+ } if (resourceIndex == tableCount+1) {
+ createResource();
+ return;
+ }
+ throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);
+ }
+
+// void deleteResource(int resourceIndex) {
+// int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+// ResourceElement.destruct(getTable(), realIndex);
+// decResourceCount();
+// }
+
+ public int getCompleteObjectRef(int resourceIndex) {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ return ResourceElement.getCompleteObjectRef(getTable(), realIndex);
+ }
+
+ public int getPredicateIndex(int resourceIndex) {
+ int i = (resourceIndex<<2) - 3 + offset;
+ return (int)table[i];
+ }
+
+ public void setPredicateIndex(int resourceIndex, int predicateIndex) {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ ResourceElement.setPredicateIndex(getTable(), realIndex, predicateIndex);
+ }
+
+ public byte[] getValue(ValueTable valueTable, int resourceIndex)
+ throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ return ResourceElement.getValue(valueTable, getTable(), realIndex);
+ }
+
+//KRAA:
+// int getString(ValueTable valueTable, int resourceIndex, char[] chars)
+// throws DatabaseException {
+// //int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+// return ResourceElement.getString(valueTable, getTable(), 4 * resourceIndex - 3 + offset, chars);
+// }
+
+ public boolean hasValue(int resourceIndex) {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ return ResourceElement.hasValue(getTable(), realIndex);
+ }
+
+// boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {
+// int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+// return ResourceElement.hasValue(valueTable, getTable(), realIndex, value);
+// }
+
+ public boolean removeValue(ValueTable valueTable, int resourceIndex) {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ boolean ret = ResourceElement.removeValue(valueTable, getTable(), realIndex);
+// if (ret && !ResourceElement.isUsed(getTable(), realIndex))
+// decResourceCount();
+ return ret;
+ }
+
+ public void setValue(ValueTable valueTable, int resourceIndex, byte[] value, int length) {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ ResourceElement.setValue(valueTable, getTable(), realIndex, value, length);
+ }
+
+ public boolean isValueEx(ValueTable valueTable, int resourceIndex) {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ return ResourceElement.isValueEx(valueTable, getTable(), realIndex);
+ }
+
+ public void setValueEx(ValueTable valueTable, int resourceIndex) {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ ResourceElement.setValueEx(valueTable, getTable(), realIndex);
+ }
+
+ static final int RESOURCE_COUNT_INDEX = 0;
+ static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.
+ static final int CLUSTER_STATUS_INDEX = 2;
+
+ int incResourceCount() {
+ int count = getExtra(RESOURCE_COUNT_INDEX) + 1;
+ setExtra(RESOURCE_COUNT_INDEX, count);
+ return count;
+ }
+
+// int decResourceCount() {
+// int count = getExtra(RESOURCE_COUNT_INDEX) - 1;
+// setExtra(RESOURCE_COUNT_INDEX, count);
+// return count;
+// }
+
+ public int getResourceCount() {
+ return getExtra(RESOURCE_COUNT_INDEX);
+ }
+ public int getClusterStatus() {
+ return getExtra(CLUSTER_STATUS_INDEX);
+ }
+ public void setClusterStatus(int value) {
+ setExtra(CLUSTER_STATUS_INDEX, value);
+ }
+ void analyse() {
+
+ final int tsize = getTableSize();
+ final int esize = ResourceElement.getSizeOf();
+ long[] table = getTable();
+ for (int i = getTableBase(); i < getTableBase() + tsize; i += esize) {
+ if (ResourceElement.isUsed(getTable(), i)) {
+ System.out.println(" -" + Long.toHexString(table[i]) + " " + Long.toHexString(table[i+1]) + " " + Long.toHexString(table[i+2]) + " " + Long.toHexString(table[i+3]));
+ }
+ }
+
+ }
+
+ public <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,
+ ClusterSupport support, Modifier modifier) throws DatabaseException {
+ final int tsize = getTableSize();
+// final int rsize = getResourceCount();
+ final int esize = ResourceElement.getSizeOf();
+ //int count = 0;
+ int key = ZERO_SHIFT;
+ for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {
+ if (ResourceElement.isUsed(getTable(), i)) {
+ int ref;
+ if (null == modifier)
+ ref = key;
+ else
+ ref = modifier.execute(key);
+ if (procedure.execute(context, ref))
+ return true; // loop was broken by procedure
+// if (rsize == ++count)
+// return false; // loop finished
+ }
+ }
+ //assert(rsize == count);
+ return false; // loop finished
+ }
+
+ public <Context> boolean foreachPredicate(int resourceIndex
+ , ClusterI.PredicateProcedure<Context> procedure, Context context
+ , ClusterSupport support, Modifier modifier, CompleteTable ct)
+ throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ return ResourceElement.foreachPredicate(getTable(), realIndex
+ , procedure, context, support, modifier, ct);
+ }
+
+ public int getSingleObject(int resourceIndex, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {
+// return ResourceElement.getSingleObject(table, realIndex, support, pRef, pCompleteType, ct, modifier);
+ return ResourceElement.getSingleObject(table, 4 * resourceIndex - 3 + offset, support, pRef, pCompleteType, ct, modifier);
+ }
+
+ public void foreachObject(int resourceIndex, ReadGraphImpl graph,
+ AsyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ ResourceElement.foreachObject(table, realIndex, graph, procedure, support,
+ pRef, pCompleteType, ct, modifier);
+ }
+
+ public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,
+ AsyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ ResourceElement.foreachObject(table, realIndex, graph, context, procedure, support,
+ pRef, pCompleteType, ct, modifier);
+ }
+
+ public <Context> boolean foreachObject(int resourceIndex
+ , ClusterI.ObjectProcedure<Context> procedure, Context context
+ , ClusterSupport support, Modifier modifier,
+ int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
+ throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ return ResourceElement.foreachObject(table, realIndex
+ , procedure, context, support, modifier
+ , pRef, completeType, ct);
+ }
+ public int addStatement(int resourceIndex, int pRef, int oRef, PredicateTable pt, ObjectTable ot
+ , ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)
+ throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ return ResourceElement.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, pCompleteType, ct);
+ }
+
+ public boolean removeStatementFromCache(int resourceIndex, int pRef, int oRef,
+ ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)
+ throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ boolean ret = ResourceElement.removeStatement(getTable(), realIndex, pRef, oRef, pCompleteType, ct);
+// if (ret && !ResourceElement.isUsed(getTable(), realIndex))
+// decResourceCount();
+ return ret;
+ }
+
+ public void removeStatement(int resourceIndex, int pRef, int oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,
+ PredicateTable pt, ObjectTable ot, ClusterBase cluster, ClusterSupport support)
+ throws DatabaseException {
+ int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+ boolean removed = ResourceElement.removeStatement(getTable(), realIndex,
+ pRef, oRef, pCompleteType, ct);
+ if (!removed)
+ return;
+ int predicateIndex = ResourceElement.getPredicateIndex(getTable(), realIndex);
+ if (0 == predicateIndex) {
+// if (!ResourceElement.isUsed(getTable(), realIndex))
+// decResourceCount();
+ return;
+ }
+ GetStatements gs = new GetStatements(ot);
+ pt.foreachPredicate(predicateIndex, gs, null, null, null);
+ ArrayList<Statement> stms = gs.getStatements();
+
+ final int SIZE = stms.size();
+ if (SIZE < 3) {
+ for (int i = 0; i < SIZE; ++i) {
+ Statement stm = stms.get(i);
+ PredicateTable.Status ret = pt.removePredicate(predicateIndex,
+ stm.pRef, stm.oIndex, ot);
+ if (ret == Status.NothingRemoved)
+ throw new DatabaseException("Internal error during statement cache fix (2).");
+ int predicateKey = cluster.makeResourceKey(stm.pRef);
+ int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);
+ ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt);
+ int pi = ResourceElement.addStatement(getTable(), realIndex, stm.pRef, stm.oIndex,
+ pt, ot, completeType, ct);
+ assert(0 >= pi);
+ }
+ assert(0 == pt.getPredicateSetSize(predicateIndex));
+ ResourceElement.setPredicateIndex(getTable(), realIndex, 0);
+ } else {
+ for (int i = 0; i < SIZE; ++i) {
+ Statement stm = stms.get(i);
+ int predicateKey = cluster.makeResourceKey(stm.pRef);
+ int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);
+ ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt);
+ int pIndex = ResourceElement.addStatement(getTable(), realIndex,
+ stm.pRef, stm.oIndex, pt, ot, completeType, ct);
+ if (pIndex > 0)
+ return; // cache fixed and full, p and o sets in use
+ }
+ throw new DatabaseException("Internal error during statement cache fix (3).");
+ }
+// if (!ResourceElement.isUsed(getTable(), realIndex))
+// decResourceCount();
+ }
+
+ //(i-1)*4+1 + 4
+ private int checkIndexAndGetRealIndex(final int INDEX) {
+ assert(INDEX > 0);
+ assert(INDEX <= getTableCount());
+// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT;
+// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT;
+// return checkIndexAndGetRealIndex(TABLE_INDEX, ResourceElement.getSizeOf());
+ return 4 * INDEX - 3 + offset;
+ }
+ public void check(ClusterBase cluster)
+ throws DatabaseException {
+// int count = 0;
+ cluster.checkValueInit();
+ long[] table = getTable();
+ int ps = getHeader().getOffset() + ZERO_SHIFT;
+ final int TABLE_SIZE = getTableSize();
+ int pe = ps + TABLE_SIZE;
+ for (int p=ps; p<pe; p+=ResourceElement.getSizeOf()) {
+ if (!ResourceElement.isUsed(table, p))
+ continue;
+ int cr = ResourceElement.getCompleteObjectRef(table, p);
+ if (0 != cr) {
+ if (ClusterTraits.completeReferenceIsMultiple(cr))
+ cluster.checkCompleteSetReference(cr);
+ else {
+ int fi = ClusterTraits.completeReferenceGetForeignIndex(cr);
+ int ri = ClusterTraits.completeReferenceGetResourceIndex(cr);
+ if (0 != fi)
+ cluster.checkForeingIndex(fi);
+ else if (ri < 1 || ri > TABLE_SIZE)
+ throw new ValidationException("Illegal resource index=" + ri);
+ }
+ }
+ int pi = ResourceElement.getPredicateIndex(table, p);
+ if (0 != pi) {
+ cluster.checkPredicateIndex(pi);
+ }
+ ResourceElement.ValueData vd = new ResourceElement.ValueData();
+ ResourceElement.getValueCapacityAndIndex(vd, table, p);
+ cluster.checkValue(vd.capacity, vd.index);
+ }
+ cluster.checkValueFini();
+ }
+
+ @Override
+ public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
+ ClusterSupport support, Modifier modifier) throws DatabaseException {
+ throw new UnsupportedOperationException();
+ }
+}
+
+class Statement {
+ Statement(int pRef, int oIndex) {
+ this.pRef = pRef;
+ this.oIndex = oIndex;
+ }
+ final int pRef;
+ final int oIndex;
+}
+
+class CalculateStatements
+implements ClusterI.PredicateProcedure<CalculateStatements> {
+ private ObjectTable ot;
+ private final int sRef;
+
+ CalculateStatements(int sRef, ObjectTable ot) {
+ this.sRef = sRef;
+ this.ot = ot;
+ }
+
+ @Override
+ public boolean execute(final CalculateStatements context
+ , final int pKey, int oIndex) {
+ if (ClusterTraits.statementIndexIsDirect(oIndex))
+ return false; // osize = 1
+ try {
+ oIndex = ClusterTraits.statementIndexGet(oIndex);
+ } catch (DatabaseException e) {
+ Logger.getDefault().logError("Missing object set for s="
+ + sRef + " p=" + pKey, null);
+ return false; // continue looping
+ }
+ int osize = ot.getObjectSetSize(oIndex);
+ if (osize == 3 || osize > 9)
+ System.out.println("Resource " + sRef + " predicate " + pKey + " has "
+ + osize + " objects.");
+ return true; // break loop
+ }
+}
+
+class GetStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {
+ private ObjectTable ot;
+ private final ArrayList<Statement> stms = new ArrayList<Statement>();
+ GetStatements(ObjectTable ot) {
+ this.ot = ot;
+ }
+ ArrayList<Statement> getStatements() {
+ return stms;
+ }
+ @Override
+ public boolean execute(Object context, int pRef, int oIndex) {
+ try {
+ ot.foreachObject(oIndex, this, pRef, null, null);
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ return false; // continue looping
+ }
+ if (stms.size() > 2)
+ return true; // break loop
+ return false; // continue looping
+ }
+
+ @Override
+ public boolean execute(Integer pRef, int oRef) {
+ stms.add(new Statement(pRef, oRef));
+ if (stms.size() > 2)
+ return true; // break loop
+ return false; // continue looping
+ }
+
+}