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%2FObjectTable.java;fp=bundles%2Forg.simantics.db.procore%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fprocore%2Fcluster%2FObjectTable.java;h=61d2edabfc8b129e39c14a20133aa3d7208ccbea;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ObjectTable.java b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ObjectTable.java new file mode 100644 index 000000000..61d2edabf --- /dev/null +++ b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ObjectTable.java @@ -0,0 +1,312 @@ +/******************************************************************************* + * 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 { + + 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 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 void foreachObject( ReadGraphImpl graph, final int objectIndex, C context, + final AsyncContextMultiProcedure 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); +// 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 boolean foreachObject(final int objectIndex, + final ClusterI.ObjectProcedure 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 0); + checkIndexSet.add(p - ps); + boolean free = false; + for (int e = p + size; p boolean foreach(int setIndex, Procedure procedure, Context context, + ClusterSupport support, Modifier modifier) throws DatabaseException { + return foreachObject(setIndex, (ObjectProcedure)procedure, context, support, modifier); + } +}