-/*******************************************************************************\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 org.simantics.db.Resource;\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.Procedure;\r
-import org.simantics.db.impl.ClusterSupport;\r
-import org.simantics.db.impl.Modifier;\r
-import org.simantics.db.impl.ResourceImpl;\r
-import org.simantics.db.impl.Table;\r
-import org.simantics.db.impl.TableFactory;\r
-import org.simantics.db.impl.TableIntAllocatorAdapter;\r
-import org.simantics.db.impl.TableSizeListener;\r
-import org.simantics.db.impl.graph.ReadGraphImpl;\r
-import org.simantics.db.procedure.AsyncContextMultiProcedure;\r
-import org.simantics.db.procedure.AsyncMultiProcedure;\r
-import org.simantics.db.procore.cluster.TableIntArraySet.Ints;\r
-\r
-import gnu.trove.map.hash.TIntIntHashMap;\r
-import gnu.trove.procedure.TIntIntProcedure;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public final class ObjectTable extends Table<int[]> {\r
-\r
- final TableIntAllocatorAdapter allocator;\r
- \r
- public ObjectTable(TableSizeListener sizeListener, int[] header, int headerBase) {\r
- super(TableFactory.getIntFactory(), sizeListener, header, headerBase);\r
- allocator = new TableIntAllocatorAdapter(this);\r
- }\r
-\r
- public ObjectTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {\r
- super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);\r
- allocator = new TableIntAllocatorAdapter(this);\r
- }\r
-\r
- final int createObjectSet(int o1, int o2) throws DatabaseException {\r
- if (0 == o1 || o1 == o2)\r
- throw new DatabaseException("Illegal argument to createObejctSet");\r
- int[] obs = new int[2];\r
- obs[0] = o1;\r
- obs[1] = o2;\r
- int hashBase = TableIntArraySet.create(obs, allocator);\r
- return convertRealIndexToTableIndex(hashBase);\r
- }\r
-\r
- final void deleteObjectSet(int objectIndex) throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase)) {\r
- int capacity = TableIntArraySet.getAllocatedSize(getTable(), hashBase);\r
- int elementIndex = objectIndex - TableIntArraySet.HeaderSize;\r
- deleteOldElement(elementIndex, capacity);\r
- } else {\r
- int capacity = TableIntSet.getAllocatedSize(getTable(), hashBase);\r
- int elementIndex = objectIndex - TableIntSet.HeaderSize;\r
- deleteOldElement(elementIndex, capacity);\r
- }\r
- }\r
-\r
- public final int getObjectSetSize(int objectIndex) {\r
- int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase))\r
- return TableIntArraySet.getSize(getTable(), hashBase);\r
- else\r
- return TableIntSet.getSize(getTable(), hashBase);\r
- }\r
-\r
- /**\r
- * @param objectIndex\r
- * @param oResourceIndex\r
- * @return zero if object already in the set else object index of the set\r
- */\r
- final int addObject(int objectIndex, int oResourceIndex) throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);\r
- int newHashBase;\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase)) {\r
- if (TableIntArraySet.getSize(getTable(), hashBase) < 5)\r
- newHashBase = TableIntArraySet.addInt(getTable(), hashBase, oResourceIndex, allocator);\r
- else {\r
- Ints ints = TableIntArraySet.getIntsIfValueNotFound(getTable(), hashBase, oResourceIndex);\r
- if (ints.found)\r
- return 0; // old object, not modified\r
- this.deleteObjectSet(objectIndex);\r
- newHashBase = TableIntSet.create(ints.ints, allocator);\r
- assert(0 != newHashBase);\r
- }\r
- } else\r
- newHashBase = TableIntSet.addInt(getTable(), hashBase, oResourceIndex, allocator);\r
- if (0 == newHashBase)\r
- return 0; // old object, not modified\r
- int ni = convertRealIndexToTableIndex(newHashBase);\r
- return ni;\r
- }\r
-\r
- /**\r
- * @param objectIndex\r
- * @param oResourceIndex\r
- * @return number of objects after removal.\r
- */\r
- final int removeObject(int objectIndex, int oResourceIndex) throws DatabaseException {\r
- if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int pRef = objectIndex;\r
- if (oResourceIndex == pRef) {\r
- return 0;\r
- } else\r
- return 1;\r
- } else\r
- objectIndex = ClusterTraits.statementIndexGet(objectIndex);\r
- int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);\r
- int[] table = getTable();\r
- if (TableIntArraySet.isArraySet(table, hashBase))\r
- return TableIntArraySet.removeInt(table, hashBase, oResourceIndex);\r
- else {\r
- TableIntSet.removeInt(table, hashBase, oResourceIndex);\r
- return TableIntSet.getSize(table, hashBase);\r
- }\r
- }\r
-\r
- final public int getSingleObject(final int objectIndex, final ClusterSupport support, Modifier modifier) throws DatabaseException {\r
-\r
- if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- return modifier.execute(objectIndex);\r
- }\r
- \r
- int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);\r
- final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase))\r
- return TableIntArraySet.getSingleInt(getTable(), hashBase, modifier);\r
- else\r
- return IntHash.getSingleInt(getTable(), hashBase, modifier);\r
- \r
- }\r
-\r
- final public void foreachObject( ReadGraphImpl graph, final int objectIndex, \r
- final AsyncMultiProcedure<Resource> procedure, Modifier modifier) throws DatabaseException {\r
- if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int key = modifier.execute(objectIndex);\r
- procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), key));\r
- procedure.finished(graph);\r
-// graph.dec();\r
- return;\r
- }\r
- int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);\r
- final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase))\r
- TableIntArraySet.foreachInt(getTable(), hashBase, graph, procedure, modifier);\r
- else\r
- IntHash.foreachInt(graph, table, hashBase, procedure, modifier);\r
- }\r
-\r
- final public <C> void foreachObject( ReadGraphImpl graph, final int objectIndex, C context, \r
- final AsyncContextMultiProcedure<C, Resource> procedure, Modifier modifier) throws DatabaseException {\r
- if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int key = modifier.execute(objectIndex);\r
- procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), key));\r
- procedure.finished(graph);\r
-// graph.dec();\r
- return;\r
- }\r
- int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);\r
- final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase))\r
- TableIntArraySet.foreachInt(getTable(), hashBase, graph, context, procedure, modifier);\r
- else\r
- IntHash.foreachInt(graph, table, hashBase, context, procedure, modifier);\r
- }\r
-\r
- final public <Context> boolean foreachObject(final int objectIndex,\r
- final ClusterI.ObjectProcedure<Context> procedure, final Context context, final ClusterSupport support,\r
- final Modifier modifier) throws DatabaseException {\r
- if (ClusterTraits.statementIndexIsDirect(objectIndex)) {\r
- int pRef = objectIndex;\r
- int key;\r
- if (null == modifier)\r
- key = pRef;\r
- else\r
- key = modifier.execute(pRef);\r
- if (procedure.execute(context, key))\r
- return true; // loop broken by procedure\r
- return false; // loop finished\r
- }\r
- int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);\r
- final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);\r
- boolean ret;\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase))\r
- ret = TableIntArraySet.foreachInt(getTable(), hashBase, procedure, context, modifier);\r
- else\r
- ret = TableIntSet.foreachInt(getTable(), hashBase, procedure, context, modifier);\r
- return ret;\r
- }\r
-\r
- private void checkEntry(ClusterBase cluster, int[] table, int index)\r
- throws DatabaseException {\r
- if (!ClusterTraits.statementIndexIsDirect(table[index]))\r
- throw new ValidationException("Illegal ObjectTable entry. Entry=" + table[index] + " index=" + index);\r
- int dr = table[index];\r
- cluster.checkDirectReference(dr);\r
- }\r
- private TIntHashSet checkIndexSet = null;\r
- public final 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]; p<e; p++) {\r
- if (IntHashTrait.isFull(table[p])) \r
- checkEntry(cluster, table, p);\r
- }\r
- } else {\r
- final int size = -table[cap];\r
- assert(size > 0);\r
- checkIndexSet.add(p - ps);\r
- boolean free = false;\r
- for (int e = p + size; p<e; p++) {\r
- if (free)\r
- assert(table[p] == 0);\r
- else if (table[p] == 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
-\r
- public final void checkObjectSetIndex(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 object set index=" + i);\r
- }\r
- public final 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];\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;\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("object 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("object array set capacity " + a + " instance count " + b);\r
- return true;\r
- }\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 foreachObject(setIndex, (ObjectProcedure<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.Resource;
+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.ObjectProcedure;
+import org.simantics.db.impl.ClusterI.Procedure;
+import org.simantics.db.impl.ClusterSupport;
+import org.simantics.db.impl.Modifier;
+import org.simantics.db.impl.ResourceImpl;
+import org.simantics.db.impl.Table;
+import org.simantics.db.impl.TableFactory;
+import org.simantics.db.impl.TableIntAllocatorAdapter;
+import org.simantics.db.impl.TableSizeListener;
+import org.simantics.db.impl.graph.ReadGraphImpl;
+import org.simantics.db.procedure.AsyncContextMultiProcedure;
+import org.simantics.db.procedure.AsyncMultiProcedure;
+import org.simantics.db.procore.cluster.TableIntArraySet.Ints;
+
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.procedure.TIntIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
+public final class ObjectTable extends Table<int[]> {
+
+ final TableIntAllocatorAdapter allocator;
+
+ public ObjectTable(TableSizeListener sizeListener, int[] header, int headerBase) {
+ super(TableFactory.getIntFactory(), sizeListener, header, headerBase);
+ allocator = new TableIntAllocatorAdapter(this);
+ }
+
+ public ObjectTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {
+ super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);
+ allocator = new TableIntAllocatorAdapter(this);
+ }
+
+ final int createObjectSet(int o1, int o2) throws DatabaseException {
+ if (0 == o1 || o1 == o2)
+ throw new DatabaseException("Illegal argument to createObejctSet");
+ int[] obs = new int[2];
+ obs[0] = o1;
+ obs[1] = o2;
+ int hashBase = TableIntArraySet.create(obs, allocator);
+ return convertRealIndexToTableIndex(hashBase);
+ }
+
+ final void deleteObjectSet(int objectIndex) throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);
+ if (TableIntArraySet.isArraySet(getTable(), hashBase)) {
+ int capacity = TableIntArraySet.getAllocatedSize(getTable(), hashBase);
+ int elementIndex = objectIndex - TableIntArraySet.HeaderSize;
+ deleteOldElement(elementIndex, capacity);
+ } else {
+ int capacity = TableIntSet.getAllocatedSize(getTable(), hashBase);
+ int elementIndex = objectIndex - TableIntSet.HeaderSize;
+ deleteOldElement(elementIndex, capacity);
+ }
+ }
+
+ public final int getObjectSetSize(int objectIndex) {
+ int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);
+ if (TableIntArraySet.isArraySet(getTable(), hashBase))
+ return TableIntArraySet.getSize(getTable(), hashBase);
+ else
+ return TableIntSet.getSize(getTable(), hashBase);
+ }
+
+ /**
+ * @param objectIndex
+ * @param oResourceIndex
+ * @return zero if object already in the set else object index of the set
+ */
+ final int addObject(int objectIndex, int oResourceIndex) throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);
+ int newHashBase;
+ if (TableIntArraySet.isArraySet(getTable(), hashBase)) {
+ if (TableIntArraySet.getSize(getTable(), hashBase) < 5)
+ newHashBase = TableIntArraySet.addInt(getTable(), hashBase, oResourceIndex, allocator);
+ else {
+ Ints ints = TableIntArraySet.getIntsIfValueNotFound(getTable(), hashBase, oResourceIndex);
+ if (ints.found)
+ return 0; // old object, not modified
+ this.deleteObjectSet(objectIndex);
+ newHashBase = TableIntSet.create(ints.ints, allocator);
+ assert(0 != newHashBase);
+ }
+ } else
+ newHashBase = TableIntSet.addInt(getTable(), hashBase, oResourceIndex, allocator);
+ if (0 == newHashBase)
+ return 0; // old object, not modified
+ int ni = convertRealIndexToTableIndex(newHashBase);
+ return ni;
+ }
+
+ /**
+ * @param objectIndex
+ * @param oResourceIndex
+ * @return number of objects after removal.
+ */
+ final int removeObject(int objectIndex, int oResourceIndex) throws DatabaseException {
+ if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int pRef = objectIndex;
+ if (oResourceIndex == pRef) {
+ return 0;
+ } else
+ return 1;
+ } else
+ objectIndex = ClusterTraits.statementIndexGet(objectIndex);
+ int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);
+ int[] table = getTable();
+ if (TableIntArraySet.isArraySet(table, hashBase))
+ return TableIntArraySet.removeInt(table, hashBase, oResourceIndex);
+ else {
+ TableIntSet.removeInt(table, hashBase, oResourceIndex);
+ return TableIntSet.getSize(table, hashBase);
+ }
+ }
+
+ final public int getSingleObject(final int objectIndex, final ClusterSupport support, Modifier modifier) throws DatabaseException {
+
+ if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ return modifier.execute(objectIndex);
+ }
+
+ int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);
+ final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);
+ if (TableIntArraySet.isArraySet(getTable(), hashBase))
+ return TableIntArraySet.getSingleInt(getTable(), hashBase, modifier);
+ else
+ return IntHash.getSingleInt(getTable(), hashBase, modifier);
+
+ }
+
+ final public void foreachObject( ReadGraphImpl graph, final int objectIndex,
+ final AsyncMultiProcedure<Resource> procedure, Modifier modifier) throws DatabaseException {
+ if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int key = modifier.execute(objectIndex);
+ procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), key));
+ procedure.finished(graph);
+// graph.dec();
+ return;
+ }
+ int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);
+ final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);
+ if (TableIntArraySet.isArraySet(getTable(), hashBase))
+ TableIntArraySet.foreachInt(getTable(), hashBase, graph, procedure, modifier);
+ else
+ IntHash.foreachInt(graph, table, hashBase, procedure, modifier);
+ }
+
+ final public <C> void foreachObject( ReadGraphImpl graph, final int objectIndex, C context,
+ final AsyncContextMultiProcedure<C, Resource> procedure, Modifier modifier) throws DatabaseException {
+ if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int key = modifier.execute(objectIndex);
+ procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), key));
+ procedure.finished(graph, context);
+// graph.dec();
+ return;
+ }
+ int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);
+ final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);
+ if (TableIntArraySet.isArraySet(getTable(), hashBase))
+ TableIntArraySet.foreachInt(getTable(), hashBase, graph, context, procedure, modifier);
+ else
+ IntHash.foreachInt(graph, table, hashBase, context, procedure, modifier);
+ }
+
+ final public <Context> boolean foreachObject(final int objectIndex,
+ final ClusterI.ObjectProcedure<Context> procedure, final Context context, final ClusterSupport support,
+ final Modifier modifier) throws DatabaseException {
+ if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
+ int pRef = objectIndex;
+ int key;
+ if (null == modifier)
+ key = pRef;
+ else
+ key = modifier.execute(pRef);
+ if (procedure.execute(context, key))
+ return true; // loop broken by procedure
+ return false; // loop finished
+ }
+ int realObjectIndex = ClusterTraits.statementIndexGet(objectIndex);
+ final int hashBase = checkIndexAndGetRealIndex(realObjectIndex, 0);
+ boolean ret;
+ if (TableIntArraySet.isArraySet(getTable(), hashBase))
+ ret = TableIntArraySet.foreachInt(getTable(), hashBase, procedure, context, modifier);
+ else
+ ret = TableIntSet.foreachInt(getTable(), hashBase, procedure, context, modifier);
+ return ret;
+ }
+
+ private void checkEntry(ClusterBase cluster, int[] table, int index)
+ throws DatabaseException {
+ if (!ClusterTraits.statementIndexIsDirect(table[index]))
+ throw new ValidationException("Illegal ObjectTable entry. Entry=" + table[index] + " index=" + index);
+ int dr = table[index];
+ cluster.checkDirectReference(dr);
+ }
+ private TIntHashSet checkIndexSet = null;
+ public final 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]; p<e; p++) {
+ if (IntHashTrait.isFull(table[p]))
+ checkEntry(cluster, table, p);
+ }
+ } else {
+ final int size = -table[cap];
+ assert(size > 0);
+ checkIndexSet.add(p - ps);
+ boolean free = false;
+ for (int e = p + size; p<e; p++) {
+ if (free)
+ assert(table[p] == 0);
+ else if (table[p] == 0)
+ free = true;
+ else
+ checkEntry(cluster, table, p);
+ }
+ }
+ count++;
+ }
+ assert(getHeader().getCount() <= count); // deleted objects are not recognized
+ }
+
+ public final void checkObjectSetIndex(ClusterBase cluster, int i)
+ throws DatabaseException {
+ if (null == checkIndexSet)
+ check(cluster); // builds checkIndexSet
+ if (!checkIndexSet.contains(i-ZERO_SHIFT))
+ throw new ValidationException("Illegal object set index=" + i);
+ }
+ public final 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];
+ 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;
+ }
+ //count++;
+ }
+ // assert(getHeader().getCount() == count);
+ stat.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int a, int b) {
+ System.out.println("object set capacity " + a + " instance count " + b);
+ return true;
+ }
+ });
+ stat2.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int a, int b) {
+ System.out.println("object 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 foreachObject(setIndex, (ObjectProcedure<Context>)procedure, context, support, modifier);
+ }
+}