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