-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.db.procore.cluster;\r
-\r
-import gnu.trove.map.hash.TIntIntHashMap;\r
-import gnu.trove.procedure.TIntIntProcedure;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.ValidationException;\r
-import org.simantics.db.impl.ClusterBase;\r
-import org.simantics.db.impl.ClusterI;\r
-import org.simantics.db.impl.ClusterI.ObjectProcedure;\r
-import org.simantics.db.impl.ClusterI.PredicateProcedure;\r
-import org.simantics.db.impl.ClusterI.Procedure;\r
-import org.simantics.db.impl.ClusterSupport;\r
-import org.simantics.db.impl.Modifier;\r
-import org.simantics.db.impl.Table;\r
-import org.simantics.db.impl.TableFactory;\r
-import org.simantics.db.impl.TableIntAllocatorAdapter;\r
-import org.simantics.db.impl.TableSizeListener;\r
-import org.simantics.db.procore.cluster.TableIntArraySet2.Tables;\r
-\r
-public final class PredicateTable extends Table<int[]> {\r
- \r
- final TableIntAllocatorAdapter allocator;\r
- \r
- public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase) {\r
- super(TableFactory.getIntFactory(), sizeListener, header, headerBase);\r
- allocator = new TableIntAllocatorAdapter(this);\r
- }\r
- public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {\r
- super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);\r
- allocator = new TableIntAllocatorAdapter(this);\r
- }\r
- int createPredicateSet(int[] ps, int[] os)\r
- throws DatabaseException {\r
- int hashBase = TableIntArraySet2.create(ps, os, allocator);\r
- return convertRealIndexToTableIndex(hashBase);\r
- }\r
- void deletePredicateSet(int predicateIndex) {\r
- int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);\r
- if (TableIntArraySet2.isArraySet(getTable(), hashBase)) {\r
- int capacity = TableIntArraySet2.getAllocatedSize(getTable(), hashBase);\r
- int elementIndex = predicateIndex - TableIntArraySet2.HeaderSize;\r
- deleteOldElement(elementIndex, capacity);\r
- } else {\r
- int capacity = TableIntSet2.getAllocatedSize(getTable(), hashBase);\r
- int elementIndex = predicateIndex - TableIntSet2.HeaderSize;\r
- deleteOldElement(elementIndex, capacity);\r
- }\r
- }\r
- public int getPredicateSetSize(int predicateIndex) {\r
- int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);\r
- if (TableIntArraySet2.isArraySet(getTable(), hashBase))\r
- return TableIntArraySet2.getSize(getTable(), hashBase);\r
- else\r
- return TableIntSet2.getSize(getTable(), hashBase);\r
- }\r
- public int getObjectIndex(int predicateIndex, int pRef) {\r
- int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);\r
- if (TableIntArraySet2.isArraySet(table, hashBase))\r
- return TableIntArraySet2.get(table, hashBase, pRef);\r
- else {\r
- return TableIntSet2.get(table, hashBase, pRef);\r
- }\r
- }\r
- private int addPredicateArray(int predicateIndex, int hashBase, int pReference, int oReference, ObjectTable ot)\r
- throws DatabaseException {\r
- int newHashBase;\r
- int objectIndex = TableIntArraySet2.get(getTable(), hashBase, pReference);\r
- if (0 == objectIndex) {\r
- newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, oReference, allocator);\r
- } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int oRef = objectIndex;\r
- if (oRef == oReference) {\r
- return 0; // old direct object\r
- }\r
- objectIndex = ot.createObjectSet(oRef, oReference);\r
- assert(0 != objectIndex);\r
- int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex);\r
- newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);\r
- } else {\r
- int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference);\r
- if (0 == newObjectIndex)\r
- return 0; // old indirect object\r
- newObjectIndex = ClusterTraits.statementIndexMake(newObjectIndex);\r
- newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);\r
- if (newHashBase == 0)\r
- return hashBase;\r
- }\r
- int TABLE_SIZE = TableIntArraySet2.getSize(getTable(), newHashBase);\r
- if (TABLE_SIZE > 5)\r
- return convertToPredicateSet(predicateIndex, newHashBase);\r
- return newHashBase;\r
- }\r
- private int convertToPredicateSet(int predicateIndex, int hashBase) {\r
- Tables tables = TableIntArraySet2.getInts(getTable(), hashBase);\r
- this.deletePredicateSet(predicateIndex);\r
- int newHashBase = TableIntSet2.create(tables.keys, tables.vals, allocator);\r
- assert(0 != newHashBase);\r
- return newHashBase;\r
- }\r
- private int addPredicateSet(int hashBase, int pReference, int oReference, ObjectTable ot)\r
- throws DatabaseException {\r
- int objectIndex = TableIntSet2.get(getTable(), hashBase, pReference);\r
- int newHashBase;\r
- if (0 == objectIndex) {\r
- newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, oReference, allocator);\r
- } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int oRef = objectIndex;\r
- if (oRef == oReference) {\r
- return 0; // old direct object\r
- }\r
- objectIndex = ot.createObjectSet(oRef, oReference);\r
- assert(0 != objectIndex);\r
- int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex);\r
- newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);\r
- assert(0 != newHashBase);\r
- } else {\r
- int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference);\r
- if (0 == newObjectIndex)\r
- return 0; // old indirect object\r
- int stmIndex = ClusterTraits.statementIndexMake(newObjectIndex);\r
- newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, stmIndex, allocator);\r
- if (newHashBase == 0)\r
- return hashBase; // new object added to old predicate (set)\r
- }\r
- return newHashBase;\r
- }\r
- /**\r
- * @param predicateIndex\r
- * @param pReference\r
- * @return zero if element was not added or predicate index.\r
- * Predicate index will change if new space is allocated.\r
- */\r
- public int addPredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot)\r
- throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);\r
- int newHashBase;\r
- if (TableIntArraySet2.isArraySet(getTable(), hashBase))\r
- newHashBase = addPredicateArray(predicateIndex, hashBase, pReference, oReference, ot);\r
- else\r
- newHashBase = addPredicateSet(hashBase, pReference, oReference, ot);\r
- if (0 == newHashBase)\r
- return 0; // not modified\r
- return convertRealIndexToTableIndex(newHashBase);\r
- }\r
- public enum Status {\r
- NothingRemoved,\r
- ObjectRemoved,\r
- PredicateRemoved;\r
- }\r
- /**\r
- * @param predicateIndex\r
- * @param oResourceIndex\r
- * @return null if nothing was removed. Status if either object or both\r
- * object and predicate were removed. \r
- */\r
- public Status removePredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot)\r
- throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);\r
- int[] table = getTable();\r
- if (TableIntArraySet2.isArraySet(table, hashBase)) {\r
- int objectIndex = TableIntArraySet2.get(table, hashBase, pReference);\r
- if (0 == objectIndex) {\r
- return Status.NothingRemoved;\r
- } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int oRef = objectIndex;\r
- if (oRef != oReference)\r
- return Status.NothingRemoved;\r
- if (TableIntArraySet2.removeInt(table, hashBase, pReference))\r
- return Status.PredicateRemoved;\r
- else\r
- throw new DatabaseException("Internal error during remove.");\r
- } else {\r
- int oIndex = ClusterTraits.statementIndexGet(objectIndex);\r
- int nO = ot.getObjectSetSize(oIndex);\r
- if (nO < 1)\r
- throw new DatabaseException("Illegal object set size="+nO);\r
- int nObject = ot.removeObject(objectIndex, oReference);\r
- if (nObject == 0) {\r
- ot.deleteObjectSet(oIndex);\r
- if (TableIntArraySet2.removeInt(table, hashBase, pReference))\r
- return Status.PredicateRemoved;\r
- else\r
- throw new DatabaseException("Internal error during remove (2).");\r
- } else if (nO == nObject)\r
- return Status.NothingRemoved;\r
- else\r
- return Status.ObjectRemoved;\r
- }\r
- } else {\r
- int objectIndex = TableIntSet2.get(table, hashBase, pReference);\r
- if (0 == objectIndex) {\r
- return Status.NothingRemoved;\r
- } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int oRef = objectIndex;\r
- if (oRef != oReference)\r
- return Status.NothingRemoved;\r
- if (TableIntSet2.removeInt(table, hashBase, pReference))\r
- return Status.PredicateRemoved;\r
- else\r
- throw new DatabaseException("Internal error during remove (3).");\r
- } else {\r
- int oIndex = ClusterTraits.statementIndexGet(objectIndex);\r
- int nO = ot.getObjectSetSize(oIndex);\r
- if (nO < 1)\r
- throw new DatabaseException("Illegal object set size="+nO);\r
- int nObject = ot.removeObject(objectIndex, oReference);\r
- if (nObject == 0) {\r
- ot.deleteObjectSet(oIndex);\r
- if (TableIntSet2.removeInt(table, hashBase, pReference))\r
- return Status.PredicateRemoved;\r
- else\r
- throw new DatabaseException("Internal error during remove (4).");\r
- } else if (nO == nObject)\r
- return Status.NothingRemoved;\r
- else\r
- return Status.ObjectRemoved;\r
- }\r
- }\r
- }\r
- public <Context> boolean foreachPredicate(int predicateIndex\r
- , ClusterI.PredicateProcedure<Context> procedure\r
- , Context context, ClusterSupport support, Modifier modifier)\r
- throws DatabaseException {\r
- final int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);\r
- boolean ret;\r
- if (TableIntArraySet2.isArraySet(getTable(), hashBase))\r
- ret = TableIntArraySet2.foreachInt(getTable(), hashBase, procedure, context, modifier);\r
- else\r
- ret = TableIntSet2.foreachInt(getTable(), hashBase, procedure, context, modifier);\r
- return ret;\r
- }\r
- private void checkEntry(ClusterBase cluster, int[] table, int index)\r
- throws DatabaseException {\r
- assert(ClusterTraits.statementIndexIsDirect(table[index]));\r
- int dr = table[index];\r
- cluster.checkDirectReference(dr);\r
- assert(table[index+1] != 0);\r
- if (ClusterTraits.statementIndexIsDirect(table[index+1])) {\r
- cluster.checkDirectReference(table[index+1]);\r
- } else {\r
- cluster.checkObjectSetReference(table[index+1]);\r
- }\r
- }\r
- private TIntHashSet checkIndexSet = null;\r
- public void check(ClusterBase cluster)\r
- throws DatabaseException {\r
- if (null == checkIndexSet)\r
- checkIndexSet = new TIntHashSet();\r
- else\r
- checkIndexSet.clear();\r
- int count = 0;\r
- int[] table = getTable();\r
- int ps = getHeader().getOffset() + ZERO_SHIFT;\r
- int pe = ps + getTableSize();\r
- for (int p=ps; p<pe;) {\r
- int cap = p++;\r
- if (table[cap] >= 0) {\r
- int use = p++;\r
- int fre = p++;\r
- int max = p++;\r
- assert(table[cap] >= table[use] + table[fre]);\r
- assert(table[max] == table[cap] >> 1);\r
- assert(table[max]+1 >= table[use]);\r
- checkIndexSet.add(p - ps);\r
- for (int e = p + table[cap]*2; p<e; p+=2) {\r
- if (!IntHashTrait.isFull(table[p])) \r
- assert(table[p+1]==0);\r
- else\r
- checkEntry(cluster, table, p);\r
- }\r
- } else {\r
- final int size = -table[cap];\r
- assert(size > 0);\r
- boolean free = false;\r
- checkIndexSet.add(p - ps);\r
- for (int e = p + size*2; p<e; p+=2) {\r
- if (free) {\r
- assert(table[p] == 0);\r
- assert(table[p+1] == 0);\r
- }\r
- else if (table[p] == 0) {\r
- assert(table[p+1] == 0);\r
- free = true;\r
- } else\r
- checkEntry(cluster, table, p);\r
- }\r
- }\r
- count++;\r
- }\r
- assert(getHeader().getCount() <= count); // deleted objects are not recognized\r
- }\r
- public final void checkPredicateSetIndex(ClusterBase cluster, int i)\r
- throws DatabaseException {\r
- if (null == checkIndexSet)\r
- check(cluster); // builds checkIndexSet\r
- if (!checkIndexSet.contains(i-ZERO_SHIFT))\r
- throw new ValidationException("Illegal predicate set index=" + i);\r
- }\r
- public void printDebugInfo() {\r
- //int count = 0;\r
- int[] table = getTable();\r
- int ps = getHeader().getOffset() + ZERO_SHIFT;\r
- int pe = ps + getTableSize();\r
- TIntIntHashMap stat = new TIntIntHashMap();\r
- TIntIntHashMap stat2 = new TIntIntHashMap();\r
- for (int p=ps; p<pe;) {\r
- int cap = p++;\r
- if (table[cap] >= 0) {\r
- int use = p++;\r
- int fre = p++;\r
- int max = p++;\r
- assert(table[cap] >= table[use] + table[fre]);\r
- assert(table[max] == table[cap] >> 1);\r
- p += table[cap]*2;\r
- int val = stat.get(table[use]) + 1;\r
- stat.put(table[use], val);\r
- } else {\r
- final int size = -table[cap];\r
- int val = stat2.get(size) + 1;\r
- stat2.put(size, val);\r
- p += size*2;\r
- }\r
- //count++;\r
- }\r
- //assert(getHeader().getCount() == count);\r
- stat.forEachEntry(new TIntIntProcedure() {\r
- @Override\r
- public boolean execute(int a, int b) {\r
- System.out.println("predicate set capacity " + a + " instance count " + b);\r
- return true;\r
- }\r
- });\r
- stat2.forEachEntry(new TIntIntProcedure() {\r
- @Override\r
- public boolean execute(int a, int b) {\r
- System.out.println("predicate array set capacity " + a + " instance count " + b);\r
- return true;\r
- }\r
- });\r
- }\r
- @Override\r
- public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,\r
- ClusterSupport support, Modifier modifier) throws DatabaseException {\r
- return foreachPredicate(setIndex, (PredicateProcedure<Context>)procedure, context, support, modifier);\r
- }\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.procore.cluster;
+
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.db.impl.ClusterBase;
+import org.simantics.db.impl.ClusterI;
+import org.simantics.db.impl.ClusterI.PredicateProcedure;
+import org.simantics.db.impl.ClusterI.Procedure;
+import org.simantics.db.impl.ClusterSupport;
+import org.simantics.db.impl.Modifier;
+import org.simantics.db.impl.Table;
+import org.simantics.db.impl.TableFactory;
+import org.simantics.db.impl.TableIntAllocatorAdapter;
+import org.simantics.db.impl.TableSizeListener;
+import org.simantics.db.procore.cluster.TableIntArraySet2.Tables;
+
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.procedure.TIntIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
+public final class PredicateTable extends Table<int[]> {
+
+ final TableIntAllocatorAdapter allocator;
+
+ public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase) {
+ super(TableFactory.getIntFactory(), sizeListener, header, headerBase);
+ allocator = new TableIntAllocatorAdapter(this);
+ }
+ public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {
+ super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);
+ allocator = new TableIntAllocatorAdapter(this);
+ }
+ int createPredicateSet(int[] ps, int[] os)
+ throws DatabaseException {
+ int hashBase = TableIntArraySet2.create(ps, os, allocator);
+ return convertRealIndexToTableIndex(hashBase);
+ }
+ void deletePredicateSet(int predicateIndex) {
+ int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
+ if (TableIntArraySet2.isArraySet(getTable(), hashBase)) {
+ int capacity = TableIntArraySet2.getAllocatedSize(getTable(), hashBase);
+ int elementIndex = predicateIndex - TableIntArraySet2.HeaderSize;
+ deleteOldElement(elementIndex, capacity);
+ } else {
+ int capacity = TableIntSet2.getAllocatedSize(getTable(), hashBase);
+ int elementIndex = predicateIndex - TableIntSet2.HeaderSize;
+ deleteOldElement(elementIndex, capacity);
+ }
+ }
+ public int getPredicateSetSize(int predicateIndex) {
+ int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
+ if (TableIntArraySet2.isArraySet(getTable(), hashBase))
+ return TableIntArraySet2.getSize(getTable(), hashBase);
+ else
+ return TableIntSet2.getSize(getTable(), hashBase);
+ }
+ public int getObjectIndex(int predicateIndex, int pRef) {
+ int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
+ if (TableIntArraySet2.isArraySet(table, hashBase))
+ return TableIntArraySet2.get(table, hashBase, pRef);
+ else {
+ return TableIntSet2.get(table, hashBase, pRef);
+ }
+ }
+ private int addPredicateArray(int predicateIndex, int hashBase, int pReference, int oReference, ObjectTable ot)
+ throws DatabaseException {
+ int newHashBase;
+ int objectIndex = TableIntArraySet2.get(getTable(), hashBase, pReference);
+ if (0 == objectIndex) {
+ newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, oReference, allocator);
+ } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int oRef = objectIndex;
+ if (oRef == oReference) {
+ return 0; // old direct object
+ }
+ objectIndex = ot.createObjectSet(oRef, oReference);
+ assert(0 != objectIndex);
+ int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex);
+ newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);
+ } else {
+ int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference);
+ if (0 == newObjectIndex)
+ return 0; // old indirect object
+ newObjectIndex = ClusterTraits.statementIndexMake(newObjectIndex);
+ newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);
+ if (newHashBase == 0)
+ return hashBase;
+ }
+ int TABLE_SIZE = TableIntArraySet2.getSize(getTable(), newHashBase);
+ if (TABLE_SIZE > 5)
+ return convertToPredicateSet(predicateIndex, newHashBase);
+ return newHashBase;
+ }
+ private int convertToPredicateSet(int predicateIndex, int hashBase) {
+ Tables tables = TableIntArraySet2.getInts(getTable(), hashBase);
+ this.deletePredicateSet(predicateIndex);
+ int newHashBase = TableIntSet2.create(tables.keys, tables.vals, allocator);
+ assert(0 != newHashBase);
+ return newHashBase;
+ }
+ private int addPredicateSet(int hashBase, int pReference, int oReference, ObjectTable ot)
+ throws DatabaseException {
+ int objectIndex = TableIntSet2.get(getTable(), hashBase, pReference);
+ int newHashBase;
+ if (0 == objectIndex) {
+ newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, oReference, allocator);
+ } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int oRef = objectIndex;
+ if (oRef == oReference) {
+ return 0; // old direct object
+ }
+ objectIndex = ot.createObjectSet(oRef, oReference);
+ assert(0 != objectIndex);
+ int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex);
+ newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);
+ assert(0 != newHashBase);
+ } else {
+ int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference);
+ if (0 == newObjectIndex)
+ return 0; // old indirect object
+ int stmIndex = ClusterTraits.statementIndexMake(newObjectIndex);
+ newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, stmIndex, allocator);
+ if (newHashBase == 0)
+ return hashBase; // new object added to old predicate (set)
+ }
+ return newHashBase;
+ }
+ /**
+ * @param predicateIndex
+ * @param pReference
+ * @return zero if element was not added or predicate index.
+ * Predicate index will change if new space is allocated.
+ */
+ public int addPredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot)
+ throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
+ int newHashBase;
+ if (TableIntArraySet2.isArraySet(getTable(), hashBase))
+ newHashBase = addPredicateArray(predicateIndex, hashBase, pReference, oReference, ot);
+ else
+ newHashBase = addPredicateSet(hashBase, pReference, oReference, ot);
+ if (0 == newHashBase)
+ return 0; // not modified
+ return convertRealIndexToTableIndex(newHashBase);
+ }
+ public enum Status {
+ NothingRemoved,
+ ObjectRemoved,
+ PredicateRemoved;
+ }
+ /**
+ * @param predicateIndex
+ * @param oResourceIndex
+ * @return null if nothing was removed. Status if either object or both
+ * object and predicate were removed.
+ */
+ public Status removePredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot)
+ throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
+ int[] table = getTable();
+ if (TableIntArraySet2.isArraySet(table, hashBase)) {
+ int objectIndex = TableIntArraySet2.get(table, hashBase, pReference);
+ if (0 == objectIndex) {
+ return Status.NothingRemoved;
+ } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int oRef = objectIndex;
+ if (oRef != oReference)
+ return Status.NothingRemoved;
+ if (TableIntArraySet2.removeInt(table, hashBase, pReference))
+ return Status.PredicateRemoved;
+ else
+ throw new DatabaseException("Internal error during remove.");
+ } else {
+ int oIndex = ClusterTraits.statementIndexGet(objectIndex);
+ int nO = ot.getObjectSetSize(oIndex);
+ if (nO < 1)
+ throw new DatabaseException("Illegal object set size="+nO);
+ int nObject = ot.removeObject(objectIndex, oReference);
+ if (nObject == 0) {
+ ot.deleteObjectSet(oIndex);
+ if (TableIntArraySet2.removeInt(table, hashBase, pReference))
+ return Status.PredicateRemoved;
+ else
+ throw new DatabaseException("Internal error during remove (2).");
+ } else if (nO == nObject)
+ return Status.NothingRemoved;
+ else
+ return Status.ObjectRemoved;
+ }
+ } else {
+ int objectIndex = TableIntSet2.get(table, hashBase, pReference);
+ if (0 == objectIndex) {
+ return Status.NothingRemoved;
+ } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int oRef = objectIndex;
+ if (oRef != oReference)
+ return Status.NothingRemoved;
+ if (TableIntSet2.removeInt(table, hashBase, pReference))
+ return Status.PredicateRemoved;
+ else
+ throw new DatabaseException("Internal error during remove (3).");
+ } else {
+ int oIndex = ClusterTraits.statementIndexGet(objectIndex);
+ int nO = ot.getObjectSetSize(oIndex);
+ if (nO < 1)
+ throw new DatabaseException("Illegal object set size="+nO);
+ int nObject = ot.removeObject(objectIndex, oReference);
+ if (nObject == 0) {
+ ot.deleteObjectSet(oIndex);
+ if (TableIntSet2.removeInt(table, hashBase, pReference))
+ return Status.PredicateRemoved;
+ else
+ throw new DatabaseException("Internal error during remove (4).");
+ } else if (nO == nObject)
+ return Status.NothingRemoved;
+ else
+ return Status.ObjectRemoved;
+ }
+ }
+ }
+ public <Context> boolean foreachPredicate(int predicateIndex
+ , ClusterI.PredicateProcedure<Context> procedure
+ , Context context, ClusterSupport support, Modifier modifier)
+ throws DatabaseException {
+ final int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
+ boolean ret;
+ if (TableIntArraySet2.isArraySet(getTable(), hashBase))
+ ret = TableIntArraySet2.foreachInt(getTable(), hashBase, procedure, context, modifier);
+ else
+ ret = TableIntSet2.foreachInt(getTable(), hashBase, procedure, context, modifier);
+ return ret;
+ }
+ private void checkEntry(ClusterBase cluster, int[] table, int index)
+ throws DatabaseException {
+ assert(ClusterTraits.statementIndexIsDirect(table[index]));
+ int dr = table[index];
+ cluster.checkDirectReference(dr);
+ assert(table[index+1] != 0);
+ if (ClusterTraits.statementIndexIsDirect(table[index+1])) {
+ cluster.checkDirectReference(table[index+1]);
+ } else {
+ cluster.checkObjectSetReference(table[index+1]);
+ }
+ }
+ private TIntHashSet checkIndexSet = null;
+ public void check(ClusterBase cluster)
+ throws DatabaseException {
+ if (null == checkIndexSet)
+ checkIndexSet = new TIntHashSet();
+ else
+ checkIndexSet.clear();
+ int count = 0;
+ int[] table = getTable();
+ int ps = getHeader().getOffset() + ZERO_SHIFT;
+ int pe = ps + getTableSize();
+ for (int p=ps; p<pe;) {
+ int cap = p++;
+ if (table[cap] >= 0) {
+ int use = p++;
+ int fre = p++;
+ int max = p++;
+ assert(table[cap] >= table[use] + table[fre]);
+ assert(table[max] == table[cap] >> 1);
+ assert(table[max]+1 >= table[use]);
+ checkIndexSet.add(p - ps);
+ for (int e = p + table[cap]*2; p<e; p+=2) {
+ if (!IntHashTrait.isFull(table[p]))
+ assert(table[p+1]==0);
+ else
+ checkEntry(cluster, table, p);
+ }
+ } else {
+ final int size = -table[cap];
+ assert(size > 0);
+ boolean free = false;
+ checkIndexSet.add(p - ps);
+ for (int e = p + size*2; p<e; p+=2) {
+ if (free) {
+ assert(table[p] == 0);
+ assert(table[p+1] == 0);
+ }
+ else if (table[p] == 0) {
+ assert(table[p+1] == 0);
+ free = true;
+ } else
+ checkEntry(cluster, table, p);
+ }
+ }
+ count++;
+ }
+ assert(getHeader().getCount() <= count); // deleted objects are not recognized
+ }
+ public final void checkPredicateSetIndex(ClusterBase cluster, int i)
+ throws DatabaseException {
+ if (null == checkIndexSet)
+ check(cluster); // builds checkIndexSet
+ if (!checkIndexSet.contains(i-ZERO_SHIFT))
+ throw new ValidationException("Illegal predicate set index=" + i);
+ }
+ public void printDebugInfo() {
+ //int count = 0;
+ int[] table = getTable();
+ int ps = getHeader().getOffset() + ZERO_SHIFT;
+ int pe = ps + getTableSize();
+ TIntIntHashMap stat = new TIntIntHashMap();
+ TIntIntHashMap stat2 = new TIntIntHashMap();
+ for (int p=ps; p<pe;) {
+ int cap = p++;
+ if (table[cap] >= 0) {
+ int use = p++;
+ int fre = p++;
+ int max = p++;
+ assert(table[cap] >= table[use] + table[fre]);
+ assert(table[max] == table[cap] >> 1);
+ p += table[cap]*2;
+ int val = stat.get(table[use]) + 1;
+ stat.put(table[use], val);
+ } else {
+ final int size = -table[cap];
+ int val = stat2.get(size) + 1;
+ stat2.put(size, val);
+ p += size*2;
+ }
+ //count++;
+ }
+ //assert(getHeader().getCount() == count);
+ stat.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int a, int b) {
+ System.out.println("predicate set capacity " + a + " instance count " + b);
+ return true;
+ }
+ });
+ stat2.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int a, int b) {
+ System.out.println("predicate array set capacity " + a + " instance count " + b);
+ return true;
+ }
+ });
+ }
+ @Override
+ public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
+ ClusterSupport support, Modifier modifier) throws DatabaseException {
+ return foreachPredicate(setIndex, (PredicateProcedure<Context>)procedure, context, support, modifier);
+ }
+}