--- /dev/null
+/*******************************************************************************\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.io.ByteArrayInputStream;\r
+import java.io.InputStream;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ExternalValueException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.db.impl.ClusterI;\r
+import org.simantics.db.impl.ClusterSupport;\r
+import org.simantics.db.impl.ClusterTraitsBase;\r
+import org.simantics.db.impl.ForEachObjectContextProcedure;\r
+import org.simantics.db.impl.ForEachObjectProcedure;\r
+import org.simantics.db.impl.ForPossibleRelatedValueContextProcedure;\r
+import org.simantics.db.impl.ForPossibleRelatedValueProcedure;\r
+import org.simantics.db.impl.Table;\r
+import org.simantics.db.impl.TableHeader;\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.service.ClusterUID;\r
+import org.simantics.db.service.ResourceUID;\r
+import org.simantics.utils.datastructures.Callback;\r
+\r
+import fi.vtt.simantics.procore.DebugPolicy;\r
+import fi.vtt.simantics.procore.internal.ClusterChange;\r
+import fi.vtt.simantics.procore.internal.ClusterStream;\r
+import fi.vtt.simantics.procore.internal.ClusterTable;\r
+import fi.vtt.simantics.procore.internal.SessionImplSocket;\r
+import gnu.trove.map.hash.TIntShortHashMap;\r
+import gnu.trove.procedure.TIntProcedure;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+final public class ClusterSmall extends ClusterImpl {\r
+ \r
+ private static final int TABLE_HEADER_SIZE = TableHeader.HEADER_SIZE + TableHeader.EXTRA_SIZE;\r
+ private static final int RESOURCE_TABLE_OFFSET = 0;\r
+ private static final int PREDICATE_TABLE_OFFSET = RESOURCE_TABLE_OFFSET + TABLE_HEADER_SIZE;\r
+ private static final int OBJECT_TABLE_OFFSET = PREDICATE_TABLE_OFFSET + TABLE_HEADER_SIZE;\r
+ private static final int VALUE_TABLE_OFFSET = OBJECT_TABLE_OFFSET + TABLE_HEADER_SIZE;\r
+ private static final int FLAT_TABLE_OFFSET = VALUE_TABLE_OFFSET + TABLE_HEADER_SIZE;\r
+ private static final int COMPLETE_TABLE_OFFSET = FLAT_TABLE_OFFSET + TABLE_HEADER_SIZE;\r
+ private static final int FOREIGN_TABLE_OFFSET = COMPLETE_TABLE_OFFSET + TABLE_HEADER_SIZE;\r
+ private static final int INT_HEADER_SIZE = FOREIGN_TABLE_OFFSET + TABLE_HEADER_SIZE;\r
+ private final int clusterBits;\r
+ public final ResourceTableSmall resourceTable;\r
+ private PredicateTable predicateTable;\r
+ final ObjectTable objectTable;\r
+ public final ValueTableSmall valueTable;\r
+ public final ForeignTableSmall foreignTable;\r
+ private final CompleteTableSmall completeTable;\r
+ private final ClusterMapSmall clusterMap;\r
+ private final int[] headerTable;\r
+ private final ClusterSupport clusterSupport;\r
+ private boolean proxy;\r
+ private boolean deleted = false;\r
+ \r
+ public ClusterSmall(ClusterUID clusterUID, int clusterKey, ClusterTable clusterTable, ClusterSupport support) {\r
+ super(clusterUID, clusterKey, support);\r
+ if(DebugPolicy.REPORT_CLUSTER_EVENTS)\r
+ new Exception(clusterUID.toString()).printStackTrace();\r
+ this.proxy = true;\r
+ this.headerTable = null;\r
+ this.resourceTable = null;\r
+ this.foreignTable = null;\r
+ this.predicateTable = null;\r
+ this.objectTable = null;\r
+ this.valueTable = null;\r
+ this.completeTable = null;\r
+ this.clusterMap = null;\r
+ this.clusterSupport = null;\r
+ this.clusterBits = 0;\r
+ this.importance = 0;\r
+ }\r
+ public ClusterSmall(ClusterUID clusterUID, int clusterKey, ClusterSupport support) {\r
+ super(clusterUID, clusterKey, support);\r
+ if(DebugPolicy.REPORT_CLUSTER_EVENTS)\r
+ new Exception(clusterUID.toString()).printStackTrace();\r
+ this.proxy = false;\r
+ this.headerTable = new int[INT_HEADER_SIZE];\r
+ this.resourceTable = new ResourceTableSmall(this, headerTable, RESOURCE_TABLE_OFFSET);\r
+ this.foreignTable = new ForeignTableSmall(this, headerTable, FOREIGN_TABLE_OFFSET);\r
+ this.predicateTable = new PredicateTable(this, headerTable, PREDICATE_TABLE_OFFSET);\r
+ this.objectTable = new ObjectTable(this, headerTable, OBJECT_TABLE_OFFSET);\r
+ this.valueTable = new ValueTableSmall(this, headerTable, VALUE_TABLE_OFFSET);\r
+ this.completeTable = new CompleteTableSmall(this, headerTable, COMPLETE_TABLE_OFFSET);\r
+ this.clusterMap = new ClusterMapSmall(this, foreignTable);\r
+ this.clusterSupport = support;\r
+ this.clusterBits = ClusterTraitsBase.getClusterBits(clusterKey);\r
+ this.importance = -clusterTable.timeCounter();\r
+ }\r
+ protected ClusterSmall(long[] longs, int[] ints, byte[] bytes, ClusterSupport support, int clusterKey)\r
+ throws DatabaseException {\r
+ super(checkValidity(-1, longs, ints, bytes), clusterKey, support);\r
+ this.proxy = false;\r
+ if (ints.length < INT_HEADER_SIZE)\r
+ throw new IllegalArgumentException("Too small integer table for cluster.");\r
+ this.headerTable = ints;\r
+ if(DebugPolicy.REPORT_CLUSTER_EVENTS) new Exception(Long.toString(clusterId)).printStackTrace();\r
+ this.resourceTable = new ResourceTableSmall(this, ints, RESOURCE_TABLE_OFFSET, longs);\r
+ this.foreignTable = new ForeignTableSmall(this, headerTable, FOREIGN_TABLE_OFFSET, longs);\r
+ this.predicateTable = new PredicateTable(this, ints, PREDICATE_TABLE_OFFSET, ints);\r
+ this.objectTable = new ObjectTable(this, ints, OBJECT_TABLE_OFFSET, ints);\r
+ this.valueTable = new ValueTableSmall(this, ints, VALUE_TABLE_OFFSET, bytes);\r
+ this.completeTable = new CompleteTableSmall(this, headerTable, COMPLETE_TABLE_OFFSET, ints);\r
+ this.clusterMap = new ClusterMapSmall(this, foreignTable);\r
+ this.clusterSupport = support;\r
+ this.clusterBits = ClusterTraitsBase.getClusterBits(clusterKey);\r
+ this.importance = clusterTable.timeCounter();\r
+ clusterTable.markImmutable(this, getImmutable());\r
+ }\r
+ void analyse() {\r
+ System.out.println("Cluster " + clusterId);\r
+ System.out.println("-size:" + getUsedSpace());\r
+ System.out.println(" -rt:" + (resourceTable.getTableCapacity() * 8 + 8));\r
+ System.out.println(" -ft:" + foreignTable.getTableCapacity() * 8);\r
+ System.out.println(" -pt:" + predicateTable.getTableCapacity() * 4);\r
+ System.out.println(" -ot:" + objectTable.getTableCapacity() * 4);\r
+ System.out.println(" -ct:" + completeTable.getTableCapacity() * 4);\r
+ System.out.println(" -vt:" + valueTable.getTableCapacity());\r
+\r
+ System.out.println("-resourceTable:");\r
+ System.out.println(" -resourceCount=" + resourceTable.getResourceCount());\r
+ System.out.println(" -size=" + resourceTable.getTableSize());\r
+ System.out.println(" -capacity=" + resourceTable.getTableCapacity());\r
+ System.out.println(" -count=" + resourceTable.getTableCount());\r
+ System.out.println(" -size=" + resourceTable.getTableSize());\r
+ //resourceTable.analyse();\r
+ }\r
+ public void checkDirectReference(int dr)\r
+ throws DatabaseException {\r
+ if (deleted) return;\r
+ if (!ClusterTraits.statementIndexIsDirect(dr))\r
+ throw new ValidationException("Reference is not direct. Reference=" + dr);\r
+ if (ClusterTraits.isFlat(dr))\r
+ throw new ValidationException("Reference is flat. Reference=" + dr);\r
+ if (ClusterTraits.isLocal(dr)) {\r
+ if (dr < 1 || dr > resourceTable.getUsedSize())\r
+ throw new ValidationException("Illegal local reference. Reference=" + dr);\r
+ } else {\r
+ int fi = ClusterTraits.getForeignIndexFromReference(dr);\r
+ int ri = ClusterTraits.getResourceIndexFromForeignReference(dr);\r
+ if (fi < 1 || fi > foreignTable.getUsedSize())\r
+ throw new ValidationException("Illegal foreign reference. Reference=" + dr + " foreign index=" + fi);\r
+ if (ri < 1 || ri > ClusterTraits.getMaxNumberOfResources())\r
+ throw new ValidationException("Illegal foreign reference. Reference=" + dr + " resource index=" + ri);\r
+ }\r
+ }\r
+ public void checkPredicateIndex(int pi)\r
+ throws DatabaseException {\r
+ if (deleted) return;\r
+ // predicateTable.checkPredicateSetIndex(this, pi);\r
+ }\r
+ public void checkObjectSetReference(int or)\r
+ throws DatabaseException {\r
+ if (deleted) return;\r
+ if (ClusterTraits.statementIndexIsDirect(or))\r
+ throw new ValidationException("Illegal object set reference. Reference=" + or);\r
+ int oi = ClusterTraits.statementIndexGet(or);\r
+ this.objectTable.checkObjectSetIndex(this, oi);\r
+ }\r
+\r
+ public void checkValueInit()\r
+ throws DatabaseException {\r
+ valueTable.checkValueInit();\r
+ }\r
+ public void checkValue(int capacity, int index)\r
+ throws DatabaseException {\r
+ valueTable.checkValue(capacity, index);\r
+ }\r
+ public void checkValueFini()\r
+ throws DatabaseException {\r
+ valueTable.checkValueFini();\r
+ }\r
+ public void checkForeingIndex(int fi)\r
+ throws DatabaseException {\r
+ if (deleted) return;\r
+ if (fi<1 || fi > foreignTable.getUsedSize())\r
+ throw new ValidationException("Illegal foreign index=" + fi);\r
+ }\r
+ public void checkCompleteSetReference(int cr)\r
+ throws DatabaseException {\r
+ if (!ClusterTraits.completeReferenceIsMultiple(cr))\r
+ throw new ValidationException("Illegal complete set reference. Reference=" + cr);\r
+ int ci = cr;\r
+ this.completeTable.checkCompleteSetIndex(this, ci);\r
+ }\r
+ public void check()\r
+ throws DatabaseException {\r
+ if (deleted) return;\r
+// this.completeTable.check(this);\r
+// this.objectTable.check(this);\r
+// // Must be after object table check.\r
+// this.predicateTable.check(this);\r
+// this.resourceTable.check(this);\r
+ }\r
+ @Override\r
+ public CompleteTypeEnum getCompleteType(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return CompleteTypeEnum.NotComplete;\r
+ final int resourceRef = getLocalReference(resourceKey);\r
+ CompleteTypeEnum ct = resourceTable.getCompleteType(resourceRef);\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.getCompleteType rk=" + resourceKey + " ct=" + ct);\r
+ return ct;\r
+ }\r
+\r
+ @Override\r
+ public int getCompleteObjectKey(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return 0;\r
+ final int resourceIndexOld = getLocalReference(resourceKey);\r
+ short completeRef = resourceTable.getCompleteObjectRef(resourceIndexOld);\r
+ int clusterIndex;\r
+ int resourceIndex;\r
+ if (0 == completeRef)\r
+ throw new DatabaseException("Resource's complete object refernce is null. Resource key=" + resourceKey + ".");\r
+ ClusterI.CompleteTypeEnum completeType = resourceTable.getCompleteType(resourceIndexOld);\r
+ if (completeType == ClusterI.CompleteTypeEnum.NotComplete)\r
+ throw new DatabaseException("Resource has multiple complete objects. Resource key=" + resourceKey + ".");\r
+ if (ClusterTraitsSmall.resourceRefIsLocal(completeRef)) {\r
+ clusterIndex = clusterKey;\r
+ resourceIndex = completeRef;\r
+ } else { // Resource has one complete statement.\r
+ ResourceUID resourceUID = clusterMap.getForeignResourceUID(completeRef);\r
+ ClusterI c = support.getClusterByClusterUIDOrMake(resourceUID.asCID());\r
+ clusterIndex = c.getClusterKey();\r
+ resourceIndex = resourceUID.getIndex();\r
+ }\r
+ int key = ClusterTraits.createResourceKey(clusterIndex, resourceIndex);\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.complete object rk=" + resourceKey + " ck=" + key);\r
+ return key;\r
+ }\r
+\r
+ @Override\r
+ public boolean isComplete(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return false;\r
+ final int resourceRef = getLocalReference(resourceKey);\r
+ final ClusterI.CompleteTypeEnum completeType = resourceTable.getCompleteType(resourceRef);\r
+ boolean complete = completeType != ClusterI.CompleteTypeEnum.NotComplete;\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.key=" + resourceKey + " isComplete=" + complete);\r
+ return complete;\r
+ }\r
+ public int getSingleObject(int resourceKey, int predicateKey, int objectIndex, ClusterSupport support) throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.getSingleObject: rk=" + resourceKey + " pk=" + predicateKey);\r
+ if (deleted) return 0;\r
+ if (0 == objectIndex) {\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);\r
+ final short pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);\r
+ return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);\r
+ }\r
+ return objectTable.getSingleObject(objectIndex, support, this);\r
+ }\r
+\r
+ public void forObjects(ReadGraphImpl graph, int resourceKey, int predicateKey, int objectIndex, AsyncMultiProcedure<Resource> procedure,\r
+ ClusterSupport support) throws DatabaseException {\r
+ if (deleted) return;\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forObjects1: rk=" + resourceKey + " pk=" + predicateKey);\r
+ if (0 == objectIndex) {\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final int pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);\r
+ resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ objectTable.foreachObject(graph, objectIndex, procedure, this);\r
+ }\r
+\r
+ public <C> void forObjects(ReadGraphImpl graph, int resourceKey, int predicateKey, int objectIndex, C context, AsyncContextMultiProcedure<C, Resource> procedure,\r
+ ClusterSupport support) throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forObjects1: rk=" + resourceKey + " pk=" + predicateKey);\r
+ if (deleted) return;\r
+ if (0 == objectIndex) {\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final int pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);\r
+ resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ objectTable.foreachObject(graph, objectIndex, context, procedure, this);\r
+ }\r
+\r
+ @Override\r
+ public <Context> boolean forObjects(int resourceKey, int predicateKey, int objectIndex, ObjectProcedure<Context> procedure,\r
+ Context context, ClusterSupport support) throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forObjects2: rk=" + resourceKey + " pk=" + predicateKey);\r
+ if (deleted) return false;\r
+ if (0 == objectIndex) {\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final short pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);\r
+ return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);\r
+ }\r
+ return objectTable.foreachObject(objectIndex, procedure, context, support, this);\r
+ }\r
+\r
+ @Override\r
+ public int getSingleObject(int resourceKey, int predicateKey, ClusterSupport support) throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey);\r
+ if (deleted) return 0;\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final short pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ final int completeType = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);\r
+ final ClusterI.CompleteTypeEnum pCompleteType = CompleteTypeEnum.make(completeType);\r
+ if (completeType > 0)\r
+ return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);\r
+ final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;\r
+ if (0 == predicateIndex) // All relevant data is in resource table.\r
+ return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);\r
+ int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);\r
+ return getSingleObject(resourceKey, predicateKey, objectIndex, support);\r
+ }\r
+\r
+ @Override\r
+ public <T> int getSingleObject(int resourceKey, ForPossibleRelatedValueProcedure<T> procedure, ClusterSupport support) throws DatabaseException {\r
+ if (deleted) return 0;\r
+ final short resourceIndex = (short)ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final int predicateKey = procedure.predicateKey;\r
+ int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);\r
+ short pRef = 0;\r
+ if(procedure.clusterKey[0] == clusterKey) {\r
+ pRef = (short)procedure.predicateReference[0];\r
+ } else {\r
+ pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ procedure.clusterKey[0] = clusterKey;\r
+ procedure.predicateReference[0] = pRef;\r
+ }\r
+\r
+ final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;\r
+ if (CompleteTypeEnum.NotComplete != pCompleteType)\r
+ return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);\r
+ final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;\r
+ if (0 == predicateIndex) // All relevant data is in resource table.\r
+ return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);\r
+ int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);\r
+ return getSingleObject(resourceKey, predicateKey, objectIndex, support);\r
+ }\r
+\r
+ @Override\r
+ public <C, T> int getSingleObject(int resourceKey, ForPossibleRelatedValueContextProcedure<C, T> procedure, ClusterSupport support) throws DatabaseException {\r
+ if (deleted) return 0;\r
+ final short resourceIndex = (short)ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final int predicateKey = procedure.predicateKey;\r
+ int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);\r
+ short pRef = 0;\r
+ if(procedure.clusterKey[0] == clusterKey) {\r
+ pRef = (short)procedure.predicateReference[0];\r
+ } else {\r
+ pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ procedure.clusterKey[0] = clusterKey;\r
+ procedure.predicateReference[0] = pRef;\r
+ }\r
+ final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;\r
+ if (CompleteTypeEnum.NotComplete != pCompleteType)\r
+ return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);\r
+ final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;\r
+ if (0 == predicateIndex) // All relevant data is in resource table.\r
+ return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);\r
+ int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);\r
+ return getSingleObject(resourceKey, predicateKey, objectIndex, support);\r
+ }\r
+\r
+ @Override\r
+ public void forObjects(ReadGraphImpl graph, int resourceKey,\r
+ int predicateKey, AsyncMultiProcedure<Resource> procedure) throws DatabaseException {\r
+ if (deleted) return;\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forObjects3: rk=" + resourceKey + " pk=" + predicateKey);\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final int pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ final int completeType = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);\r
+ final ClusterI.CompleteTypeEnum pCompleteType = CompleteTypeEnum.make(completeType);\r
+ if (completeType > 0) {\r
+ resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;\r
+ if (0 == predicateIndex) {\r
+ resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);\r
+ forObjects(graph, resourceKey, predicateKey, objectIndex, procedure, support);\r
+ }\r
+\r
+ public void forObjects(ReadGraphImpl graph, int resourceKey, ForEachObjectProcedure procedure) throws DatabaseException {\r
+ if (deleted) return;\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final int predicateKey = procedure.predicateKey;\r
+ int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);\r
+ int pRef = 0;\r
+ if(procedure.clusterKey[0] == clusterKey) {\r
+ pRef = procedure.predicateReference[0];\r
+ } else {\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ procedure.clusterKey[0] = clusterKey;\r
+ procedure.predicateReference[0] = pRef;\r
+ }\r
+ final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;\r
+ if (0 == predicateIndex) {\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ int hashBase = predicateIndex + predicateTable.offset;\r
+ if (predicateTable.table[hashBase-1] < 0) {\r
+ int objectIndex = TableIntArraySet2.get(predicateTable.table, hashBase, pRef & 0xFFFF);\r
+ //int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ forObjects(graph, resourceKey, predicateKey, objectIndex, procedure, support);\r
+ } else {\r
+ procedure.finished(graph);\r
+// graph.dec();\r
+ }\r
+}\r
+\r
+ public <C> void forObjects(ReadGraphImpl graph, int resourceKey, C context, ForEachObjectContextProcedure<C> procedure) throws DatabaseException {\r
+ if (deleted) return;\r
+ final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final int predicateKey = procedure.predicateKey;\r
+ int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);\r
+ int pRef = 0;\r
+ if(procedure.clusterKey[0] == clusterKey) {\r
+ pRef = procedure.predicateReference[0];\r
+ } else {\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ procedure.clusterKey[0] = clusterKey;\r
+ procedure.predicateReference[0] = pRef;\r
+ }\r
+\r
+ final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;\r
+ if (0 == predicateIndex) {\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);\r
+ return;\r
+ }\r
+ int hashBase = predicateIndex + predicateTable.offset;\r
+ if(predicateTable.table[hashBase-1] < 0) {\r
+ int objectIndex = TableIntArraySet2.get(predicateTable.table, hashBase, pRef & 0xFFFF);\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ forObjects(graph, resourceKey, predicateKey, objectIndex, context, procedure, support);\r
+ } else {\r
+ int objectIndex = TableIntSet2.get(predicateTable.table, hashBase, pRef & 0xFFFF);\r
+ SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
+ ClusterSupport support = session.clusterTranslator;\r
+ forObjects(graph, resourceKey, predicateKey, objectIndex, context, procedure, support);\r
+ }\r
+ }\r
+ @Override\r
+ public <Context> boolean forObjects(int resourceKey, int predicateKey,\r
+ ObjectProcedure<Context> procedure, Context context, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forObjects4: rk=" + resourceKey + " pk=" + predicateKey);\r
+ if (deleted) return false;\r
+ final short resourceIndex = (short)ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);\r
+ final short pRef = getInternalReferenceOrZero2(predicateKey, support);\r
+ final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);\r
+ // PredicateType is complete i.e. all relevant data is in resource table.\r
+ if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forObjects: complete type was " + pCompleteType + " cluster=" + getClusterUID());\r
+ return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);\r
+ }\r
+ final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);\r
+ if (0 == predicateIndex) { // All relevant data is in resource table.\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forObjects: no predicate table " + pCompleteType);\r
+ return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);\r
+ }\r
+ int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);\r
+ return forObjects(resourceKey, predicateKey, objectIndex, procedure, context, support);\r
+ }\r
+ @Override\r
+ public <Context> boolean forPredicates(int resourceKey,\r
+ PredicateProcedure<Context> procedure, Context context, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.forPredicates: rk=" + resourceKey );\r
+ if (deleted) return false;\r
+ final int resourceIndex = getLocalReference(resourceKey);\r
+ final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);\r
+ if (0 == predicateIndex)\r
+ return resourceTable.foreachPredicate(resourceIndex,\r
+ procedure, context, support, this, completeTable);\r
+ else {\r
+ boolean broken = resourceTable.foreachPredicate(resourceIndex,\r
+ procedure, context, support, this, completeTable);\r
+ if (broken)\r
+ return true;\r
+ }\r
+ return predicateTable.foreachPredicate(predicateIndex,\r
+ procedure, context, support, this);\r
+ }\r
+ @Override\r
+ public ClusterI addRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("add rk=" + sResourceKey + " pk=" + pResourceKey + " ok=" + oResourceKey);\r
+ if (deleted) return null;\r
+ if(proxy) {\r
+ ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);\r
+ return cluster.addRelation(sResourceKey, pResourceKey, oResourceKey, support);\r
+ }\r
+\r
+ // check();\r
+ boolean ret;\r
+ try {\r
+ short sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.ADD_OPERATION);\r
+ short pri = getReferenceOrCreateIfForeign(pResourceKey, support, ClusterStream.NULL_OPERATION);\r
+ short ori = getReferenceOrCreateIfForeign(oResourceKey, support, ClusterStream.NULL_OPERATION);\r
+ ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);\r
+ ret = addRelationInternal(sri, pri, ori, completeType);\r
+ calculateModifiedId();\r
+ } catch (OutOfSpaceException e) {\r
+ boolean streamOff = support.getStreamOff();\r
+ if (!streamOff) {\r
+ support.cancelStatement(this);\r
+ support.setStreamOff(true);\r
+ }\r
+ ClusterI cluster = toBig(support);\r
+ if (!streamOff)\r
+ support.setStreamOff(false);\r
+ ClusterI cluster2 = cluster.addRelation(sResourceKey, pResourceKey, oResourceKey, support);\r
+ if (cluster != cluster2)\r
+ throw new DatabaseException("Internal error. Contact application support.");\r
+ return cluster;\r
+ }\r
+// check();\r
+ if (ret) {\r
+ support.addStatement(this);\r
+ return this;\r
+ } else {\r
+ support.cancelStatement(this);\r
+ return null;\r
+ }\r
+ }\r
+ @Override\r
+ public boolean removeRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return false;\r
+ short sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.REMOVE_OPERATION);\r
+ short pri = getInternalReferenceOrZeroAnd(pResourceKey, support, ClusterStream.NULL_OPERATION);\r
+ short ori = getInternalReferenceOrZeroAnd(oResourceKey, support, ClusterStream.NULL_OPERATION);\r
+ boolean ret = false;\r
+ if (0 != pri && 0 != ori) {\r
+ ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);\r
+ ret = removeRelationInternal(sri, pri, ori, completeType, support);\r
+ calculateModifiedId();\r
+ }\r
+ if (ret)\r
+ support.removeStatement(this);\r
+ else\r
+ support.cancelStatement(this);\r
+ // check();\r
+ return ret;\r
+ }\r
+ @Override\r
+ public void denyRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return;\r
+ short s = checkResourceKeyIsOursAndGetResourceIndexIf(sResourceKey, support);\r
+ ResourceReferenceAndCluster p = checkResourceKeyAndGetResourceIndexIf(pResourceKey, support);\r
+ ResourceReferenceAndCluster o = checkResourceKeyAndGetResourceIndexIf(oResourceKey, support);\r
+ if (0 == s || 0 == p.reference || 0 == o.reference)\r
+ return;\r
+ // check();\r
+ ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);\r
+ boolean ret = removeRelationInternal(s, p.reference, o.reference, completeType, support);\r
+ if (ret) {\r
+ support.addStatementIndex(this, sResourceKey, getClusterUID(), ClusterChange.REMOVE_OPERATION);\r
+ support.addStatementIndex(this, pResourceKey, p.clusterUID, ClusterStream.NULL_OPERATION);\r
+ support.addStatementIndex(this, oResourceKey, o.clusterUID, ClusterStream.NULL_OPERATION);\r
+ support.removeStatement(this);\r
+ }\r
+ calculateModifiedId();\r
+ // check();\r
+ return;\r
+ }\r
+ @Override\r
+ public InputStream getValueStream(int resourceKey, ClusterSupport support) throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.getValue " + resourceKey);\r
+ if (deleted) return null;\r
+ int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);\r
+ try {\r
+ byte[] buffer = resourceTable.getValue(valueTable, resourceIndex);\r
+ if(buffer == null) return null;\r
+ return new ByteArrayInputStream(buffer);\r
+ } catch (ExternalValueException e) {\r
+ return support.getValueStreamEx(resourceIndex, clusterId);\r
+ }\r
+ }\r
+ @Override\r
+ public byte[] getValue(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.getValue " + resourceKey);\r
+ if (deleted) return null;\r
+ int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);\r
+ try {\r
+ return resourceTable.getValue(valueTable, resourceIndex);\r
+ } catch (ExternalValueException e) {\r
+ return support.getValueEx(resourceIndex, clusterId);\r
+ }\r
+ }\r
+ @Override\r
+ public boolean hasValue(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return false;\r
+ int resourceIndex = getLocalReference(resourceKey);\r
+ return resourceTable.hasValue(resourceIndex);\r
+ }\r
+ @Override\r
+ public boolean removeValue(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return false;\r
+ int resourceIndex = getLocalReferenceAnd(resourceKey, support, ClusterChange.DELETE_OPERATION);\r
+ support.removeValue(this);\r
+ calculateModifiedId();\r
+ return resourceTable.removeValue(valueTable, resourceIndex);\r
+ }\r
+ @Override\r
+ public ClusterI setValue(int rResourceId, byte[] value, int length, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return null;\r
+ int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.SET_OPERATION);\r
+ support.setValue(this, getClusterId(), value, length);\r
+ try {\r
+ resourceTable.setValue(valueTable, resourceIndex, value, length);\r
+ calculateModifiedId();\r
+ return this;\r
+ } catch (OutOfSpaceException e) {\r
+ boolean streamOff = support.getStreamOff();\r
+ if (!streamOff)\r
+ support.setStreamOff(true);\r
+ ClusterI cluster = toBig(support);\r
+ cluster.setValue(rResourceId, value, length, support);\r
+ if (!streamOff)\r
+ support.setStreamOff(false);\r
+ return cluster;\r
+ }\r
+ }\r
+ @Override\r
+ public ClusterI modiValueEx(int rResourceId, long voffset, int length, byte[] value, int offset, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return null;\r
+ int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.MODI_OPERATION);\r
+ support.modiValue(this, getClusterId(), voffset, length, value, offset);\r
+ resourceTable.setValueEx(valueTable, resourceIndex);\r
+ calculateModifiedId();\r
+ return this;\r
+ }\r
+ @Override\r
+ public byte[] readValueEx(int rResourceId, long voffset, int length, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return null;\r
+ int resourceIndex = getLocalReference(rResourceId);\r
+ boolean isExternal = resourceTable.isValueEx(valueTable, resourceIndex);\r
+ if (!isExternal)\r
+ throw new DatabaseException("ClusterI.readValue supported only for external value. Resource key=" + rResourceId);\r
+ return support.getValueEx(resourceIndex, getClusterId(), voffset, length);\r
+ }\r
+ @Override\r
+ public long getValueSizeEx(int rResourceId, ClusterSupport support)\r
+ throws DatabaseException, ExternalValueException {\r
+ if (deleted) return 0;\r
+ int resourceIndex = getLocalReference(rResourceId);\r
+ boolean isExternal = resourceTable.isValueEx(valueTable, resourceIndex);\r
+ if (!isExternal)\r
+ throw new ExternalValueException("ClusterI.getValueSizeEx supported only for external value. Resource key=" + rResourceId);\r
+ return support.getValueSizeEx(resourceIndex, getClusterId());\r
+ }\r
+ @Override\r
+ public void setValueEx(int rResourceId)\r
+ throws DatabaseException {\r
+ int resourceIndex = getLocalReference(rResourceId);\r
+ resourceTable.setValueEx(valueTable, resourceIndex);\r
+ }\r
+ @Override\r
+ public int createResource(ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return 0;\r
+ if(proxy) {\r
+ ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);\r
+ return cluster.createResource(support);\r
+ }\r
+\r
+ short resourceIndex = resourceTable.createResource();\r
+ calculateModifiedId();\r
+ if(DebugPolicy.REPORT_RESOURCE_ID_ALLOCATION)\r
+ System.out.println("[RID_ALLOCATION]: ClusterSmall[" + clusterId + "] allocates " + resourceIndex);\r
+ support.createResource(this, resourceIndex, getClusterId());\r
+ return ClusterTraits.createResourceKey(clusterKey, resourceIndex);\r
+ }\r
+ @Override\r
+ public boolean hasResource(int resourceKey, ClusterSupport support) {\r
+ if (deleted) return false;\r
+ int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(resourceKey);\r
+ if (this.clusterKey != clusterKey) // foreign resource\r
+ return false;\r
+ int resourceIndex;\r
+ try {\r
+ resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);\r
+ } catch (DatabaseException e) {\r
+ return false;\r
+ }\r
+ if (resourceIndex > 0 & resourceIndex <= resourceTable.getTableCount())\r
+ return true;\r
+ else\r
+ return false;\r
+ }\r
+ @Override\r
+ public int getNumberOfResources(ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return 0;\r
+ if(proxy) {\r
+ ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);\r
+ return cluster.getNumberOfResources(support);\r
+ }\r
+\r
+ return resourceTable.getUsedSize();\r
+ }\r
+\r
+ public int getNumberOfResources() {\r
+ if (deleted || proxy)\r
+ return 0;\r
+ return resourceTable.getUsedSize();\r
+ }\r
+\r
+ @Override\r
+ public long getUsedSpace() {\r
+ if (deleted) return 0;\r
+ if(isEmpty()) return 0;\r
+ long rt = resourceTable.getTableCapacity() * 8 + 8; // (8 = cluster id)\r
+ long ft = foreignTable.getTableCapacity() * 8;\r
+ long pt = predicateTable.getTableCapacity() * 4;\r
+ long ot = objectTable.getTableCapacity() * 4;\r
+ long ct = completeTable.getTableCapacity() * 4;\r
+ long vt = valueTable.getTableCapacity() * 1;\r
+ long cm = clusterMap.getUsedSpace();\r
+ return rt + ft + pt + ot + ct + vt + cm;\r
+ }\r
+ @Override\r
+ public boolean isEmpty() {\r
+ if (deleted) return true; // Deleted cluster is always empty.\r
+ if(resourceTable == null) return true;\r
+ return resourceTable.getTableCount() == 0;\r
+ }\r
+ @Override\r
+ public void printDebugInfo(String message, ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (deleted) return;\r
+ throw new DatabaseException("Not implemented!");\r
+ }\r
+ private short getInternalReferenceOrZero2(int resourceKey, ClusterSupport support) throws DatabaseException {\r
+ int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);\r
+ if (!ClusterTraitsBase.isCluster(clusterBits, resourceKey)) {\r
+ return clusterMap.getForeignReferenceOrZero(resourceKey);\r
+ } else {\r
+ return (short)resourceIndex;\r
+ }\r
+ }\r
+ private short getInternalReferenceOrZeroAnd(int resourceKey, ClusterSupport support, byte op)\r
+ throws DatabaseException {\r
+ int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);\r
+ int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);\r
+ if (this.clusterKey != clusterKey) { // foreign resource\r
+ ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);\r
+ ClusterUID clusterUID = foreignCluster.getClusterUID();\r
+ short foreignRef = clusterMap.getForeignReferenceOrZero(resourceKey);\r
+ support.addStatementIndex(this, resourceKey, clusterUID, op);\r
+ return foreignRef;\r
+ }\r
+ support.addStatementIndex(this, resourceKey, getClusterUID(), op);\r
+ return (short)resourceIndex;\r
+ }\r
+ private final short getLocalReference(int resourceKey) throws DatabaseException {\r
+ return ClusterTraits.getResourceIndexFromResourceKeyNoThrow(resourceKey);\r
+ }\r
+ private final short getLocalReferenceAnd(int resourceKey, ClusterSupport support, byte op)\r
+ throws DatabaseException {\r
+ short resourceIndex = getLocalReference(resourceKey);\r
+ support.addStatementIndex(this, resourceKey, getClusterUID(), op);\r
+ return resourceIndex;\r
+ }\r
+ private short checkResourceKeyIsOursAndGetResourceIndexIf(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ int clusterShortId = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);\r
+ if (this.clusterKey != clusterShortId)\r
+ return 0;\r
+ int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);\r
+ return (short)resourceIndex;\r
+ }\r
+ private short getReferenceOrCreateIfForeign(int resourceKey, ClusterSupport support, byte op)\r
+ throws DatabaseException {\r
+ int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);\r
+ short resourceIndex = (short)ClusterTraits.getResourceIndexFromResourceKey(resourceKey);\r
+ if (this.clusterKey != clusterKey) {\r
+ ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);\r
+ ClusterUID clusterUID = foreignCluster.getClusterUID();\r
+ support.addStatementIndex(this, resourceKey, clusterUID, op);\r
+ short ref = clusterMap.getForeignReferenceOrCreateByResourceKey(resourceKey, clusterUID);\r
+ return ref;\r
+ }\r
+ support.addStatementIndex(this, resourceKey, getClusterUID(), op);\r
+ return resourceIndex;\r
+ }\r
+ private class ResourceReferenceAndCluster {\r
+ ResourceReferenceAndCluster(short reference, ClusterUID clusterUID) {\r
+ this.reference = reference;\r
+ this.clusterUID = clusterUID;\r
+ }\r
+ public final short reference;\r
+ public final ClusterUID clusterUID;\r
+ }\r
+ private ResourceReferenceAndCluster checkResourceKeyAndGetResourceIndexIf(int resourceKey, ClusterSupport support)\r
+ throws DatabaseException {\r
+ int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);\r
+ short resourceIndex = (short)ClusterTraits.getResourceIndexFromResourceKey(resourceKey);\r
+ if (this.clusterKey != clusterKey) { // foreign resource\r
+ ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);\r
+ ClusterUID clusterUID = foreignCluster.getClusterUID();\r
+ short ref = clusterMap.getForeignReferenceOrZero(resourceKey);\r
+ return new ResourceReferenceAndCluster(ref, clusterUID);\r
+ }\r
+ return new ResourceReferenceAndCluster(resourceIndex, getClusterUID());\r
+ }\r
+\r
+ static long fTime = 0;\r
+ \r
+ int executeIndex = 0;\r
+ long clusterUID1 = 0;\r
+ long clusterUID2 = 0;\r
+\r
+ @Override\r
+ final public int execute(int resourceReference) throws DatabaseException {\r
+ \r
+ if (deleted) return 0;\r
+ short resourceRef = (short)resourceReference;\r
+ int key;\r
+ if (ClusterTraitsSmall.resourceRefIsLocal(resourceRef)) {\r
+ key = clusterBits | resourceRef;\r
+ } else {\r
+ foreignTable.fillResourceUID(ClusterTraitsSmall.resourceRefGetForeignIndex((short)resourceRef), this);\r
+ key = ClusterTraitsBase.createResourceKey(clusterSupport.getClusterKeyByClusterUIDOrMake(clusterUID1, clusterUID2), executeIndex);\r
+ }\r
+ if (DEBUG)\r
+ System.out.println("ClusterSmall.execute key=" + key);\r
+ return key;\r
+ }\r
+\r
+ private boolean addRelationInternal(short sReference, short pReference, short oReference, ClusterI.CompleteTypeEnum completeType)\r
+ throws DatabaseException {\r
+ int predicateIndex = resourceTable.addStatement(sReference, pReference, oReference, predicateTable, objectTable, completeType, completeTable);\r
+ if (0 == predicateIndex)\r
+ return true; // added to resourceTable\r
+ else if (0 > predicateIndex)\r
+ return false; // old complete statemenent\r
+ int newPredicateIndex = predicateTable.addPredicate(predicateIndex, 0xFFFF & pReference, 0xFFFF & oReference, objectTable);\r
+ if (0 == newPredicateIndex)\r
+ return false;\r
+ if (predicateIndex != newPredicateIndex)\r
+ resourceTable.setPredicateIndex(sReference, newPredicateIndex);\r
+ return true;\r
+ }\r
+ private boolean removeRelationInternal(int sResourceIndex, short pResourceIndex,\r
+ short oResourceIndex, ClusterI.CompleteTypeEnum completeType, ClusterSupport support)\r
+ throws DatabaseException {\r
+ int predicateIndex = resourceTable.getPredicateIndex(sResourceIndex);\r
+ if (0 == predicateIndex || ClusterI.CompleteTypeEnum.NotComplete != completeType)\r
+ return resourceTable.removeStatementFromCache(sResourceIndex,\r
+ pResourceIndex, oResourceIndex, completeType, completeTable);\r
+ PredicateTable.Status ret = predicateTable.removePredicate(predicateIndex, 0xFFFF & pResourceIndex, 0xFFFF & oResourceIndex, objectTable);\r
+ switch (ret) {\r
+ case NothingRemoved:\r
+ return false;\r
+ case PredicateRemoved: {\r
+ if (0 == predicateTable.getPredicateSetSize(predicateIndex))\r
+ resourceTable.setPredicateIndex(sResourceIndex, 0);\r
+ // intentionally dropping to next case\r
+ } default:\r
+ break;\r
+ }\r
+ resourceTable.removeStatement(sResourceIndex,\r
+ pResourceIndex, oResourceIndex,\r
+ completeType, completeTable,\r
+ predicateTable, objectTable, support);\r
+ return true;\r
+ }\r
+ @Override\r
+ public void load() {\r
+ if (deleted) return;\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ @Override\r
+ public void load(Callback<DatabaseException> r) {\r
+ if (deleted) return;\r
+ throw new Error("Not supported.");\r
+ }\r
+\r
+ public boolean contains(int resourceKey) {\r
+ if (deleted) return false;\r
+ return ClusterTraitsBase.isCluster(clusterBits, resourceKey);\r
+ }\r
+ @Override\r
+ public void load(final ClusterSupport support, final Runnable callback) {\r
+ if (deleted) return;\r
+ try {\r
+ clusterTable.load2(clusterId, clusterKey);\r
+ callback.run();\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ }\r
+ @Override\r
+ public ClusterI getClusterByResourceKey(int resourceKey,\r
+ ClusterSupport support) {\r
+ if (deleted) return null;\r
+ throw new Error();\r
+ }\r
+ @Override\r
+ public void increaseReferenceCount(int amount) {\r
+ if (deleted) return;\r
+ throw new Error();\r
+ }\r
+ @Override\r
+ public void decreaseReferenceCount(int amount) {\r
+ if (deleted) return;\r
+ throw new Error();\r
+ }\r
+ @Override\r
+ public int getReferenceCount() {\r
+ if (deleted) return 0;\r
+ throw new Error();\r
+ }\r
+ @Override\r
+ public void releaseMemory() {\r
+ }\r
+ @Override\r
+ public void compact() {\r
+ if (deleted) return;\r
+ clusterMap.compact();\r
+ }\r
+ @Override\r
+ public boolean isLoaded() {\r
+ return !proxy || deleted; // Deleted cluster is always loaded.\r
+ }\r
+\r
+ public ClusterImpl tryLoad(SessionImplSocket sessionImpl) throws DatabaseException {\r
+ if (deleted) return this; // Never load deleted cluster.\r
+ return clusterTable.tryLoad(clusterId, clusterKey);\r
+ }\r
+\r
+\r
+ @Override\r
+ public ClusterBig toBig(ClusterSupport support)\r
+ throws DatabaseException {\r
+ if (DEBUG) {\r
+ System.out.println("DEBUG: toBig cluster=" + clusterId);\r
+ new Exception().printStackTrace();\r
+ }\r
+ if (deleted) return null; // Can't convert deleted cluster to big.\r
+ ClusterBig big = new ClusterBig(getClusterUID(), clusterKey, support);\r
+ big.cc = this.cc;\r
+ big.cc.clusterImpl = this;\r
+ resourceTable.toBig(big, support, this);\r
+ big.foreignLookup = this.foreignLookup;\r
+ big.change = this.change;\r
+ this.cc = null;\r
+ this.foreignLookup = null;\r
+ this.change = null;\r
+ return big;\r
+ }\r
+\r
+ @Override\r
+ public ClusterTypeEnum getType() {\r
+ return ClusterTypeEnum.SMALL;\r
+ }\r
+ @Override\r
+ public boolean getImmutable() {\r
+ if (deleted) return false;\r
+ if (null == resourceTable)\r
+ return false;\r
+ int status = resourceTable.getClusterStatus();\r
+ return (status & ClusterStatus.ImmutableMaskSet) == ClusterStatus.ImmutableMaskSet;\r
+ }\r
+ @Override\r
+ public void setImmutable(boolean immutable, ClusterSupport support) {\r
+ if (deleted) return;\r
+ if(resourceTable != null) {\r
+ int status = resourceTable.getClusterStatus();\r
+ if (immutable)\r
+ status |= ClusterStatus.ImmutableMaskSet;\r
+ else\r
+ status &= ClusterStatus.ImmutableMaskClear;\r
+ resourceTable.setClusterStatus(status);\r
+ }\r
+ support.setImmutable(this, immutable);\r
+ }\r
+ @Override\r
+ public boolean getDeleted() {\r
+ if (deleted) return true;\r
+ int status = resourceTable.getClusterStatus();\r
+ return (status & ClusterStatus.DeletedMaskSet) == ClusterStatus.DeletedMaskSet;\r
+ }\r
+ @Override\r
+ public void setDeleted(boolean set, ClusterSupport support) {\r
+ deleted = set;\r
+ if(resourceTable != null) {\r
+ int status = resourceTable.getClusterStatus();\r
+ if (set)\r
+ status |= ClusterStatus.DeletedMaskSet;\r
+ else\r
+ status &= ClusterStatus.DeletedMaskClear;\r
+ resourceTable.setClusterStatus(status);\r
+ }\r
+ if (null != support)\r
+ support.setDeleted(this, set);\r
+ }\r
+ @Override\r
+ public String toString() {\r
+ if (deleted) return "ClusterSmall[" + getClusterId() + " - has been deleted or hasn't been created.]";\r
+ try {\r
+ final TIntHashSet set = new TIntHashSet();\r
+ TIntShortHashMap map = foreignTable.getResourceHashMap();\r
+ map.forEachKey(new TIntProcedure() {\r
+ @Override\r
+ public boolean execute(int value) {\r
+ set.add(value & 0xfffff000);\r
+ return true;\r
+ }\r
+ });\r
+ return "ClusterSmall[" + getClusterId() + " - " + getNumberOfResources() + " - " + foreignTable.getResourceHashMap().size() + " - " + set.size() + "]";\r
+ } catch (Throwable e) {\r
+ return "ClusterSmall[" + getNumberOfResources() + "]";\r
+ }\r
+ }\r
+ @Override\r
+ public Table<?> getPredicateTable() {\r
+ return predicateTable;\r
+ }\r
+ @Override\r
+ public Table<?> getForeignTable() {\r
+ return foreignTable;\r
+ }\r
+ @Override\r
+ public int makeResourceKey(int pRef) throws DatabaseException {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+ @Override\r
+ public Table<?> getCompleteTable() {\r
+ return completeTable;\r
+ }\r
+ @Override\r
+ public Table<?> getValueTable() {\r
+ return valueTable;\r
+ }\r
+ @Override\r
+ public Table<?> getObjectTable() {\r
+ return objectTable;\r
+ }\r
+\r
+}\r
+\r
+class ClusterStatus {\r
+ public static final int ImmutableMaskClear = 0xFFFFFFFE;\r
+ public static final int ImmutableMaskSet = 0x00000001;\r
+ public static final int DeletedMaskClear = 0xFFFFFFFD;\r
+ public static final int DeletedMaskSet = 0x00000002;\r
+}\r