]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ResourceTableSmall.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / ResourceTableSmall.java
index 1edaeec789df4672afa1a4000eae1f3686059823..d72b79aa567d5d582e23e90f132c9c45edee7599 100644 (file)
-/*******************************************************************************\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 java.util.ArrayList;\r
-\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.exception.DatabaseException;\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.ClusterTraitsBase;\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.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.PredicateTable.Status;\r
-\r
-\r
-\r
-public final class ResourceTableSmall extends Table<long[]> {\r
-    public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {\r
-        super(TableFactory.getLongFactory(), sizeListener, header, headerBase);\r
-    }\r
-\r
-    public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {\r
-        super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);\r
-    }\r
-\r
-    public int getUsedSize() {\r
-        return getTableCount();\r
-    }\r
-\r
-    public short createResource() {\r
-        final int INDEX = getTableCount();\r
-        final int SIZE = ResourceElementSmall.getSizeOf();\r
-        int resourceIndex = createNewElement(SIZE);\r
-        assert (0 != resourceIndex);\r
-        final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);\r
-        ResourceElementSmall.construct(getTable(), REAL_INDEX);\r
-        incResourceCount();\r
-        return (short)(INDEX + ZERO_SHIFT);\r
-    }\r
-\r
-    void createResource(int resourceIndex) {\r
-        final int tableCount = getTableCount();\r
-        if (resourceIndex <= tableCount) { // old index\r
-            int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-            if (ResourceElementSmall.isEmpty(getTable(), realIndex))\r
-                return;\r
-        } if (resourceIndex == tableCount+1) {\r
-            createResource();\r
-            return;\r
-        }\r
-        throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);\r
-    }\r
-\r
-    public short getCompleteObjectRef(int resourceIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.getCompleteObjectRef(getTable(), realIndex);\r
-    }\r
-    \r
-    public ClusterI.CompleteTypeEnum getCompleteType(int resourceIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.getCompleteType(getTable(), realIndex);\r
-    }\r
-    \r
-    public int getPredicateIndex(int resourceIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.getPredicateIndex(table, realIndex);\r
-    }\r
-\r
-    public void setPredicateIndex(int resourceIndex, int predicateIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        ResourceElementSmall.setPredicateIndex(getTable(), realIndex, predicateIndex);\r
-    }\r
-\r
-    public byte[] getValue(ValueTableSmall valueTable, int resourceIndex)\r
-    throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.getValue(valueTable, getTable(), realIndex);\r
-    }\r
-//KRAA:\r
-//    char[] getString(ValueTableSmall valueTable, int resourceIndex) {\r
-//        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-//        return ResourceElementSmall.getString(valueTable, getTable(), realIndex);\r
-//    }\r
-\r
-    public boolean hasValue(int resourceIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.hasValue(getTable(), realIndex);\r
-    }\r
-\r
-//    boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {\r
-//        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-//        return ResourceElementSmall.hasValue(valueTable, getTable(), realIndex, value);\r
-//    }\r
-\r
-    public boolean removeValue(ValueTableSmall valueTable, int resourceIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        boolean ret = ResourceElementSmall.removeValue(valueTable, getTable(), realIndex);\r
-//        if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))\r
-//            decResourceCount();\r
-        return ret;\r
-    }\r
-\r
-    public void setValue(ValueTableSmall valueTable, int resourceIndex, byte[] value, int length)\r
-    throws OutOfSpaceException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        ResourceElementSmall.setValue(valueTable, getTable(), realIndex, value, length);\r
-    }\r
-\r
-    public boolean isValueEx(ValueTableSmall valueTable, int resourceIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.isValueEx(valueTable, getTable(), realIndex);\r
-    }\r
-\r
-    public void setValueEx(ValueTableSmall valueTable, int resourceIndex) {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        ResourceElementSmall.setValueEx(valueTable, getTable(), realIndex);\r
-    }\r
-\r
-    static final int RESOURCE_COUNT_INDEX = 0;\r
-    static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.\r
-    static final int CLUSTER_STATUS_INDEX = 2;\r
-\r
-    int incResourceCount() {\r
-        int count = getExtra(RESOURCE_COUNT_INDEX) + 1;\r
-        setExtra(RESOURCE_COUNT_INDEX, count);\r
-        return count;\r
-    }\r
-\r
-//    int decResourceCount() {\r
-//        int count = getExtra(RESOURCE_COUNT_INDEX) - 1;\r
-//        setExtra(RESOURCE_COUNT_INDEX, count);\r
-//        return count;\r
-//    }\r
-\r
-    public int getResourceCount() {\r
-        return getExtra(RESOURCE_COUNT_INDEX);\r
-    }\r
-    public int getClusterStatus() {\r
-        return getExtra(CLUSTER_STATUS_INDEX);\r
-    }\r
-    public void setClusterStatus(int value) {\r
-        setExtra(CLUSTER_STATUS_INDEX, value);\r
-    }\r
-\r
-    <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,\r
-            ClusterSupport support, Modifier modifier) throws DatabaseException {\r
-        final int tsize = getTableSize();\r
-//        final int rsize = getResourceCount();\r
-        final int esize = ResourceElementSmall.getSizeOf();\r
-        //int count = 0;\r
-        int key = ZERO_SHIFT;\r
-        for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {\r
-            if (ResourceElementSmall.isUsed(getTable(), i)) {\r
-                int ref;\r
-                if (null == modifier)\r
-                    ref = key;\r
-                else\r
-                    ref = modifier.execute(key);\r
-                if (procedure.execute(context, ref))\r
-                    return true; // loop was broken by procedure\r
-//                if (rsize == ++count)\r
-//                    return false; // loop finished\r
-            }\r
-        }\r
-        //assert(rsize == count);\r
-        return false; // loop finished\r
-    }\r
-\r
-    public <Context> boolean foreachPredicate(int resourceIndex\r
-            , ClusterI.PredicateProcedure<Context> procedure, Context context\r
-            , ClusterSupport support, Modifier modifier, CompleteTable ct)\r
-    throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.foreachPredicate(getTable(), realIndex\r
-                , procedure, context, support, modifier, ct);\r
-    }\r
-\r
-    public int getSingleObject(int resourceIndex, ClusterSupport support, short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.getSingleObject(table, realIndex, support, pRef, completeType, ct, modifier);\r
-    }\r
-\r
-    public void foreachObject(int resourceIndex, ReadGraphImpl graph,\r
-            AsyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        ResourceElementSmall.foreachObject(table, realIndex, graph, procedure, support,\r
-                pRef, completeType, ct, modifier);\r
-    }\r
-\r
-    public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,\r
-            AsyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        ResourceElementSmall.foreachObject(table, realIndex, graph, context, procedure, support,\r
-                pRef, completeType, ct, modifier);\r
-    }\r
-\r
-    public <Context> boolean foreachObject(int resourceIndex\r
-            , ClusterI.ObjectProcedure<Context> procedure, Context context\r
-            , ClusterSupport support, Modifier modifier,\r
-            short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
-    throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.foreachObject(table, realIndex\r
-                , procedure, context, support, modifier\r
-                , pRef, completeType, ct);\r
-    }\r
-    public int addStatement(int resourceIndex, short pRef, short oRef, PredicateTable pt, ObjectTable ot\r
-            , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
-            throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        return ResourceElementSmall.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, completeType, ct);\r
-    }\r
-\r
-    public boolean removeStatementFromCache(int resourceIndex, short pRef, short oRef,\r
-            ClusterI.CompleteTypeEnum completeType, CompleteTable ct)\r
-    throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        boolean ret = ResourceElementSmall.removeStatement(getTable(), realIndex, pRef, oRef, completeType, ct);\r
-//        if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))\r
-//            decResourceCount();\r
-        return ret;\r
-    }\r
-    \r
-    public void removeStatement(int resourceIndex, short pRef, short oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,\r
-            PredicateTable pt, ObjectTable ot, ClusterSupport support)\r
-            throws DatabaseException {\r
-        int realIndex = checkIndexAndGetRealIndex(resourceIndex);\r
-        boolean removed = ResourceElementSmall.removeStatement(getTable(), realIndex,\r
-                pRef, oRef, pCompleteType, ct);\r
-        if (!removed)\r
-            return;\r
-        int predicateIndex = ResourceElementSmall.getPredicateIndex(getTable(), realIndex);\r
-        if (0 == predicateIndex) {\r
-//            if (!ResourceElementSmall.isUsed(getTable(), realIndex))\r
-//                decResourceCount();\r
-            return;\r
-        } else if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)\r
-            return; // Complete type statements are not kept in statement cache.\r
-        // We have one more statements in predicate table.\r
-        // Here we check if statement cache needs fixing.\r
-        GetStatementsSmall gs = new GetStatementsSmall(ot);\r
-        pt.foreachPredicate(predicateIndex, gs, null, null, null);\r
-        ArrayList<Statement> stms = gs.getStatements();\r
-\r
-        final int SIZE = stms.size();\r
-        if (SIZE < 3) {\r
-            for (int i = 0; i < SIZE; ++i) {\r
-                Statement stm = stms.get(i);\r
-                PredicateTable.Status ret = pt.removePredicate(predicateIndex,\r
-                        stm.pRef, stm.oIndex, ot);\r
-                if (ret == Status.NothingRemoved)\r
-                    throw new DatabaseException("Internal error during statement cache fix (2).");\r
-                assert(stm.pRef < (1<<16));\r
-                assert(stm.oIndex < 1<<16);\r
-                int pi = ResourceElementSmall.addStatement(getTable(), realIndex, (short)stm.pRef, (short)stm.oIndex,\r
-                        pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);\r
-                assert(0 >= pi);\r
-            }\r
-            assert(0 == pt.getPredicateSetSize(predicateIndex));\r
-            ResourceElementSmall.setPredicateIndex(getTable(), realIndex, 0);\r
-        } else {\r
-            for (int i = 0; i < SIZE; ++i) {\r
-                Statement stm = stms.get(i);\r
-                assert(stm.pRef < (1<<16));\r
-                assert(stm.oIndex < 1<<16);\r
-                int pIndex = ResourceElementSmall.addStatement(getTable(), realIndex,\r
-                        (short)stm.pRef, (short)stm.oIndex, pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);\r
-                if (pIndex > 0)\r
-                    return; // cache fixed and full, p and o sets in use\r
-            }\r
-            throw new DatabaseException("Internal error during statement cache fix (3).");\r
-        }\r
-//        if (!ResourceElementSmall.isUsed(getTable(), realIndex))\r
-//            decResourceCount();\r
-    }\r
-\r
-    private int checkIndexAndGetRealIndex(final int resourceIndex) {\r
-        if (ClusterTraitsBase.isIllegalResourceIndex(resourceIndex))\r
-            throw new RuntimeException("Illegal resource index. index=" + resourceIndex + ".");\r
-        if(resourceIndex > getTableCount())\r
-            throw new RuntimeException("Illegal resource index. index=" + resourceIndex + " table count=" + getTableCount());\r
-        final int SIZE = ResourceElementSmall.getSizeOf();\r
-        final int REAL_INDEX = resourceIndex * SIZE - (SIZE - ZERO_SHIFT) + offset;\r
-        return REAL_INDEX;\r
-    }\r
-    void check(ClusterImpl cluster)\r
-    throws DatabaseException {\r
-//        throw new Error("Not implemented.//KRAA:");\r
-    }\r
-\r
-    public void toBig(ClusterBase big, final ClusterSupport support, final ClusterBase small)\r
-    throws DatabaseException {\r
-        int resourceIndex = 1;\r
-        long[] table = getTable();\r
-        int ps = getHeader().getOffset() + ZERO_SHIFT;\r
-        final int TABLE_SIZE = getTableSize();\r
-        int pe = ps + TABLE_SIZE;\r
-        for (int p=ps; p<pe; p+=ResourceElementSmall.getSizeOf(), ++resourceIndex) {\r
-            big.createResource(support);\r
-            int subjectKey = ClusterTraits.createResourceKey(small.clusterKey, resourceIndex);  \r
-            if (!ResourceElementSmall.isUsed(table, p))\r
-                continue;\r
-            int cr = ResourceElementSmall.getCompleteObjectRef(table, p);\r
-            if (0 != cr) {\r
-                ClusterI.CompleteTypeEnum ct = ResourceElementSmall.getCompleteType(table, p);\r
-                if (ClusterI.CompleteTypeEnum.NotComplete != ct) {\r
-                    int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);\r
-                    int oKey = small.getCompleteObjectKey(subjectKey, support);\r
-                    big.addRelation(subjectKey, pKey, oKey, support);\r
-                } else {\r
-                    final class ForeachObject<Context>\r
-                    implements ClusterI.ObjectProcedure<Context> {\r
-                        int sKey;\r
-                        ClusterBase big;\r
-                        public ForeachObject(int sKey, ClusterBase big) {\r
-                            this.sKey = sKey;\r
-                            this.big = big;\r
-                        }\r
-                        @Override\r
-                        public boolean execute(Context context, int completeRef)\r
-                        throws DatabaseException {\r
-                            ClusterI.CompleteTypeEnum ct = ClusterTraitsSmall.completeRefAndTypeGetType(completeRef);\r
-                            int p = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);\r
-                            int o = small.execute(completeRef & 0xFFFF);\r
-                            big.addRelation(sKey, p, o, support);\r
-                            return false; // Continue looping.\r
-                        }\r
-                    }\r
-                    ForeachObject<Object> op = new ForeachObject<Object>(subjectKey, big);\r
-                    small.getCompleteTable().foreach(cr & 0xFFFF, op, null, support, null);\r
-                }\r
-            }\r
-            int pi = ResourceElementSmall.getPredicateIndex(table, p);\r
-            if (0 != pi) {\r
-                ToBigStatements tbs = new ToBigStatements(small, big, support, subjectKey);\r
-                small.getPredicateTable().foreach(pi, tbs, null, null, null);\r
-            } else {\r
-                int p1 = ResourceElementSmall.getStm1Predicate(table, p);\r
-                int o1 = ResourceElementSmall.getStm1Object(table, p);\r
-                if (p1 != 0) {\r
-                    int pk1 = small.execute(p1);\r
-                    int ok1 = small.execute(o1);\r
-                    big.addRelation(subjectKey, pk1, ok1, support);\r
-                    int p2 = ResourceElementSmall.getStm2Predicate(table, p);\r
-                    int o2 = ResourceElementSmall.getStm2Object(table, p);\r
-                    if (p2 != 0) {\r
-                        int pk2 = small.execute(p2);\r
-                        int ok2 = small.execute(o2);\r
-                        big.addRelation(subjectKey, pk2, ok2, support);\r
-                    }\r
-                }\r
-            }\r
-            int valueIndex = ResourceElementSmall.getValueIndex(table, p);\r
-            if (ClusterTraitsSmall.VALUE_INDEX_EX == valueIndex)\r
-              big.setValueEx(subjectKey);\r
-            else {\r
-                byte[] value = ResourceElementSmall.getValue((ValueTableSmall)small.getValueTable(), table, p);\r
-                if (null != value)\r
-                    big.setValue(subjectKey, value, value.length, support);\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
-        throw new UnsupportedOperationException();\r
-    }\r
-}\r
-\r
-class CalculateStatementsSmall\r
-implements ClusterI.PredicateProcedure<CalculateStatements> {\r
-    private ObjectTable         ot;\r
-    private final int           sRef;\r
-\r
-    CalculateStatementsSmall(int sRef, ObjectTable ot) {\r
-        this.sRef = sRef;\r
-        this.ot = ot;\r
-    }\r
-\r
-    @Override\r
-    public boolean execute(CalculateStatements context\r
-            , final int pKey, int oIndex) {\r
-        if (ClusterTraits.statementIndexIsDirect(oIndex))\r
-            return false; // osize = 1\r
-        try {\r
-            oIndex = ClusterTraits.statementIndexGet(oIndex);\r
-        } catch (DatabaseException e) {\r
-            Logger.getDefault().logError("Missing object set for s="\r
-                    + sRef + " p=" + pKey, null);\r
-            return false; // continue looping\r
-        }\r
-        int osize = ot.getObjectSetSize(oIndex);\r
-        if (osize == 3 || osize > 9)\r
-            System.out.println("Resource " + sRef + " predicate " + pKey + " has "\r
-                    + osize + " objects.");\r
-        return true; // break loop\r
-    }\r
-}\r
-\r
-class GetStatementsSmall implements ClusterI.PredicateProcedure<Object>, ClusterI.ObjectProcedure<Integer> {\r
-    private ObjectTable         ot;\r
-    private final ArrayList<Statement> stms = new ArrayList<Statement>(); \r
-    GetStatementsSmall(ObjectTable ot) {\r
-        this.ot = ot;\r
-    }\r
-    ArrayList<Statement> getStatements() {\r
-        return stms;\r
-    }\r
-    @Override\r
-    public boolean execute(Object context, int pRef, int oIndex) {\r
-        try {\r
-            ot.foreachObject(oIndex, this, pRef, null, null);\r
-        } catch (DatabaseException e) {\r
-            e.printStackTrace();\r
-            return false; // continue looping\r
-        }\r
-        if (stms.size() > 2)\r
-            return true; // break loop\r
-        return false; // continue looping\r
-    }\r
-    \r
-    @Override\r
-    public boolean execute(Integer pRef, int oRef) {\r
-        stms.add(new Statement(pRef, oRef));\r
-        if (stms.size() > 2)\r
-            return true; // break loop\r
-        return false; // continue looping\r
-    }\r
-}\r
-\r
-class ToBigStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {\r
-    private ClusterBase small;\r
-    private ClusterBase big;\r
-    private ClusterSupport support;\r
-    private int subjectKey;\r
-    ToBigStatements(ClusterBase small, ClusterBase big, ClusterSupport support, int subjectKey) {\r
-        this.small = small;\r
-        this.big = big;\r
-        this.support = support;\r
-        this.subjectKey = subjectKey;\r
-    }\r
-    @Override\r
-    public boolean execute(Object context, int pRef, int oIndex) {\r
-        try {\r
-            small.getObjectTable().foreach(oIndex, this, pRef, null, null);\r
-        } catch (DatabaseException e) {\r
-            e.printStackTrace();\r
-            return false; // continue looping\r
-        }\r
-        return false; // continue looping\r
-    }\r
-\r
-    @Override\r
-    public boolean execute(Integer pRef, int oRef)\r
-    throws DatabaseException {\r
-        int pKey = small.execute(pRef);\r
-        int oKey = small.execute(oRef);\r
-        big.addRelation(subjectKey, pKey, oKey, support);\r
-        return false; // continue looping\r
-    }\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 java.util.ArrayList;
+
+import org.simantics.db.Resource;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+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.PredicateProcedure;
+import org.simantics.db.impl.ClusterI.Procedure;
+import org.simantics.db.impl.ClusterSupport;
+import org.simantics.db.impl.ClusterTraitsBase;
+import org.simantics.db.impl.Modifier;
+import org.simantics.db.impl.Table;
+import org.simantics.db.impl.TableFactory;
+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.PredicateTable.Status;
+
+
+
+public final class ResourceTableSmall extends Table<long[]> {
+    public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {
+        super(TableFactory.getLongFactory(), sizeListener, header, headerBase);
+    }
+
+    public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {
+        super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);
+    }
+
+    public int getUsedSize() {
+        return getTableCount();
+    }
+
+    public short createResource() {
+        final int INDEX = getTableCount();
+        final int SIZE = ResourceElementSmall.getSizeOf();
+        int resourceIndex = createNewElement(SIZE);
+        assert (0 != resourceIndex);
+        final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);
+        ResourceElementSmall.construct(getTable(), REAL_INDEX);
+        incResourceCount();
+        return (short)(INDEX + ZERO_SHIFT);
+    }
+
+    void createResource(int resourceIndex) {
+        final int tableCount = getTableCount();
+        if (resourceIndex <= tableCount) { // old index
+            int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+            if (ResourceElementSmall.isEmpty(getTable(), realIndex))
+                return;
+        } if (resourceIndex == tableCount+1) {
+            createResource();
+            return;
+        }
+        throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);
+    }
+
+    public short getCompleteObjectRef(int resourceIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.getCompleteObjectRef(getTable(), realIndex);
+    }
+    
+    public ClusterI.CompleteTypeEnum getCompleteType(int resourceIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.getCompleteType(getTable(), realIndex);
+    }
+    
+    public int getPredicateIndex(int resourceIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.getPredicateIndex(table, realIndex);
+    }
+
+    public void setPredicateIndex(int resourceIndex, int predicateIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        ResourceElementSmall.setPredicateIndex(getTable(), realIndex, predicateIndex);
+    }
+
+    public byte[] getValue(ValueTableSmall valueTable, int resourceIndex)
+    throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.getValue(valueTable, getTable(), realIndex);
+    }
+//KRAA:
+//    char[] getString(ValueTableSmall valueTable, int resourceIndex) {
+//        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+//        return ResourceElementSmall.getString(valueTable, getTable(), realIndex);
+//    }
+
+    public boolean hasValue(int resourceIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.hasValue(getTable(), realIndex);
+    }
+
+//    boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {
+//        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+//        return ResourceElementSmall.hasValue(valueTable, getTable(), realIndex, value);
+//    }
+
+    public boolean removeValue(ValueTableSmall valueTable, int resourceIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        boolean ret = ResourceElementSmall.removeValue(valueTable, getTable(), realIndex);
+//        if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
+//            decResourceCount();
+        return ret;
+    }
+
+    public void setValue(ValueTableSmall valueTable, int resourceIndex, byte[] value, int length)
+    throws OutOfSpaceException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        ResourceElementSmall.setValue(valueTable, getTable(), realIndex, value, length);
+    }
+
+    public boolean isValueEx(ValueTableSmall valueTable, int resourceIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.isValueEx(valueTable, getTable(), realIndex);
+    }
+
+    public void setValueEx(ValueTableSmall valueTable, int resourceIndex) {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        ResourceElementSmall.setValueEx(valueTable, getTable(), realIndex);
+    }
+
+    static final int RESOURCE_COUNT_INDEX = 0;
+    static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.
+    static final int CLUSTER_STATUS_INDEX = 2;
+
+    int incResourceCount() {
+        int count = getExtra(RESOURCE_COUNT_INDEX) + 1;
+        setExtra(RESOURCE_COUNT_INDEX, count);
+        return count;
+    }
+
+//    int decResourceCount() {
+//        int count = getExtra(RESOURCE_COUNT_INDEX) - 1;
+//        setExtra(RESOURCE_COUNT_INDEX, count);
+//        return count;
+//    }
+
+    public int getResourceCount() {
+        return getExtra(RESOURCE_COUNT_INDEX);
+    }
+    public int getClusterStatus() {
+        return getExtra(CLUSTER_STATUS_INDEX);
+    }
+    public void setClusterStatus(int value) {
+        setExtra(CLUSTER_STATUS_INDEX, value);
+    }
+
+    <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,
+            ClusterSupport support, Modifier modifier) throws DatabaseException {
+        final int tsize = getTableSize();
+//        final int rsize = getResourceCount();
+        final int esize = ResourceElementSmall.getSizeOf();
+        //int count = 0;
+        int key = ZERO_SHIFT;
+        for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {
+            if (ResourceElementSmall.isUsed(getTable(), i)) {
+                int ref;
+                if (null == modifier)
+                    ref = key;
+                else
+                    ref = modifier.execute(key);
+                if (procedure.execute(context, ref))
+                    return true; // loop was broken by procedure
+//                if (rsize == ++count)
+//                    return false; // loop finished
+            }
+        }
+        //assert(rsize == count);
+        return false; // loop finished
+    }
+
+    public <Context> boolean foreachPredicate(int resourceIndex
+            , ClusterI.PredicateProcedure<Context> procedure, Context context
+            , ClusterSupport support, Modifier modifier, CompleteTable ct)
+    throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.foreachPredicate(getTable(), realIndex
+                , procedure, context, support, modifier, ct);
+    }
+
+    public int getSingleObject(int resourceIndex, ClusterSupport support, short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.getSingleObject(table, realIndex, support, pRef, completeType, ct, modifier);
+    }
+
+    public void foreachObject(int resourceIndex, ReadGraphImpl graph,
+            AsyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        ResourceElementSmall.foreachObject(table, realIndex, graph, procedure, support,
+                pRef, completeType, ct, modifier);
+    }
+
+    public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,
+            AsyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        ResourceElementSmall.foreachObject(table, realIndex, graph, context, procedure, support,
+                pRef, completeType, ct, modifier);
+    }
+
+    public <Context> boolean foreachObject(int resourceIndex
+            , ClusterI.ObjectProcedure<Context> procedure, Context context
+            , ClusterSupport support, Modifier modifier,
+            short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
+    throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.foreachObject(table, realIndex
+                , procedure, context, support, modifier
+                , pRef, completeType, ct);
+    }
+    public int addStatement(int resourceIndex, short pRef, short oRef, PredicateTable pt, ObjectTable ot
+            , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
+            throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        return ResourceElementSmall.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, completeType, ct);
+    }
+
+    public boolean removeStatementFromCache(int resourceIndex, short pRef, short oRef,
+            ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
+    throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        boolean ret = ResourceElementSmall.removeStatement(getTable(), realIndex, pRef, oRef, completeType, ct);
+//        if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
+//            decResourceCount();
+        return ret;
+    }
+    
+    public void removeStatement(int resourceIndex, short pRef, short oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,
+            PredicateTable pt, ObjectTable ot, ClusterSupport support)
+            throws DatabaseException {
+        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
+        boolean removed = ResourceElementSmall.removeStatement(getTable(), realIndex,
+                pRef, oRef, pCompleteType, ct);
+        if (!removed)
+            return;
+        int predicateIndex = ResourceElementSmall.getPredicateIndex(getTable(), realIndex);
+        if (0 == predicateIndex) {
+//            if (!ResourceElementSmall.isUsed(getTable(), realIndex))
+//                decResourceCount();
+            return;
+        } else if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
+            return; // Complete type statements are not kept in statement cache.
+        // We have one more statements in predicate table.
+        // Here we check if statement cache needs fixing.
+        GetStatementsSmall gs = new GetStatementsSmall(ot);
+        pt.foreachPredicate(predicateIndex, gs, null, null, null);
+        ArrayList<Statement> stms = gs.getStatements();
+
+        final int SIZE = stms.size();
+        if (SIZE < 3) {
+            for (int i = 0; i < SIZE; ++i) {
+                Statement stm = stms.get(i);
+                PredicateTable.Status ret = pt.removePredicate(predicateIndex,
+                        stm.pRef, stm.oIndex, ot);
+                if (ret == Status.NothingRemoved)
+                    throw new DatabaseException("Internal error during statement cache fix (2).");
+                assert(stm.pRef < (1<<16));
+                assert(stm.oIndex < 1<<16);
+                int pi = ResourceElementSmall.addStatement(getTable(), realIndex, (short)stm.pRef, (short)stm.oIndex,
+                        pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
+                assert(0 >= pi);
+            }
+            assert(0 == pt.getPredicateSetSize(predicateIndex));
+            ResourceElementSmall.setPredicateIndex(getTable(), realIndex, 0);
+        } else {
+            for (int i = 0; i < SIZE; ++i) {
+                Statement stm = stms.get(i);
+                assert(stm.pRef < (1<<16));
+                assert(stm.oIndex < 1<<16);
+                int pIndex = ResourceElementSmall.addStatement(getTable(), realIndex,
+                        (short)stm.pRef, (short)stm.oIndex, pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
+                if (pIndex > 0)
+                    return; // cache fixed and full, p and o sets in use
+            }
+            throw new DatabaseException("Internal error during statement cache fix (3).");
+        }
+//        if (!ResourceElementSmall.isUsed(getTable(), realIndex))
+//            decResourceCount();
+    }
+
+    private int checkIndexAndGetRealIndex(final int resourceIndex) {
+        if (ClusterTraitsBase.isIllegalResourceIndex(resourceIndex))
+            throw new RuntimeException("Illegal resource index. index=" + resourceIndex + ".");
+        if(resourceIndex > getTableCount())
+            throw new RuntimeException("Illegal resource index. index=" + resourceIndex + " table count=" + getTableCount());
+        final int SIZE = ResourceElementSmall.getSizeOf();
+        final int REAL_INDEX = resourceIndex * SIZE - (SIZE - ZERO_SHIFT) + offset;
+        return REAL_INDEX;
+    }
+    void check(ClusterImpl cluster)
+    throws DatabaseException {
+//        throw new Error("Not implemented.//KRAA:");
+    }
+
+    public void toBig(ClusterBase big, final ClusterSupport support, final ClusterBase small)
+    throws DatabaseException {
+        int resourceIndex = 1;
+        long[] table = getTable();
+        int ps = getHeader().getOffset() + ZERO_SHIFT;
+        final int TABLE_SIZE = getTableSize();
+        int pe = ps + TABLE_SIZE;
+        for (int p=ps; p<pe; p+=ResourceElementSmall.getSizeOf(), ++resourceIndex) {
+            big.createResource(support);
+            int subjectKey = ClusterTraits.createResourceKey(small.clusterKey, resourceIndex);  
+            if (!ResourceElementSmall.isUsed(table, p))
+                continue;
+            int cr = ResourceElementSmall.getCompleteObjectRef(table, p);
+            if (0 != cr) {
+                ClusterI.CompleteTypeEnum ct = ResourceElementSmall.getCompleteType(table, p);
+                if (ClusterI.CompleteTypeEnum.NotComplete != ct) {
+                    int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
+                    int oKey = small.getCompleteObjectKey(subjectKey, support);
+                    big.addRelation(subjectKey, pKey, oKey, support);
+                } else {
+                    final class ForeachObject<Context>
+                    implements ClusterI.ObjectProcedure<Context> {
+                        int sKey;
+                        ClusterBase big;
+                        public ForeachObject(int sKey, ClusterBase big) {
+                            this.sKey = sKey;
+                            this.big = big;
+                        }
+                        @Override
+                        public boolean execute(Context context, int completeRef)
+                        throws DatabaseException {
+                            ClusterI.CompleteTypeEnum ct = ClusterTraitsSmall.completeRefAndTypeGetType(completeRef);
+                            int p = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
+                            int o = small.execute(completeRef & 0xFFFF);
+                            big.addRelation(sKey, p, o, support);
+                            return false; // Continue looping.
+                        }
+                    }
+                    ForeachObject<Object> op = new ForeachObject<Object>(subjectKey, big);
+                    small.getCompleteTable().foreach(cr & 0xFFFF, op, null, support, null);
+                }
+            }
+            int pi = ResourceElementSmall.getPredicateIndex(table, p);
+            if (0 != pi) {
+                ToBigStatements tbs = new ToBigStatements(small, big, support, subjectKey);
+                small.getPredicateTable().foreach(pi, tbs, null, null, null);
+            } else {
+                int p1 = ResourceElementSmall.getStm1Predicate(table, p);
+                int o1 = ResourceElementSmall.getStm1Object(table, p);
+                if (p1 != 0) {
+                    int pk1 = small.execute(p1);
+                    int ok1 = small.execute(o1);
+                    big.addRelation(subjectKey, pk1, ok1, support);
+                    int p2 = ResourceElementSmall.getStm2Predicate(table, p);
+                    int o2 = ResourceElementSmall.getStm2Object(table, p);
+                    if (p2 != 0) {
+                        int pk2 = small.execute(p2);
+                        int ok2 = small.execute(o2);
+                        big.addRelation(subjectKey, pk2, ok2, support);
+                    }
+                }
+            }
+            int valueIndex = ResourceElementSmall.getValueIndex(table, p);
+            if (ClusterTraitsSmall.VALUE_INDEX_EX == valueIndex)
+              big.setValueEx(subjectKey);
+            else {
+                byte[] value = ResourceElementSmall.getValue((ValueTableSmall)small.getValueTable(), table, p);
+                if (null != value)
+                    big.setValue(subjectKey, value, value.length, support);
+            }
+        }
+    }
+
+    @Override
+    public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
+            ClusterSupport support, Modifier modifier) throws DatabaseException {
+        throw new UnsupportedOperationException();
+    }
+}
+
+class CalculateStatementsSmall
+implements ClusterI.PredicateProcedure<CalculateStatements> {
+    private ObjectTable         ot;
+    private final int           sRef;
+
+    CalculateStatementsSmall(int sRef, ObjectTable ot) {
+        this.sRef = sRef;
+        this.ot = ot;
+    }
+
+    @Override
+    public boolean execute(CalculateStatements context
+            , final int pKey, int oIndex) {
+        if (ClusterTraits.statementIndexIsDirect(oIndex))
+            return false; // osize = 1
+        try {
+            oIndex = ClusterTraits.statementIndexGet(oIndex);
+        } catch (DatabaseException e) {
+            Logger.getDefault().logError("Missing object set for s="
+                    + sRef + " p=" + pKey, null);
+            return false; // continue looping
+        }
+        int osize = ot.getObjectSetSize(oIndex);
+        if (osize == 3 || osize > 9)
+            System.out.println("Resource " + sRef + " predicate " + pKey + " has "
+                    + osize + " objects.");
+        return true; // break loop
+    }
+}
+
+class GetStatementsSmall implements ClusterI.PredicateProcedure<Object>, ClusterI.ObjectProcedure<Integer> {
+    private ObjectTable         ot;
+    private final ArrayList<Statement> stms = new ArrayList<Statement>(); 
+    GetStatementsSmall(ObjectTable ot) {
+        this.ot = ot;
+    }
+    ArrayList<Statement> getStatements() {
+        return stms;
+    }
+    @Override
+    public boolean execute(Object context, int pRef, int oIndex) {
+        try {
+            ot.foreachObject(oIndex, this, pRef, null, null);
+        } catch (DatabaseException e) {
+            e.printStackTrace();
+            return false; // continue looping
+        }
+        if (stms.size() > 2)
+            return true; // break loop
+        return false; // continue looping
+    }
+    
+    @Override
+    public boolean execute(Integer pRef, int oRef) {
+        stms.add(new Statement(pRef, oRef));
+        if (stms.size() > 2)
+            return true; // break loop
+        return false; // continue looping
+    }
+}
+
+class ToBigStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {
+    private ClusterBase small;
+    private ClusterBase big;
+    private ClusterSupport support;
+    private int subjectKey;
+    ToBigStatements(ClusterBase small, ClusterBase big, ClusterSupport support, int subjectKey) {
+        this.small = small;
+        this.big = big;
+        this.support = support;
+        this.subjectKey = subjectKey;
+    }
+    @Override
+    public boolean execute(Object context, int pRef, int oIndex) {
+        try {
+            small.getObjectTable().foreach(oIndex, this, pRef, null, null);
+        } catch (DatabaseException e) {
+            e.printStackTrace();
+            return false; // continue looping
+        }
+        return false; // continue looping
+    }
+
+    @Override
+    public boolean execute(Integer pRef, int oRef)
+    throws DatabaseException {
+        int pKey = small.execute(pRef);
+        int oKey = small.execute(oRef);
+        big.addRelation(subjectKey, pKey, oKey, support);
+        return false; // continue looping
+    }
+    
+}