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%2FClusterBig.java;fp=bundles%2Forg.simantics.db.procore%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fprocore%2Fcluster%2FClusterBig.java;h=48f1b27a258cd084fda8ca7939997ba9b7b7babf;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ClusterBig.java b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ClusterBig.java new file mode 100644 index 000000000..48f1b27a2 --- /dev/null +++ b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ClusterBig.java @@ -0,0 +1,994 @@ +/******************************************************************************* + * 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.ClusterI.PredicateProcedure; +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.impl.query.QueryProcessor; +import org.simantics.db.procedure.AsyncContextMultiProcedure; +import org.simantics.db.procedure.AsyncMultiProcedure; +import org.simantics.db.service.ClusterUID; +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.SessionImplSocket; + +final public class ClusterBig 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; + final private ResourceTable resourceTable; + //final private ResourceTable movedResourceTable; + final private PredicateTable predicateTable; + final private ObjectTable objectTable; + final private ValueTable valueTable; + final private FlatTable flatTable; + final private ForeignTable foreignTable; + final private CompleteTable completeTable; + final private ClusterMap clusterMap; + final private int[] headerTable; + final private ClusterSupport clusterSupport; + public ClusterBig(ClusterUID clusterUID, int clusterKey, ClusterSupport support) { + super(clusterUID, clusterKey, support); + if(DebugPolicy.REPORT_CLUSTER_EVENTS) + new Exception(getClusterUID().toString()).printStackTrace(); + this.headerTable = new int[INT_HEADER_SIZE]; + this.resourceTable = new ResourceTable(this, headerTable, RESOURCE_TABLE_OFFSET); + this.foreignTable = new ForeignTable(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 ValueTable(this, headerTable, VALUE_TABLE_OFFSET); + this.completeTable = new CompleteTable(this, headerTable, COMPLETE_TABLE_OFFSET); + this.flatTable = null; + this.clusterMap = new ClusterMap(foreignTable, flatTable); + this.clusterSupport = support; + this.clusterBits = ClusterTraitsBase.getClusterBits(clusterKey); + this.importance = 0; +// clusterTable.setDirtySizeInBytes(true); + } + protected ClusterBig(long[] longs, int[] ints, byte[] bytes, ClusterSupport support, int clusterKey) + throws DatabaseException { + super(checkValidity(0, longs, ints, bytes), clusterKey, support); + if(DebugPolicy.REPORT_CLUSTER_EVENTS) + new Exception(getClusterUID().toString()).printStackTrace(); + if (ints.length < INT_HEADER_SIZE) + throw new IllegalArgumentException("Too small integer table for cluster."); + this.headerTable = ints; + this.resourceTable = new ResourceTable(this, ints, RESOURCE_TABLE_OFFSET, longs); + this.foreignTable = new ForeignTable(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 ValueTable(this, ints, VALUE_TABLE_OFFSET, bytes); + this.flatTable = null; + this.completeTable = new CompleteTable(this, headerTable, COMPLETE_TABLE_OFFSET, ints); + this.clusterMap = new ClusterMap(foreignTable, flatTable); + 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 (!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 { + predicateTable.checkPredicateSetIndex(this, pi); + } + public void checkObjectSetReference(int or) + throws DatabaseException { + 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 (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 { + 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 { + final int resourceRef = getLocalReference(resourceKey); + int completeRef = resourceTable.getCompleteObjectRef(resourceRef); + CompleteTypeEnum ct = ClusterTraits.completeReferenceGetType(completeRef); + if (DEBUG) + System.out.println("Cluster.getCompleteType rk=" + resourceKey + " ct=" + ct); + int i = ct.getValue(); + switch (i) { + case 0: return CompleteTypeEnum.NotComplete; + case 1: return CompleteTypeEnum.InstanceOf; + case 2: return CompleteTypeEnum.Inherits; + case 3: return CompleteTypeEnum.SubrelationOf; + default: throw new DatabaseException("Illegal complete type enumeration."); + } + } + + @Override + public int getCompleteObjectKey(int resourceKey, ClusterSupport support) + throws DatabaseException { + final int resourceRef = getLocalReference(resourceKey); + int completeRef = resourceTable.getCompleteObjectRef(resourceRef); + int clusterIndex; + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + + ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); + if (completeType == ClusterI.CompleteTypeEnum.NotComplete) + throw new DatabaseException("Resource has multiple complete objects. Resource key=" + resourceKey + "."); + + if (ClusterTraits.completeReferenceIsLocal(completeRef)) { + clusterIndex = clusterKey; + } else { + int foreignIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); +// System.err.println("completeRef=" + completeRef + " foreignIndex=" + foreignIndex ); + ClusterUID clusterUID = foreignTable.getResourceUID(foreignIndex).asCID(); + ClusterI c = support.getClusterByClusterUIDOrMake(clusterUID); + clusterIndex = c.getClusterKey(); + } + int key = ClusterTraits.createResourceKey(clusterIndex, resourceIndex); + if (DEBUG) + System.out.println("Cluster.complete object rk=" + resourceKey + " ck=" + key); + return key; + } + + @Override + public boolean isComplete(int resourceKey, ClusterSupport support) + throws DatabaseException { + final int resourceRef = getLocalReference(resourceKey); + int completeRef = resourceTable.getCompleteObjectRef(resourceRef); + ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); + boolean complete = completeType != ClusterI.CompleteTypeEnum.NotComplete; + if (DEBUG) + System.out.println("Cluster.key=" + resourceKey + " isComplete=" + complete); + return complete; + } + + public int getSingleObject(int resourceKey, int predicateKey, int objectIndex, ClusterSupport support) throws DatabaseException { + if (DEBUG) + System.out.println("Cluster.getSingleObject: rk=" + resourceKey + " pk=" + predicateKey); + if (0 == objectIndex) { + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(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(int resourceKey, int predicateKey, int objectIndex, QueryProcessor processor, ReadGraphImpl graph, AsyncMultiProcedure procedure, + ClusterSupport support) throws DatabaseException { + if (DEBUG) + System.out.println("Cluster.forObjects1: rk=" + resourceKey + " pk=" + predicateKey); + if (0 == objectIndex) { + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(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(int resourceKey, int predicateKey, int objectIndex, QueryProcessor processor, ReadGraphImpl graph, C context, AsyncContextMultiProcedure procedure, + ClusterSupport support) throws DatabaseException { + if (DEBUG) + System.out.println("Cluster.forObjects1: rk=" + resourceKey + " pk=" + predicateKey); + if (0 == objectIndex) { + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(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("Cluster.forObjects2: rk=" + resourceKey + " pk=" + predicateKey); + if (0 == objectIndex) { + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(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("Cluster.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey); + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(predicateKey, support); + final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) + return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this); + final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex); + if (0 == predicateIndex) + return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this); + int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef); + return getSingleObject(resourceKey, predicateKey, objectIndex, support); + } + + @Override + public int getSingleObject(int resourceKey, ForPossibleRelatedValueProcedure procedure, ClusterSupport support) throws DatabaseException { + final int predicateKey = procedure.predicateKey; + if (DEBUG) + System.out.println("Cluster.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey); + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(predicateKey, support); + final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) + return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this); + final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex); + if (0 == predicateIndex) + return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this); + int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef); + return getSingleObject(resourceKey, predicateKey, objectIndex, support); + } + + @Override + public int getSingleObject(int resourceKey, ForPossibleRelatedValueContextProcedure procedure, ClusterSupport support) throws DatabaseException { + final int predicateKey = procedure.predicateKey; + if (DEBUG) + System.out.println("Cluster.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey); + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(predicateKey, support); + final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) + return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this); + final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex); + if (0 == predicateIndex) + return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this); + int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef); + return getSingleObject(resourceKey, predicateKey, objectIndex, support); + } + + @Override + public void forObjects(ReadGraphImpl graph, int resourceKey, + int predicateKey, AsyncMultiProcedure procedure) + throws DatabaseException { + + SessionImplSocket session = (SessionImplSocket)graph.getSession(); + ClusterSupport support = session.clusterTranslator; + + if (DEBUG) + System.out.println("Cluster.forObjects3: rk=" + resourceKey + " pk=" + predicateKey); + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(predicateKey, support); + final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { + resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this); + return; + } + final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex); + if (0 == predicateIndex) { + resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this); + return; + } + int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef); + forObjects(resourceKey, predicateKey, objectIndex, graph.processor, graph, procedure, support); + + } + + @Override + public void forObjects(ReadGraphImpl graph, int resourceKey, ForEachObjectProcedure procedure) throws DatabaseException { + SessionImplSocket session = (SessionImplSocket)graph.getSession(); + ClusterSupport support = session.clusterTranslator; + final int predicateKey = procedure.predicateKey; + if (DEBUG) + System.out.println("Cluster.forObjects3: rk=" + resourceKey + " pk=" + predicateKey); + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(predicateKey, support); + final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { + resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this); + return; + } + final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex); + if (0 == predicateIndex) { + resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this); + return; + } + int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef); + forObjects(resourceKey, predicateKey, objectIndex, graph.processor, graph, procedure, support); + + } + @Override + public void forObjects(ReadGraphImpl graph, int resourceKey, C context, + ForEachObjectContextProcedure procedure) throws DatabaseException { + + SessionImplSocket session = (SessionImplSocket)graph.getSession(); + ClusterSupport support = session.clusterTranslator; + + final int predicateKey = procedure.predicateKey; + + if (DEBUG) + System.out.println("Cluster.forObjects3: rk=" + resourceKey + " pk=" + predicateKey); + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(predicateKey, support); + final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { + resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this); + return; + } + final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex); + if (0 == predicateIndex) { + resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this); + return; + } + int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef); + forObjects(resourceKey, predicateKey, objectIndex, graph.processor, graph, context, procedure, support); + + } + + @Override + public boolean forObjects(int resourceKey, int predicateKey, + ObjectProcedure procedure, Context context, ClusterSupport support) + throws DatabaseException { + if (DEBUG) + System.out.println("Cluster.forObjects4: rk=" + resourceKey + " pk=" + predicateKey); + final int resourceIndex = getLocalReference(resourceKey); + final int pRef = getInternalReferenceOrZero(predicateKey, support); + final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) + return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable); + final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex); + if (0 == predicateIndex) + return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable); + int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef); + 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("Cluster.forPredicates: rk=" + resourceKey); + 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); + int sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.ADD_OPERATION); + int pri = getReferenceOrCreateIfForeign(pResourceKey, support, ClusterStream.NULL_OPERATION); + int ori = getReferenceOrCreateIfForeign(oResourceKey, support, ClusterStream.NULL_OPERATION); + ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey); + boolean ret = addRelationInternal(sri, pri, ori, completeType); +// 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 { +// check(); + int sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.REMOVE_OPERATION); + int pri = getInternalReferenceOrZeroAnd(pResourceKey, support, ClusterStream.NULL_OPERATION); + int 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); + } + 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 { + int sri = checkResourceKeyIsOursAndGetResourceIndexIf(sResourceKey, support); + ResourceIndexAndId p = checkResourceKeyAndGetResourceIndexIf(pResourceKey, support); + ResourceIndexAndId o = checkResourceKeyAndGetResourceIndexIf(oResourceKey, support); + if (0 == sri || 0 == p.index || 0 == o.index) + return; +// check(); + ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey); + boolean ret = removeRelationInternal(sri, 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); + } +// check(); + return; + } + @Override + public InputStream getValueStream(int rResourceId, ClusterSupport support) throws DatabaseException { + if (DEBUG) + System.out.println("ClusterBig.getValue " + rResourceId); + int resourceIndex = getLocalReference(rResourceId); + 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 rResourceId, ClusterSupport support) + throws DatabaseException { + if (DEBUG) + System.out.println("ClusterBig.getValue " + rResourceId); + int resourceIndex = getLocalReference(rResourceId); + try { + return resourceTable.getValue(valueTable, resourceIndex); + } catch (ExternalValueException e) { + return support.getValueEx(resourceIndex, clusterId); + } + } + @Override + public boolean hasValue(int rResourceId, ClusterSupport support) + throws DatabaseException { + int resourceIndex = getLocalReference(rResourceId); + return resourceTable.hasValue(resourceIndex); + } + @Override + public boolean removeValue(int rResourceId, ClusterSupport support) + throws DatabaseException { + int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterChange.DELETE_OPERATION); + support.removeValue(this); + return resourceTable.removeValue(valueTable, resourceIndex); + } + + @Override + public ClusterI setValue(int rResourceId, byte[] value, int length, ClusterSupport support) + throws DatabaseException { + int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.SET_OPERATION); + support.setValue(this, getClusterId(), value, length); + resourceTable.setValue(valueTable, resourceIndex, value, length); + return this; + } + @Override + public ClusterI modiValueEx(int rResourceId, long voffset, int length, byte[] value, int offset, ClusterSupport support) + throws DatabaseException { + int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.MODI_OPERATION); + support.modiValue(this, getClusterId(), voffset, length, value, offset); + resourceTable.setValueEx(valueTable, resourceIndex); + return this; + } + @Override + public byte[] readValueEx(int rResourceId, long voffset, int length, ClusterSupport support) + throws DatabaseException { + 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 resourceKey, ClusterSupport support) + throws DatabaseException, ExternalValueException { + int resourceIndex = getLocalReference(resourceKey); + boolean isExternal = resourceTable.isValueEx(valueTable, resourceIndex); + if (!isExternal) + throw new ExternalValueException("ClusterI.getSize supported only for external value. Resource key=" + resourceKey); + return support.getValueSizeEx(resourceIndex, getClusterId()); + } + public boolean isValueEx(int resourceKey) + throws DatabaseException { + int resourceIndex = getLocalReference(resourceKey); + return resourceTable.isValueEx(valueTable, resourceIndex); + } + @Override + public void setValueEx(int resourceKey) + throws DatabaseException { + int resourceIndex = getLocalReference(resourceKey); + resourceTable.setValueEx(valueTable, resourceIndex); + } + @Override + public int createResource(ClusterSupport support) + throws DatabaseException { + short resourceIndex = resourceTable.createResource(); + + if(DebugPolicy.REPORT_RESOURCE_ID_ALLOCATION) + System.out.println("[RID_ALLOCATION]: ClusterBig[" + clusterId + "] allocates " + resourceIndex); + + support.createResource(this, resourceIndex, clusterId); + return ClusterTraits.createResourceKey(clusterKey, resourceIndex); + } + @Override + public boolean hasResource(int resourceKey, ClusterSupport support) { + 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) { + return resourceTable.getUsedSize(); + } + @Override + public long getUsedSpace() { + 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; +// System.out.println("resource table " + rt); +// System.out.println("foreign table (non flat cluster table) " + ft); +// System.out.println("predicate table " + pt); +// long pt2 = getRealSizeOfPredicateTable() * 4; +// System.out.println("predicate table real size " + pt2); +// System.out.println("object table " + ot); +// long ot2 = getRealSizeOfObjectTable() * 4; +// System.out.println("object table real size " + ot2); +// System.out.println("value table " + vt); + } + int getRealSizeOfPredicateTable() throws DatabaseException { + SizeOfPredicateTable proc = new SizeOfPredicateTable(resourceTable, predicateTable); + resourceTable.foreachResource(proc, 0, null, null); + return proc.getSize(); + } + int getRealSizeOfObjectTable() throws DatabaseException { + SizeOfObjectTable proc = new SizeOfObjectTable(resourceTable, predicateTable, objectTable); + resourceTable.foreachResource(proc, 0, null, null); + return proc.getSize(); + } + @Override + public boolean isEmpty() { + return resourceTable.getTableCount() == 0; + } + @Override + public void printDebugInfo(String message, ClusterSupport support) + throws DatabaseException { + predicateTable.printDebugInfo(); + objectTable.printDebugInfo(); + ClusterPrintDebugInfo proc = new ClusterPrintDebugInfo(this + , resourceTable, predicateTable, support, objectTable); + resourceTable.foreachResource(proc, 0, null, null); + } + private int getInternalReferenceOrZero(int resourceKey, ClusterSupport support) + 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(); + int foreignResourceIndex = clusterMap.getForeignReferenceOrZero(resourceIndex, clusterUID); + return foreignResourceIndex; + } + return resourceIndex; + } + private int 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(); + int foreignResourceIndex = clusterMap.getForeignReferenceOrZero(resourceIndex, clusterUID); + support.addStatementIndex(this, resourceKey, clusterUID, op); + return foreignResourceIndex; + } + support.addStatementIndex(this, resourceKey, getClusterUID(), op); + return resourceIndex; + } + private short getLocalReference(int resourceKey) throws DatabaseException { + return ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey); + } + private int getLocalReferenceAnd(int resourceKey, ClusterSupport support, byte op) + throws DatabaseException { + int resourceIndex = getLocalReference(resourceKey); + support.addStatementIndex(this, resourceKey, getClusterUID(), op); + return resourceIndex; + } + private int checkResourceKeyIsOursAndGetResourceIndexIf(int resourceKey, ClusterSupport support) + throws DatabaseException { + int clusterShortId = ClusterTraits.getClusterKeyFromResourceKey(resourceKey); + if (this.clusterKey != clusterShortId) + return 0; + int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey); + return resourceIndex; + } + private int getReferenceOrCreateIfForeign(int resourceKey, ClusterSupport support, byte op) + throws DatabaseException { + int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey); + int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey); + if (this.clusterKey != clusterKey) { + ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey); + ClusterUID clusterUID = foreignCluster.getClusterUID(); + support.addStatementIndex(this, resourceKey, clusterUID, op); + return clusterMap.getForeignReferenceOrCreateByResourceKey(resourceKey, clusterUID); + } + support.addStatementIndex(this, resourceKey, getClusterUID(), op); + return resourceIndex; + } + private class ResourceIndexAndId { + ResourceIndexAndId(int reference, int index, ClusterUID clusterUID) { + this.reference = reference; + this.index = index; + this.clusterUID = clusterUID; + } + public final int reference; + public final int index; + public final ClusterUID clusterUID; + } + private ResourceIndexAndId checkResourceKeyAndGetResourceIndexIf(int resourceKey, ClusterSupport support) + 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(); + int ref = clusterMap.getForeignReferenceOrCreateByResourceIndex(resourceIndex, clusterUID); + return new ResourceIndexAndId(ref, resourceIndex, clusterUID); + } + return new ResourceIndexAndId(resourceIndex, resourceIndex, getClusterUID()); + } + + @Override + final public int execute(int resourceIndex) throws DatabaseException { + int key; + if(resourceIndex > 0) { + key = clusterBits | resourceIndex; + } else { + ClusterUID clusterUID = clusterMap.getResourceUID(resourceIndex).asCID(); + ClusterI cluster = clusterSupport.getClusterByClusterUIDOrMake(clusterUID); + int foreingResourceIndex = clusterMap.getForeignResourceIndex(resourceIndex); + key = ClusterTraits.createResourceKey(cluster.getClusterKey(), foreingResourceIndex); + } + if (DEBUG) + System.out.println("Cluster.execute key=" + key); + return key; + } + + private boolean addRelationInternal(int sReference, int pReference, int 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, + pReference, oReference, objectTable); + if (0 == newPredicateIndex) + return false; + if (predicateIndex != newPredicateIndex) + resourceTable.setPredicateIndex(sReference, newPredicateIndex); + return true; + } + private boolean removeRelationInternal(int sResourceIndex, int pResourceIndex, + int 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, pResourceIndex, 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, this, support); + return true; + } + @Override + public void load() { + throw new Error("Not supported."); + } + + @Override + public void load(Callback r) { + throw new Error("Not supported."); + } + + public int makeResourceKey(int resourceIndex) throws DatabaseException { + int key = 0; +// if (ClusterTraitsBase.isIllegalResourceIndex(resourceIndex)) +// throw new DatabaseException("Illegal resource key " + resourceIndex); + if (resourceIndex > 0) // local resource + key = ClusterTraits.createResourceKey(clusterKey, resourceIndex); + else { + ClusterUID clusterUID = clusterMap.getResourceUID(resourceIndex).asCID(); + ClusterI cluster = clusterSupport.getClusterByClusterUIDOrMake(clusterUID); + int foreingResourceIndex = clusterMap.getForeignResourceIndex(resourceIndex); + key = ClusterTraits.createResourceKey(cluster.getClusterKey(), foreingResourceIndex); + } + if (0 == key) + throw new DatabaseException("Failed to make resource key from " + resourceIndex); + return key; + } + @Override + public ClusterBig toBig(ClusterSupport support) throws DatabaseException { + throw new Error("Not implemented"); + } + @Override + public void load(ClusterSupport session, Runnable callback) { + throw new Error("Not implemented"); + } + @Override + public ClusterI getClusterByResourceKey(int resourceKey, + ClusterSupport support) { + throw new Error("Not implemented"); + } + @Override + public void increaseReferenceCount(int amount) { + throw new Error("Not implemented"); + } + @Override + + public void decreaseReferenceCount(int amount) { + throw new Error("Not implemented"); + } + @Override + public int getReferenceCount() { + throw new Error("Not implemented"); + } + @Override + public void releaseMemory() { + } + @Override + public void compact() { + clusterMap.compact(); + } + public boolean contains(int resourceKey) { + return ClusterTraitsBase.isCluster(clusterBits, resourceKey); + } + @Override + public ClusterTypeEnum getType() { + return ClusterTypeEnum.BIG; + } + @Override + public boolean getImmutable() { + int status = resourceTable.getClusterStatus(); + return (status & ClusterStatus.ImmutableMaskSet) == ClusterStatus.ImmutableMaskSet; + } + @Override + public void setImmutable(boolean immutable, ClusterSupport support) { + int status = resourceTable.getClusterStatus(); + if (immutable) + status |= ClusterStatus.ImmutableMaskSet; + else + status &= ClusterStatus.ImmutableMaskClear; + resourceTable.setClusterStatus(status); + support.setImmutable(this, immutable); + } + @Override + public boolean getDeleted() { + int status = resourceTable.getClusterStatus(); + return (status & ClusterStatus.DeletedMaskSet) == ClusterStatus.DeletedMaskSet; + } + @Override + public void setDeleted(boolean deleted, ClusterSupport support) { + int status = resourceTable.getClusterStatus(); + if (deleted) + status |= ClusterStatus.DeletedMaskSet; + else + status &= ClusterStatus.DeletedMaskClear; + resourceTable.setClusterStatus(status); + support.setDeleted(this, deleted); + } + @Override + public Table getPredicateTable() { + return predicateTable; + } + @Override + public Table getForeignTable() { + return foreignTable; + } + @Override + public Table getCompleteTable() { + return completeTable; + } + @Override + public Table getValueTable() { + return valueTable; + } + @Override + public Table getObjectTable() { + return objectTable; + } +} + +class SizeOfPredicateTable implements ClusterI.ObjectProcedure { + private final ResourceTable mrResourceTable; + private final PredicateTable mrPredicateTable; + private int size = 0; + SizeOfPredicateTable(ResourceTable resourceTable + , PredicateTable predicateTable) { + mrResourceTable = resourceTable; + mrPredicateTable = predicateTable; + } + @Override + public boolean execute(Integer i, int resourceRef) { + int predicateIndex = mrResourceTable.getPredicateIndex(resourceRef); + if (0 == predicateIndex) + return false; // continue loop + size += mrPredicateTable.getPredicateSetSize(predicateIndex); + return false; // continue loop + } + + public int getSize() { + return size; + } +} + +class SizeOfObjectTable implements ClusterI.ObjectProcedure { + private final ResourceTable mrResourceTable; + private final PredicateTable mrPredicateTable; + private final ObjectTable mrObjectTable; + private int size = 0; + SizeOfObjectTable(ResourceTable resourceTable + , PredicateTable predicateTable, ObjectTable objectTable) { + mrResourceTable = resourceTable; + mrPredicateTable = predicateTable; + mrObjectTable = objectTable; + } + + @Override + public boolean execute(Integer i, int resourceRef) { + int predicateIndex = mrResourceTable.getPredicateIndex(resourceRef); + if (0 == predicateIndex) + return false; // continue loop + ClusterI.PredicateProcedure procedure = new PredicateProcedure() { + @Override + public boolean execute(Object context, int pRef, int oIndex) { + if (ClusterTraits.statementIndexIsDirect(oIndex)) + return false; // no table space reserved, continue looping + int objectIndex; + try { + objectIndex = ClusterTraits.statementIndexGet(oIndex); + size += mrObjectTable.getObjectSetSize(objectIndex); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return false; // continue looping + } + }; + try { + mrPredicateTable.foreachPredicate(predicateIndex, procedure, null, null, null); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return false; // continue loop + } + + public int getSize() { + return size; + } + +} \ No newline at end of file