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%2FResourceTable.java;h=d0619976d4775421d4bd5b915d4dbe23b6063081;hp=a36f54d056ac3de5a90915b0a4f55ed6bb3c387d;hb=0d9b90834ce56b292c00b1a39850ed842c3e4d42;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ResourceTable.java b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ResourceTable.java index a36f54d05..d0619976d 100644 --- a/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ResourceTable.java +++ b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ResourceTable.java @@ -1,1236 +1,1237 @@ -/******************************************************************************* - * 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.exception.ExternalValueException; -import org.simantics.db.exception.ValidationException; -import org.simantics.db.impl.ClusterBase; -import org.simantics.db.impl.ClusterI; -import org.simantics.db.impl.ClusterI.CompleteTypeEnum; -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.ResourceImpl; -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; - - -final class ResourceElement { - private static final boolean DEBUG = ClusterImpl.DEBUG; - private static final int DESCRIPTOR_OFFSET = 0; // predicate descriptor - private static final int VALUE_OFFSET = 1; // value descriptor - private static final int STM_OFFSET = 2; // first statement - private static final int SIZE_OF = 4; - - static void construct(long[] table, int index) { - int i = DESCRIPTOR_OFFSET + index; - table[i++] = 0; // predicate capacity & index - table[i++] = 0; // value capacity & index - table[i++] = 0; // stm1 - table[i++] = 0; // stm2 - } - - static void destruct(long[] table, int index) { - int i = DESCRIPTOR_OFFSET + index; - table[i++] = 0; // predicate capacity & index - table[i++] = 0; // value capacity & index - table[i++] = 0; // stm1 - table[i++] = 0; // stm2 - } - - static boolean isUsed(long[] table, int index) { - int i = DESCRIPTOR_OFFSET + index; - if (table[i++] != 0) - return true; - if (table[i++] != 0) - return true; - if (table[i++] != 0) - return true; - if (table[i++] != 0) - return true; - return false; - } - - static int getSizeOf() { - return SIZE_OF; - } - - static int getCompleteObjectRef(long[] table, int index) { - int i = DESCRIPTOR_OFFSET + index; - return BitUtility.getHighInt(table[i]); - } - - static void setCompleteObjectRef(long[] table, int index, int ref) { - int i = DESCRIPTOR_OFFSET + index; - table[i] = BitUtility.setHighInt(table[i], ref); - } - - static int getPredicateIndex(long[] table, int index) { - int i = DESCRIPTOR_OFFSET + index; - int predicateIndex = BitUtility.getLowInt(table[i]); - assert (predicateIndex >= 0); - return predicateIndex; - } - - static void setPredicateIndex(long[] table, int index, int predicateIndex) { - assert (predicateIndex >= 0); - int i = DESCRIPTOR_OFFSET + index; - table[i] = BitUtility.setLowInt(table[i], predicateIndex); - } - - static int copyValue(ValueTable valueTable, long[] table, int index, byte[] byteTable, int byteSize, int byteBase, - int byteCurrent) { - int i = VALUE_OFFSET + index; - if (0 == table[i] || -1 == table[i]) - return byteCurrent; // no value or external value - // getValueCapacity call optimized away - int capacity = BitUtility.getLowInt(table[i]); - int valueIndex = getValueIndex(table, index); - if (0 == valueIndex) - return byteCurrent; - valueTable.getValue(valueIndex, byteTable, byteCurrent, capacity); - valueIndex = byteCurrent - byteBase; - setValueIndex(table, index, valueIndex); - byteCurrent += capacity; - return byteCurrent; - } - - static byte[] getValue(ValueTable valueTable, long[] table, int index) - throws DatabaseException { - int i = VALUE_OFFSET + index; - if (0 == table[i]) - return null; // no value - if (-1 == table[i]) - throw new ExternalValueException("Value stored externally."); - // getValueCapacity call optimized away - int capacity = BitUtility.getLowInt(table[i]); - byte[] t = new byte[capacity]; - int valueIndex = getValueIndex(table, index); - valueTable.getValue(valueIndex, t, 0, capacity); - return t; - } - -// static int getString(ValueTable valueTable, long[] table, int index, char[] t) -// throws DatabaseException { -// long l = table[index + VALUE_OFFSET]; -// if (-1 == l) -// throw new ExternalValueException("String stored externally."); -// int capacity = (int)l; -// int valueIndex = (int) (l >>> 32); -//// char[] t = new char[capacity-1]; -// valueTable.getString(valueIndex, t, 0, capacity-1); -// return capacity-1; -// -// } - - static boolean hasValue(long[] table, int index) { - int i = VALUE_OFFSET + index; - return 0 != table[i]; - } -//KRAA: -// static boolean hasValue(ValueTable valueTable, long[] table, int index, byte[] value) { -// int i = VALUE_OFFSET + index; -// if (0 == table[i]) -// return false; -// // getValueCapacity call optimized away -// int capacity = BitUtility.getLowInt(table[i]); -// if (capacity != value.length) -// return false; -// int valueIndex = getValueIndex(table, index); -// return valueTable.isEqual(valueIndex, value); -// } - - static boolean removeValue(ValueTable valueTable, long[] table, int index) { - int i = VALUE_OFFSET + index; - if (0 == table[i]) - return false; - else if (-1 != table[i]) { - // getValueCapacity call optimized away - int capacity = BitUtility.getLowInt(table[i]); - int valueIndex = getValueIndex(table, index); - valueTable.removeValue(valueIndex, capacity); - } - //setValueCapacityAndIndex(table, index, 0, 0); optimized away - table[i] = 0; - return true; - } - - public static void setValue(ValueTable valueTable, long[] table, int index, byte[] value, int length) { - int i = VALUE_OFFSET + index; - // getValueCapacity call optimized away - int capacity = BitUtility.getLowInt(table[i]); - int valueIndex = getValueIndex(table, index); - if (length <= capacity) { - valueTable.setValue(valueIndex, value, length); - // we "leak" memory TODO: add value size member to - // resource entry or value entry - setValueCapacity(table, index, length); - } else { - if (valueIndex != 0 && capacity > 0) - valueTable.removeValue(valueIndex, capacity); - valueIndex = valueTable.createValue(value, 0, length); - capacity = length; - setValueCapacityAndIndex(table, index, capacity, valueIndex); - } - return; - } - public static boolean isValueEx(ValueTable valueTable, long[] table, int index) { - int i = VALUE_OFFSET + index; - if (-1 == table[i]) - return true; - else - return false; - } - public static void setValueEx(ValueTable valueTable, long[] table, int index) { - int i = VALUE_OFFSET + index; - if (-1 == table[i]) - return; - else if (0 != table[i]) { - int capacity = BitUtility.getLowInt(table[i]); - int valueIndex = getValueIndex(table, index); - valueTable.removeValue(valueIndex, capacity); - } - //setValueCapacityAndIndex(table, index, 0, 0); optimized away - table[i] = -1; - } - static class ValueData { - int capacity; - int index; -// ValueData(int capacity, int index) { -// this.capacity = capacity; -// this.index = index; -// } - } - static void getValueCapacityAndIndex(ValueData vd, long[] table, int index) { - int i = VALUE_OFFSET + index; - // getValueCapacity call optimized away - vd.capacity = BitUtility.getLowInt(table[i]); - vd.index = getValueIndex(table, index); - - } - private static int getValueIndex(long[] table, int index) { - int i = VALUE_OFFSET + index; - return BitUtility.getHighInt(table[i]); - } - - private static void setValueIndex(long[] table, int index, int valueIndex) { - int i = VALUE_OFFSET + index; - table[i] = BitUtility.setHighInt(table[i], valueIndex); - } - - private static void setValueCapacity(long[] table, int index, int capacity) { - int i = VALUE_OFFSET + index; - table[i] = BitUtility.setLowInt(table[i], capacity); - } - - private static void setValueCapacityAndIndex(long[] table, int index, int capacity, int valueIndex) { - int i = VALUE_OFFSET + index; - table[i] = BitUtility.setLowAndHighInt(table[i], capacity, valueIndex); - } - - public static boolean foreachPredicate(long[] table, int index, - ClusterI.PredicateProcedure procedure, - Context context, ClusterSupport support, Modifier modifier, - CompleteTable ct) - throws DatabaseException { - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: 1"); - int completeRef = ResourceElement.getCompleteObjectRef(table, index); - if (0 != completeRef) { - if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements - boolean broken = ct.foreachPredicate(completeRef, procedure, context, support, modifier); - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: multi-complete ci=" + completeRef + " break=" + broken); - if (broken) - return true; // loop broken by procedure - } else { - ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); - if (ClusterI.CompleteTypeEnum.NotComplete != completeType) { - int key = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType); - boolean broken = procedure.execute(context, key, 0); - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: complete rk=" + key + " break=" + broken); - if (broken) - return true; // loop broken by procedure - } - } - } - // If predicate set is in use it will contain also these statements. - if (0 != ResourceElement.getPredicateIndex(table, index)) { - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: more than 2 objects"); - return false; - } - int i = STM_OFFSET + index; - int p1 = BitUtility.getHighInt(table[i]); - if (0 == p1) { - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: empty cache"); - return false; // loop finished, no statements - } - int externalRef; - if (null == modifier) - externalRef = p1; - else - externalRef = modifier.execute(p1); - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: cache1 pk=" + externalRef); - if (procedure.execute(context, externalRef, 0)) - return true; // loop broken by procedure - int p2 = BitUtility.getHighInt(table[++i]); - if (0 == p2 || p1 == p2) { - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: cache2 empty"); - return false; // loop finished, one statement - } if (null == modifier) - externalRef = p2; - else - externalRef = modifier.execute(p2); - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: cache2 pk=" + externalRef); - if (procedure.execute(context, externalRef, 0)) - return true; // loop broken by procedure - if (DEBUG) - System.out.println("ResourceElement.foreachPredicate: not in cache"); - return false; // loop finished, two statements - } - - public static int getSingleObject(long[] table, int index, ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier) - throws DatabaseException { - if (DEBUG) - System.out.println("ResourceElement.getSingleObject: index=" + index); - if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { - int completeRef = getCompleteObjectRef(table, index); - if (0 == completeRef) - return 0; // no objects for given complete type - if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { - // Multiple complete type elements. - if (DEBUG) - System.out.println("ResourceElement.getSingleObject was complete 2"); - class ForeachObject - implements ClusterI.ObjectProcedure { - @Override - public boolean execute(Integer context, int completeRef) - throws DatabaseException { - ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef); - if (pCompleteType == oCompleteType) { // we have a match - if (context != 0) { // we have an old match - context = 0; // multiple objects for given type - return true; // break loop - } - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - context = modifier.execute(resourceIndex); - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - context = modifier.execute(externalRef); - } - } - return true; // continue looping - } - - } - ForeachObject t = new ForeachObject(); - // CompleteRef is complete object set index. - Integer c = 0; - ct.foreachComplete(completeRef, t, c, support, modifier); - return c; - } - // one complete type element - ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); - if (pCompleteType != completeType) - return 0; - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - return modifier.execute(resourceIndex); - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - return modifier.execute(externalRef); - } - } - int i = STM_OFFSET + index; - int p1 = BitUtility.getHighInt(table[i]); - if (0 == p1) - return 0; // loop finished, no statements - int result = 0; - if (pRef == p1) { - int o1 = BitUtility.getLowInt(table[i]); - result = modifier.execute(o1); -// procedure.execute(graph, new ResourceImpl(null, modifier.execute(o1))); -// int externalRef; -// if (null == modifier) -// externalRef = o1; -// else -// externalRef = modifier.execute(callerThread, o1); -// if (procedure.execute(callerThread, context, externalRef)) -// return true; // loop broken by procedure - } - int p2 = BitUtility.getHighInt(table[++i]); - if (0 == p2 || pRef != p2) - return result; // loop finished, one statements - - // Many statements - if (result != 0) return -1; - - int o2 = BitUtility.getLowInt(table[i]); - return modifier.execute(o2); - -// return 0; -// int o2 = BitUtility.getLowInt(table[i]); -// int externalRef; -// if (null == modifier) -// externalRef = o2; -// else -// externalRef = modifier.execute(callerThread, o2); -// if (procedure.execute(callerThread, context, externalRef)) -// return true; // loop broken by procedure -// return false; // loop finished -// procedure.execute(graph, new ResourceImpl(null, modifier.execute(o2))); - } - - public static void foreachObject(long[] table, int index, - final ReadGraphImpl graph, final AsyncMultiProcedure procedure, - final ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier) - throws DatabaseException { - if (DEBUG) - System.out.println("ResourceElement.foreachObject1: index=" + index); - if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { - int completeRef = getCompleteObjectRef(table, index); - if (0 == completeRef) { - procedure.finished(graph); -// graph.state.dec(0); - return; // no objects for given complete type - } - if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { - // Multiple complete type statements. - if (DEBUG) - System.out.println("ResourceElement.was complete 2"); - class ForeachObject implements ClusterI.ObjectProcedure { - @Override - public boolean execute(Object context, int completeRef) throws DatabaseException { - ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef); - if (pCompleteType == oCompleteType) { - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); - } - } - return false; // continue looping - } - - } - ForeachObject t = new ForeachObject(); - // CompleteRef is complete object set index. - ct.foreachComplete(completeRef, t, null, support, modifier); - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished - } - // one complete type element - ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); - if (pCompleteType != completeType) { - procedure.finished(graph); -// graph.state.dec(0); - return; - } - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); - } - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished - } - int i = STM_OFFSET + index; - long l = table[i]; - int p1 = (int) (l >>> 32); - if (0 == p1) { - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished, no statements - } - if (pRef == p1) { - int o1 = (int)l; - procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1))); -// int externalRef; -// if (null == modifier) -// externalRef = o1; -// else -// externalRef = modifier.execute(callerThread, o1); -// if (procedure.execute(callerThread, context, externalRef)) -// return true; // loop broken by procedure - } - long l2 = table[++i]; - int p2 = (int) (l2 >>> 32); - if (pRef != p2) { - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished, one statements - } - int o2 = (int)l2; - procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2))); - procedure.finished(graph); -// graph.state.dec(0); - } - - public static void foreachObject(long[] table, int index, - final ReadGraphImpl graph, final C context, final AsyncContextMultiProcedure procedure, - final ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier) - throws DatabaseException { - if (DEBUG) - System.out.println("ResourceElement.foreachObject1: index=" + index); - if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { - int completeRef = getCompleteObjectRef(table, index); - if (0 == completeRef) { - procedure.finished(graph); -// graph.state.dec(0); - return; // no objects for given complete type - } - if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { - // Multiple complete type statements. - if (DEBUG) - System.out.println("ResourceElement.was complete 2"); - class ForeachObject implements ClusterI.ObjectProcedure { - @Override - public boolean execute(Object _context, int completeRef) throws DatabaseException { - ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef); - if (pCompleteType == oCompleteType) { - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); - } - } - return false; // continue looping - } - - } - ForeachObject t = new ForeachObject(); - // CompleteRef is complete object set index. - ct.foreachComplete(completeRef, t, null, support, modifier); - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished - } - // one complete type element - ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); - if (pCompleteType != completeType) { - procedure.finished(graph); -// graph.state.dec(0); - return; - } - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); - } - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished - } - int i = STM_OFFSET + index; - long l = table[i]; - int p1 = (int) (l >>> 32); - if (0 == p1) { - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished, no statements - } - if (pRef == p1) { - int o1 = (int)l; - procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1))); -// int externalRef; -// if (null == modifier) -// externalRef = o1; -// else -// externalRef = modifier.execute(callerThread, o1); -// if (procedure.execute(callerThread, context, externalRef)) -// return true; // loop broken by procedure - } - long l2 = table[++i]; - int p2 = (int) (l2 >>> 32); - if (pRef != p2) { - procedure.finished(graph); -// graph.state.dec(0); - return; // loop finished, one statements - } - int o2 = (int)l2; - procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2))); - procedure.finished(graph); -// graph.state.dec(0); - } - - public static boolean foreachObject(long[] table, int index - , ClusterI.ObjectProcedure procedure - , Context context, ClusterSupport support, Modifier modifier - , final int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct) - throws DatabaseException { - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: 1 "); - if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { - int completeRef = getCompleteObjectRef(table, index); - if (0 == completeRef) { - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: no complete"); - return false; // no objects for given complete type - } - if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: multi-complete ci=" + completeRef); - return ct.foreachObject(completeRef, procedure, context, support, modifier, pCompleteType); - } - // one complete type element - ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); - if (pCompleteType != completeType) { - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: complete different predicate"); - return false; - } - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - int externalRef; - if (null == modifier) - externalRef = resourceIndex; - else - externalRef = modifier.execute(resourceIndex); - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef); - if (procedure.execute(context, externalRef)) - return true; // loop broken by procedure - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - if (null != modifier) - externalRef = modifier.execute(externalRef); - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef); - if (procedure.execute(context, externalRef)) - return true; // loop broken by procedure - } - return false; // loop finished - } - int i = STM_OFFSET + index; - int p1 = BitUtility.getHighInt(table[i]); - if (0 == p1) { - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: empty cache="); - return false; // loop finished, no statements - } - if (pRef == p1) { - int o1 = BitUtility.getLowInt(table[i]); - int externalRef; - if (null == modifier) - externalRef = o1; - else - externalRef = modifier.execute(o1); - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: cache1 ok=" + externalRef); - if (procedure.execute(context, externalRef)) - return true; // loop broken by procedure - } - int p2 = BitUtility.getHighInt(table[++i]); - if (0 == p2 || pRef != p2) { - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: not in cache1"); - return false; // loop finished, one statements - } - int o2 = BitUtility.getLowInt(table[i]); - int externalRef; - if (null == modifier) - externalRef = o2; - else - externalRef = modifier.execute(o2); - if (DEBUG) - System.out.println("ResourceElement.foreachObject2: cache2 ok=" + externalRef); - return procedure.execute(context, externalRef); - } - static boolean isEmpty(long[] table, int index) { - return getStatementCount(table, index) == 0 && !hasValue(table, index); - } - static int getStatementCount(long[] table, int index) { - int i = STM_OFFSET + index; - int p1 = BitUtility.getHighInt(table[i]); - int p2 = BitUtility.getLowInt(table[++i]); - if (0 == p1) - return 0; - else if (0 == p2) - return 1; - int predicateIndex = getPredicateIndex(table, index); - if (0 == predicateIndex) - return 2; - return 3; - } - private static int makeCompleteObjectRef(int oRef, ClusterI.CompleteTypeEnum completeType) { - int ref; - if (oRef > 0) { - int resourceIndex = oRef; - int clusterIndex = 0; - ref = ClusterTraits.completeReferenceMake(completeType.getValue(), resourceIndex, clusterIndex); - } else { - assert(oRef < 0); - assert(!ClusterTraits.isFlat(oRef)); - ref = (completeType.getValue() <<30) | (oRef & 0x3FFFFFFF); - } - return ref; - } - static int addStatement(long[] table, int index, int pRef, int oRef - , PredicateTable pt, ObjectTable ot - , ClusterI.CompleteTypeEnum completeType, CompleteTable ct) - throws DatabaseException { - assert (0 != pRef); - assert (0 != oRef); - if (ClusterI.CompleteTypeEnum.NotComplete != completeType) { - int cRef = makeCompleteObjectRef(oRef, completeType); - int ctr = getCompleteObjectRef(table, index); - if (0 == ctr) - setCompleteObjectRef(table, index, cRef); - else { - int nRef; - if (ctr == cRef) - return -1; // old complete - else if (ClusterTraits.completeReferenceIsMultiple(ctr)) { - nRef = ct.addComplete(ctr, cRef); - if (0 == nRef) - return -1; // old complete - } else { - nRef = ct.createCompleteArraySet(ctr, cRef); - } - setCompleteObjectRef(table, index, nRef); - } - return 0; // added to complete - } - int i = STM_OFFSET + index; - int p1 = BitUtility.getHighInt(table[i]); - int o1 = BitUtility.getLowInt(table[i]); - if (0 == p1) { - table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef); - return 0; // added to stm cache - } else if (p1 == pRef && o1 == oRef) - return -1; // same statement - int p2 = BitUtility.getHighInt(table[++i]); - int o2 = BitUtility.getLowInt(table[i]); - if (0 == p2) { - table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef); - return 0; // added to stm cache - } else if (p2 == pRef && o2 == oRef) - return -1; // same statement - int predicateIndex = getPredicateIndex(table, index); - if (0 == predicateIndex) { - if (p1 == p2) { - int objectIndex = ot.createObjectSet(o1, o2); - assert (0 != objectIndex); - int[] os = new int[1]; - os[0] = ClusterTraits.statementIndexMake(objectIndex); - int[] ps = new int[1]; - ps[0] = p1; - predicateIndex = pt.createPredicateSet(ps, os); - } else { - int[] os = new int[2]; - os[0] = o1; - os[1] = o2; - int[] ps = new int[2]; - ps[0] = p1; - ps[1] = p2; - predicateIndex = pt.createPredicateSet(ps, os); - } - assert (0 != predicateIndex); - setPredicateIndex(table, index, predicateIndex); - } - assert (0 != predicateIndex); - return predicateIndex; - } - - static boolean removeStatement(long[] table, int index, int pRef, int oRef, - ClusterI.CompleteTypeEnum completeType, CompleteTable ct) - throws DatabaseException { - assert (0 != pRef); - assert (0 != oRef); - if (completeType != ClusterI.CompleteTypeEnum.NotComplete) { - int completeRef = ResourceElement.getCompleteObjectRef(table, index); - if (0 != completeRef) { - ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef); - if (completeType == completeType2) { - int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); - int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); - if (0 == clusterIndex) { - if (oRef == resourceIndex) { - ResourceElement.setCompleteObjectRef(table, index, 0); - return true; // statement removed - } - } else { - int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); - if (oRef == externalRef) { - ResourceElement.setCompleteObjectRef(table, index, 0); - return true; // statement removed - } - } - } else if (completeType2 == ClusterI.CompleteTypeEnum.NotComplete) { // multiple complete type references - int cRef = makeCompleteObjectRef(oRef, completeType); - int oldSize = ct.getCompleteSetSize(completeRef); - int newSize = ct.removeComplete(completeRef, cRef); - if (oldSize == newSize) - return false; // not removed - else if (newSize == 1) { - cRef = ct.removeLast(completeRef); - ResourceElement.setCompleteObjectRef(table, index, cRef); - } - return true; - } - } - } - int i = STM_OFFSET + index; - int p1 = BitUtility.getHighInt(table[i]); - int o1 = BitUtility.getLowInt(table[i]); - if (0 == p1) - return false; // no statements cached - else if (p1 == pRef && o1 == oRef) { - table[i] = table[i + 1]; - // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away - table[i + 1] = 0; - return true; // statement removed - } - int p2 = BitUtility.getHighInt(table[++i]); - int o2 = BitUtility.getLowInt(table[i]); - if (0 == p2) - return false; // no match - else if (p2 == pRef && o2 == oRef) { - // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away - table[i] = 0; - return true; // statement removed - } - return false; - } -} - -public final class ResourceTable extends Table { - public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase) { - super(TableFactory.getLongFactory(), sizeListener, header, headerBase); - } - - public ResourceTable(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 = ResourceElement.getSizeOf(); - int resourceIndex = createNewElement(SIZE); - assert (0 != resourceIndex); - final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE); - ResourceElement.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 (ResourceElement.isEmpty(getTable(), realIndex)) - return; - } if (resourceIndex == tableCount+1) { - createResource(); - return; - } - throw new InternalError("Trying to create resource with illegal index=" + resourceIndex); - } - -// void deleteResource(int resourceIndex) { -// int realIndex = checkIndexAndGetRealIndex(resourceIndex); -// ResourceElement.destruct(getTable(), realIndex); -// decResourceCount(); -// } - - public int getCompleteObjectRef(int resourceIndex) { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - return ResourceElement.getCompleteObjectRef(getTable(), realIndex); - } - - public int getPredicateIndex(int resourceIndex) { - int i = (resourceIndex<<2) - 3 + offset; - return (int)table[i]; - } - - public void setPredicateIndex(int resourceIndex, int predicateIndex) { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - ResourceElement.setPredicateIndex(getTable(), realIndex, predicateIndex); - } - - public byte[] getValue(ValueTable valueTable, int resourceIndex) - throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - return ResourceElement.getValue(valueTable, getTable(), realIndex); - } - -//KRAA: -// int getString(ValueTable valueTable, int resourceIndex, char[] chars) -// throws DatabaseException { -// //int realIndex = checkIndexAndGetRealIndex(resourceIndex); -// return ResourceElement.getString(valueTable, getTable(), 4 * resourceIndex - 3 + offset, chars); -// } - - public boolean hasValue(int resourceIndex) { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - return ResourceElement.hasValue(getTable(), realIndex); - } - -// boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) { -// int realIndex = checkIndexAndGetRealIndex(resourceIndex); -// return ResourceElement.hasValue(valueTable, getTable(), realIndex, value); -// } - - public boolean removeValue(ValueTable valueTable, int resourceIndex) { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - boolean ret = ResourceElement.removeValue(valueTable, getTable(), realIndex); -// if (ret && !ResourceElement.isUsed(getTable(), realIndex)) -// decResourceCount(); - return ret; - } - - public void setValue(ValueTable valueTable, int resourceIndex, byte[] value, int length) { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - ResourceElement.setValue(valueTable, getTable(), realIndex, value, length); - } - - public boolean isValueEx(ValueTable valueTable, int resourceIndex) { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - return ResourceElement.isValueEx(valueTable, getTable(), realIndex); - } - - public void setValueEx(ValueTable valueTable, int resourceIndex) { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - ResourceElement.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); - } - void analyse() { - - final int tsize = getTableSize(); - final int esize = ResourceElement.getSizeOf(); - long[] table = getTable(); - for (int i = getTableBase(); i < getTableBase() + tsize; i += esize) { - if (ResourceElement.isUsed(getTable(), i)) { - System.out.println(" -" + Long.toHexString(table[i]) + " " + Long.toHexString(table[i+1]) + " " + Long.toHexString(table[i+2]) + " " + Long.toHexString(table[i+3])); - } - } - - } - - public boolean foreachResource(ClusterI.ObjectProcedure procedure, Context context, - ClusterSupport support, Modifier modifier) throws DatabaseException { - final int tsize = getTableSize(); -// final int rsize = getResourceCount(); - final int esize = ResourceElement.getSizeOf(); - //int count = 0; - int key = ZERO_SHIFT; - for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) { - if (ResourceElement.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 boolean foreachPredicate(int resourceIndex - , ClusterI.PredicateProcedure procedure, Context context - , ClusterSupport support, Modifier modifier, CompleteTable ct) - throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - return ResourceElement.foreachPredicate(getTable(), realIndex - , procedure, context, support, modifier, ct); - } - - public int getSingleObject(int resourceIndex, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException { -// return ResourceElement.getSingleObject(table, realIndex, support, pRef, pCompleteType, ct, modifier); - return ResourceElement.getSingleObject(table, 4 * resourceIndex - 3 + offset, support, pRef, pCompleteType, ct, modifier); - } - - public void foreachObject(int resourceIndex, ReadGraphImpl graph, - AsyncMultiProcedure procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - ResourceElement.foreachObject(table, realIndex, graph, procedure, support, - pRef, pCompleteType, ct, modifier); - } - - public void foreachObject(int resourceIndex, ReadGraphImpl graph, C context, - AsyncContextMultiProcedure procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - ResourceElement.foreachObject(table, realIndex, graph, context, procedure, support, - pRef, pCompleteType, ct, modifier); - } - - public boolean foreachObject(int resourceIndex - , ClusterI.ObjectProcedure procedure, Context context - , ClusterSupport support, Modifier modifier, - int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct) - throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - return ResourceElement.foreachObject(table, realIndex - , procedure, context, support, modifier - , pRef, completeType, ct); - } - public int addStatement(int resourceIndex, int pRef, int oRef, PredicateTable pt, ObjectTable ot - , ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct) - throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - return ResourceElement.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, pCompleteType, ct); - } - - public boolean removeStatementFromCache(int resourceIndex, int pRef, int oRef, - ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct) - throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - boolean ret = ResourceElement.removeStatement(getTable(), realIndex, pRef, oRef, pCompleteType, ct); -// if (ret && !ResourceElement.isUsed(getTable(), realIndex)) -// decResourceCount(); - return ret; - } - - public void removeStatement(int resourceIndex, int pRef, int oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, - PredicateTable pt, ObjectTable ot, ClusterBase cluster, ClusterSupport support) - throws DatabaseException { - int realIndex = checkIndexAndGetRealIndex(resourceIndex); - boolean removed = ResourceElement.removeStatement(getTable(), realIndex, - pRef, oRef, pCompleteType, ct); - if (!removed) - return; - int predicateIndex = ResourceElement.getPredicateIndex(getTable(), realIndex); - if (0 == predicateIndex) { -// if (!ResourceElement.isUsed(getTable(), realIndex)) -// decResourceCount(); - return; - } - GetStatements gs = new GetStatements(ot); - pt.foreachPredicate(predicateIndex, gs, null, null, null); - ArrayList 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)."); - int predicateKey = cluster.makeResourceKey(stm.pRef); - int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey); - ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt); - int pi = ResourceElement.addStatement(getTable(), realIndex, stm.pRef, stm.oIndex, - pt, ot, completeType, ct); - assert(0 >= pi); - } - assert(0 == pt.getPredicateSetSize(predicateIndex)); - ResourceElement.setPredicateIndex(getTable(), realIndex, 0); - } else { - for (int i = 0; i < SIZE; ++i) { - Statement stm = stms.get(i); - int predicateKey = cluster.makeResourceKey(stm.pRef); - int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey); - ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt); - int pIndex = ResourceElement.addStatement(getTable(), realIndex, - stm.pRef, stm.oIndex, pt, ot, completeType, 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 (!ResourceElement.isUsed(getTable(), realIndex)) -// decResourceCount(); - } - - //(i-1)*4+1 + 4 - private int checkIndexAndGetRealIndex(final int INDEX) { - assert(INDEX > 0); - assert(INDEX <= getTableCount()); -// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT; -// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT; -// return checkIndexAndGetRealIndex(TABLE_INDEX, ResourceElement.getSizeOf()); - return 4 * INDEX - 3 + offset; - } - public void check(ClusterBase cluster) - throws DatabaseException { -// int count = 0; - cluster.checkValueInit(); - long[] table = getTable(); - int ps = getHeader().getOffset() + ZERO_SHIFT; - final int TABLE_SIZE = getTableSize(); - int pe = ps + TABLE_SIZE; - for (int p=ps; p TABLE_SIZE) - throw new ValidationException("Illegal resource index=" + ri); - } - } - int pi = ResourceElement.getPredicateIndex(table, p); - if (0 != pi) { - cluster.checkPredicateIndex(pi); - } - ResourceElement.ValueData vd = new ResourceElement.ValueData(); - ResourceElement.getValueCapacityAndIndex(vd, table, p); - cluster.checkValue(vd.capacity, vd.index); - } - cluster.checkValueFini(); - } - - @Override - public boolean foreach(int setIndex, Procedure procedure, Context context, - ClusterSupport support, Modifier modifier) throws DatabaseException { - throw new UnsupportedOperationException(); - } -} - -class Statement { - Statement(int pRef, int oIndex) { - this.pRef = pRef; - this.oIndex = oIndex; - } - final int pRef; - final int oIndex; -} - -class CalculateStatements -implements ClusterI.PredicateProcedure { - private ObjectTable ot; - private final int sRef; - - CalculateStatements(int sRef, ObjectTable ot) { - this.sRef = sRef; - this.ot = ot; - } - - @Override - public boolean execute(final 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 GetStatements implements PredicateProcedure, ObjectProcedure { - private ObjectTable ot; - private final ArrayList stms = new ArrayList(); - GetStatements(ObjectTable ot) { - this.ot = ot; - } - ArrayList 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 - } - -} +/******************************************************************************* + * 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.exception.ExternalValueException; +import org.simantics.db.exception.ValidationException; +import org.simantics.db.impl.ClusterBase; +import org.simantics.db.impl.ClusterI; +import org.simantics.db.impl.ClusterI.CompleteTypeEnum; +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.ResourceImpl; +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.SyncContextMultiProcedure; +import org.simantics.db.procedure.SyncMultiProcedure; +import org.simantics.db.procore.cluster.PredicateTable.Status; + + +final class ResourceElement { + private static final boolean DEBUG = ClusterImpl.DEBUG; + private static final int DESCRIPTOR_OFFSET = 0; // predicate descriptor + private static final int VALUE_OFFSET = 1; // value descriptor + private static final int STM_OFFSET = 2; // first statement + private static final int SIZE_OF = 4; + + static void construct(long[] table, int index) { + int i = DESCRIPTOR_OFFSET + index; + table[i++] = 0; // predicate capacity & index + table[i++] = 0; // value capacity & index + table[i++] = 0; // stm1 + table[i++] = 0; // stm2 + } + + static void destruct(long[] table, int index) { + int i = DESCRIPTOR_OFFSET + index; + table[i++] = 0; // predicate capacity & index + table[i++] = 0; // value capacity & index + table[i++] = 0; // stm1 + table[i++] = 0; // stm2 + } + + static boolean isUsed(long[] table, int index) { + int i = DESCRIPTOR_OFFSET + index; + if (table[i++] != 0) + return true; + if (table[i++] != 0) + return true; + if (table[i++] != 0) + return true; + if (table[i++] != 0) + return true; + return false; + } + + static int getSizeOf() { + return SIZE_OF; + } + + static int getCompleteObjectRef(long[] table, int index) { + int i = DESCRIPTOR_OFFSET + index; + return BitUtility.getHighInt(table[i]); + } + + static void setCompleteObjectRef(long[] table, int index, int ref) { + int i = DESCRIPTOR_OFFSET + index; + table[i] = BitUtility.setHighInt(table[i], ref); + } + + static int getPredicateIndex(long[] table, int index) { + int i = DESCRIPTOR_OFFSET + index; + int predicateIndex = BitUtility.getLowInt(table[i]); + assert (predicateIndex >= 0); + return predicateIndex; + } + + static void setPredicateIndex(long[] table, int index, int predicateIndex) { + assert (predicateIndex >= 0); + int i = DESCRIPTOR_OFFSET + index; + table[i] = BitUtility.setLowInt(table[i], predicateIndex); + } + + static int copyValue(ValueTable valueTable, long[] table, int index, byte[] byteTable, int byteSize, int byteBase, + int byteCurrent) { + int i = VALUE_OFFSET + index; + if (0 == table[i] || -1 == table[i]) + return byteCurrent; // no value or external value + // getValueCapacity call optimized away + int capacity = BitUtility.getLowInt(table[i]); + int valueIndex = getValueIndex(table, index); + if (0 == valueIndex) + return byteCurrent; + valueTable.getValue(valueIndex, byteTable, byteCurrent, capacity); + valueIndex = byteCurrent - byteBase; + setValueIndex(table, index, valueIndex); + byteCurrent += capacity; + return byteCurrent; + } + + static byte[] getValue(ValueTable valueTable, long[] table, int index) + throws DatabaseException { + int i = VALUE_OFFSET + index; + if (0 == table[i]) + return null; // no value + if (-1 == table[i]) + throw new ExternalValueException("Value stored externally."); + // getValueCapacity call optimized away + int capacity = BitUtility.getLowInt(table[i]); + byte[] t = new byte[capacity]; + int valueIndex = getValueIndex(table, index); + valueTable.getValue(valueIndex, t, 0, capacity); + return t; + } + +// static int getString(ValueTable valueTable, long[] table, int index, char[] t) +// throws DatabaseException { +// long l = table[index + VALUE_OFFSET]; +// if (-1 == l) +// throw new ExternalValueException("String stored externally."); +// int capacity = (int)l; +// int valueIndex = (int) (l >>> 32); +//// char[] t = new char[capacity-1]; +// valueTable.getString(valueIndex, t, 0, capacity-1); +// return capacity-1; +// +// } + + static boolean hasValue(long[] table, int index) { + int i = VALUE_OFFSET + index; + return 0 != table[i]; + } +//KRAA: +// static boolean hasValue(ValueTable valueTable, long[] table, int index, byte[] value) { +// int i = VALUE_OFFSET + index; +// if (0 == table[i]) +// return false; +// // getValueCapacity call optimized away +// int capacity = BitUtility.getLowInt(table[i]); +// if (capacity != value.length) +// return false; +// int valueIndex = getValueIndex(table, index); +// return valueTable.isEqual(valueIndex, value); +// } + + static boolean removeValue(ValueTable valueTable, long[] table, int index) { + int i = VALUE_OFFSET + index; + if (0 == table[i]) + return false; + else if (-1 != table[i]) { + // getValueCapacity call optimized away + int capacity = BitUtility.getLowInt(table[i]); + int valueIndex = getValueIndex(table, index); + valueTable.removeValue(valueIndex, capacity); + } + //setValueCapacityAndIndex(table, index, 0, 0); optimized away + table[i] = 0; + return true; + } + + public static void setValue(ValueTable valueTable, long[] table, int index, byte[] value, int length) { + int i = VALUE_OFFSET + index; + // getValueCapacity call optimized away + int capacity = BitUtility.getLowInt(table[i]); + int valueIndex = getValueIndex(table, index); + if (length <= capacity) { + valueTable.setValue(valueIndex, value, length); + // we "leak" memory TODO: add value size member to + // resource entry or value entry + setValueCapacity(table, index, length); + } else { + if (valueIndex != 0 && capacity > 0) + valueTable.removeValue(valueIndex, capacity); + valueIndex = valueTable.createValue(value, 0, length); + capacity = length; + setValueCapacityAndIndex(table, index, capacity, valueIndex); + } + return; + } + public static boolean isValueEx(ValueTable valueTable, long[] table, int index) { + int i = VALUE_OFFSET + index; + if (-1 == table[i]) + return true; + else + return false; + } + public static void setValueEx(ValueTable valueTable, long[] table, int index) { + int i = VALUE_OFFSET + index; + if (-1 == table[i]) + return; + else if (0 != table[i]) { + int capacity = BitUtility.getLowInt(table[i]); + int valueIndex = getValueIndex(table, index); + valueTable.removeValue(valueIndex, capacity); + } + //setValueCapacityAndIndex(table, index, 0, 0); optimized away + table[i] = -1; + } + static class ValueData { + int capacity; + int index; +// ValueData(int capacity, int index) { +// this.capacity = capacity; +// this.index = index; +// } + } + static void getValueCapacityAndIndex(ValueData vd, long[] table, int index) { + int i = VALUE_OFFSET + index; + // getValueCapacity call optimized away + vd.capacity = BitUtility.getLowInt(table[i]); + vd.index = getValueIndex(table, index); + + } + private static int getValueIndex(long[] table, int index) { + int i = VALUE_OFFSET + index; + return BitUtility.getHighInt(table[i]); + } + + private static void setValueIndex(long[] table, int index, int valueIndex) { + int i = VALUE_OFFSET + index; + table[i] = BitUtility.setHighInt(table[i], valueIndex); + } + + private static void setValueCapacity(long[] table, int index, int capacity) { + int i = VALUE_OFFSET + index; + table[i] = BitUtility.setLowInt(table[i], capacity); + } + + private static void setValueCapacityAndIndex(long[] table, int index, int capacity, int valueIndex) { + int i = VALUE_OFFSET + index; + table[i] = BitUtility.setLowAndHighInt(table[i], capacity, valueIndex); + } + + public static boolean foreachPredicate(long[] table, int index, + ClusterI.PredicateProcedure procedure, + Context context, ClusterSupport support, Modifier modifier, + CompleteTable ct) + throws DatabaseException { + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: 1"); + int completeRef = ResourceElement.getCompleteObjectRef(table, index); + if (0 != completeRef) { + if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements + boolean broken = ct.foreachPredicate(completeRef, procedure, context, support, modifier); + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: multi-complete ci=" + completeRef + " break=" + broken); + if (broken) + return true; // loop broken by procedure + } else { + ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); + if (ClusterI.CompleteTypeEnum.NotComplete != completeType) { + int key = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType); + boolean broken = procedure.execute(context, key, 0); + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: complete rk=" + key + " break=" + broken); + if (broken) + return true; // loop broken by procedure + } + } + } + // If predicate set is in use it will contain also these statements. + if (0 != ResourceElement.getPredicateIndex(table, index)) { + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: more than 2 objects"); + return false; + } + int i = STM_OFFSET + index; + int p1 = BitUtility.getHighInt(table[i]); + if (0 == p1) { + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: empty cache"); + return false; // loop finished, no statements + } + int externalRef; + if (null == modifier) + externalRef = p1; + else + externalRef = modifier.execute(p1); + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: cache1 pk=" + externalRef); + if (procedure.execute(context, externalRef, 0)) + return true; // loop broken by procedure + int p2 = BitUtility.getHighInt(table[++i]); + if (0 == p2 || p1 == p2) { + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: cache2 empty"); + return false; // loop finished, one statement + } if (null == modifier) + externalRef = p2; + else + externalRef = modifier.execute(p2); + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: cache2 pk=" + externalRef); + if (procedure.execute(context, externalRef, 0)) + return true; // loop broken by procedure + if (DEBUG) + System.out.println("ResourceElement.foreachPredicate: not in cache"); + return false; // loop finished, two statements + } + + public static int getSingleObject(long[] table, int index, ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier) + throws DatabaseException { + if (DEBUG) + System.out.println("ResourceElement.getSingleObject: index=" + index); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { + int completeRef = getCompleteObjectRef(table, index); + if (0 == completeRef) + return 0; // no objects for given complete type + if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { + // Multiple complete type elements. + if (DEBUG) + System.out.println("ResourceElement.getSingleObject was complete 2"); + class ForeachObject + implements ClusterI.ObjectProcedure { + @Override + public boolean execute(Integer context, int completeRef) + throws DatabaseException { + ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef); + if (pCompleteType == oCompleteType) { // we have a match + if (context != 0) { // we have an old match + context = 0; // multiple objects for given type + return true; // break loop + } + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + context = modifier.execute(resourceIndex); + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + context = modifier.execute(externalRef); + } + } + return true; // continue looping + } + + } + ForeachObject t = new ForeachObject(); + // CompleteRef is complete object set index. + Integer c = 0; + ct.foreachComplete(completeRef, t, c, support, modifier); + return c; + } + // one complete type element + ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); + if (pCompleteType != completeType) + return 0; + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + return modifier.execute(resourceIndex); + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + return modifier.execute(externalRef); + } + } + int i = STM_OFFSET + index; + int p1 = BitUtility.getHighInt(table[i]); + if (0 == p1) + return 0; // loop finished, no statements + int result = 0; + if (pRef == p1) { + int o1 = BitUtility.getLowInt(table[i]); + result = modifier.execute(o1); +// procedure.execute(graph, new ResourceImpl(null, modifier.execute(o1))); +// int externalRef; +// if (null == modifier) +// externalRef = o1; +// else +// externalRef = modifier.execute(callerThread, o1); +// if (procedure.execute(callerThread, context, externalRef)) +// return true; // loop broken by procedure + } + int p2 = BitUtility.getHighInt(table[++i]); + if (0 == p2 || pRef != p2) + return result; // loop finished, one statements + + // Many statements + if (result != 0) return -1; + + int o2 = BitUtility.getLowInt(table[i]); + return modifier.execute(o2); + +// return 0; +// int o2 = BitUtility.getLowInt(table[i]); +// int externalRef; +// if (null == modifier) +// externalRef = o2; +// else +// externalRef = modifier.execute(callerThread, o2); +// if (procedure.execute(callerThread, context, externalRef)) +// return true; // loop broken by procedure +// return false; // loop finished +// procedure.execute(graph, new ResourceImpl(null, modifier.execute(o2))); + } + + public static void foreachObject(long[] table, int index, + final ReadGraphImpl graph, final SyncMultiProcedure procedure, + final ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier) + throws DatabaseException { + if (DEBUG) + System.out.println("ResourceElement.foreachObject1: index=" + index); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { + int completeRef = getCompleteObjectRef(table, index); + if (0 == completeRef) { + procedure.finished(graph); +// graph.state.dec(0); + return; // no objects for given complete type + } + if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { + // Multiple complete type statements. + if (DEBUG) + System.out.println("ResourceElement.was complete 2"); + class ForeachObject implements ClusterI.ObjectProcedure { + @Override + public boolean execute(Object context, int completeRef) throws DatabaseException { + ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef); + if (pCompleteType == oCompleteType) { + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); + } + } + return false; // continue looping + } + + } + ForeachObject t = new ForeachObject(); + // CompleteRef is complete object set index. + ct.foreachComplete(completeRef, t, null, support, modifier); + procedure.finished(graph); +// graph.state.dec(0); + return; // loop finished + } + // one complete type element + ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); + if (pCompleteType != completeType) { + procedure.finished(graph); +// graph.state.dec(0); + return; + } + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); + } + procedure.finished(graph); +// graph.state.dec(0); + return; // loop finished + } + int i = STM_OFFSET + index; + long l = table[i]; + int p1 = (int) (l >>> 32); + if (0 == p1) { + procedure.finished(graph); +// graph.state.dec(0); + return; // loop finished, no statements + } + if (pRef == p1) { + int o1 = (int)l; + procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1))); +// int externalRef; +// if (null == modifier) +// externalRef = o1; +// else +// externalRef = modifier.execute(callerThread, o1); +// if (procedure.execute(callerThread, context, externalRef)) +// return true; // loop broken by procedure + } + long l2 = table[++i]; + int p2 = (int) (l2 >>> 32); + if (pRef != p2) { + procedure.finished(graph); +// graph.state.dec(0); + return; // loop finished, one statements + } + int o2 = (int)l2; + procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2))); + procedure.finished(graph); +// graph.state.dec(0); + } + + public static void foreachObject(long[] table, int index, + final ReadGraphImpl graph, final C context, final SyncContextMultiProcedure procedure, + final ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier) + throws DatabaseException { + if (DEBUG) + System.out.println("ResourceElement.foreachObject1: index=" + index); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { + int completeRef = getCompleteObjectRef(table, index); + if (0 == completeRef) { + procedure.finished(graph, context); +// graph.state.dec(0); + return; // no objects for given complete type + } + if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { + // Multiple complete type statements. + if (DEBUG) + System.out.println("ResourceElement.was complete 2"); + class ForeachObject implements ClusterI.ObjectProcedure { + @Override + public boolean execute(Object _context, int completeRef) throws DatabaseException { + ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef); + if (pCompleteType == oCompleteType) { + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); + } + } + return false; // continue looping + } + + } + ForeachObject t = new ForeachObject(); + // CompleteRef is complete object set index. + ct.foreachComplete(completeRef, t, null, support, modifier); + procedure.finished(graph, context); +// graph.state.dec(0); + return; // loop finished + } + // one complete type element + ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); + if (pCompleteType != completeType) { + procedure.finished(graph, context); +// graph.state.dec(0); + return; + } + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex))); + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef))); + } + procedure.finished(graph, context); +// graph.state.dec(0); + return; // loop finished + } + int i = STM_OFFSET + index; + long l = table[i]; + int p1 = (int) (l >>> 32); + if (0 == p1) { + procedure.finished(graph, context); +// graph.state.dec(0); + return; // loop finished, no statements + } + if (pRef == p1) { + int o1 = (int)l; + procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1))); +// int externalRef; +// if (null == modifier) +// externalRef = o1; +// else +// externalRef = modifier.execute(callerThread, o1); +// if (procedure.execute(callerThread, context, externalRef)) +// return true; // loop broken by procedure + } + long l2 = table[++i]; + int p2 = (int) (l2 >>> 32); + if (pRef != p2) { + procedure.finished(graph, context); +// graph.state.dec(0); + return; // loop finished, one statements + } + int o2 = (int)l2; + procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2))); + procedure.finished(graph, context); +// graph.state.dec(0); + } + + public static boolean foreachObject(long[] table, int index + , ClusterI.ObjectProcedure procedure + , Context context, ClusterSupport support, Modifier modifier + , final int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct) + throws DatabaseException { + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: 1 "); + if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) { + int completeRef = getCompleteObjectRef(table, index); + if (0 == completeRef) { + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: no complete"); + return false; // no objects for given complete type + } + if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: multi-complete ci=" + completeRef); + return ct.foreachObject(completeRef, procedure, context, support, modifier, pCompleteType); + } + // one complete type element + ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef); + if (pCompleteType != completeType) { + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: complete different predicate"); + return false; + } + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + int externalRef; + if (null == modifier) + externalRef = resourceIndex; + else + externalRef = modifier.execute(resourceIndex); + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef); + if (procedure.execute(context, externalRef)) + return true; // loop broken by procedure + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + if (null != modifier) + externalRef = modifier.execute(externalRef); + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef); + if (procedure.execute(context, externalRef)) + return true; // loop broken by procedure + } + return false; // loop finished + } + int i = STM_OFFSET + index; + int p1 = BitUtility.getHighInt(table[i]); + if (0 == p1) { + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: empty cache="); + return false; // loop finished, no statements + } + if (pRef == p1) { + int o1 = BitUtility.getLowInt(table[i]); + int externalRef; + if (null == modifier) + externalRef = o1; + else + externalRef = modifier.execute(o1); + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: cache1 ok=" + externalRef); + if (procedure.execute(context, externalRef)) + return true; // loop broken by procedure + } + int p2 = BitUtility.getHighInt(table[++i]); + if (0 == p2 || pRef != p2) { + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: not in cache1"); + return false; // loop finished, one statements + } + int o2 = BitUtility.getLowInt(table[i]); + int externalRef; + if (null == modifier) + externalRef = o2; + else + externalRef = modifier.execute(o2); + if (DEBUG) + System.out.println("ResourceElement.foreachObject2: cache2 ok=" + externalRef); + return procedure.execute(context, externalRef); + } + static boolean isEmpty(long[] table, int index) { + return getStatementCount(table, index) == 0 && !hasValue(table, index); + } + static int getStatementCount(long[] table, int index) { + int i = STM_OFFSET + index; + int p1 = BitUtility.getHighInt(table[i]); + int p2 = BitUtility.getLowInt(table[++i]); + if (0 == p1) + return 0; + else if (0 == p2) + return 1; + int predicateIndex = getPredicateIndex(table, index); + if (0 == predicateIndex) + return 2; + return 3; + } + private static int makeCompleteObjectRef(int oRef, ClusterI.CompleteTypeEnum completeType) { + int ref; + if (oRef > 0) { + int resourceIndex = oRef; + int clusterIndex = 0; + ref = ClusterTraits.completeReferenceMake(completeType.getValue(), resourceIndex, clusterIndex); + } else { + assert(oRef < 0); + assert(!ClusterTraits.isFlat(oRef)); + ref = (completeType.getValue() <<30) | (oRef & 0x3FFFFFFF); + } + return ref; + } + static int addStatement(long[] table, int index, int pRef, int oRef + , PredicateTable pt, ObjectTable ot + , ClusterI.CompleteTypeEnum completeType, CompleteTable ct) + throws DatabaseException { + assert (0 != pRef); + assert (0 != oRef); + if (ClusterI.CompleteTypeEnum.NotComplete != completeType) { + int cRef = makeCompleteObjectRef(oRef, completeType); + int ctr = getCompleteObjectRef(table, index); + if (0 == ctr) + setCompleteObjectRef(table, index, cRef); + else { + int nRef; + if (ctr == cRef) + return -1; // old complete + else if (ClusterTraits.completeReferenceIsMultiple(ctr)) { + nRef = ct.addComplete(ctr, cRef); + if (0 == nRef) + return -1; // old complete + } else { + nRef = ct.createCompleteArraySet(ctr, cRef); + } + setCompleteObjectRef(table, index, nRef); + } + return 0; // added to complete + } + int i = STM_OFFSET + index; + int p1 = BitUtility.getHighInt(table[i]); + int o1 = BitUtility.getLowInt(table[i]); + if (0 == p1) { + table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef); + return 0; // added to stm cache + } else if (p1 == pRef && o1 == oRef) + return -1; // same statement + int p2 = BitUtility.getHighInt(table[++i]); + int o2 = BitUtility.getLowInt(table[i]); + if (0 == p2) { + table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef); + return 0; // added to stm cache + } else if (p2 == pRef && o2 == oRef) + return -1; // same statement + int predicateIndex = getPredicateIndex(table, index); + if (0 == predicateIndex) { + if (p1 == p2) { + int objectIndex = ot.createObjectSet(o1, o2); + assert (0 != objectIndex); + int[] os = new int[1]; + os[0] = ClusterTraits.statementIndexMake(objectIndex); + int[] ps = new int[1]; + ps[0] = p1; + predicateIndex = pt.createPredicateSet(ps, os); + } else { + int[] os = new int[2]; + os[0] = o1; + os[1] = o2; + int[] ps = new int[2]; + ps[0] = p1; + ps[1] = p2; + predicateIndex = pt.createPredicateSet(ps, os); + } + assert (0 != predicateIndex); + setPredicateIndex(table, index, predicateIndex); + } + assert (0 != predicateIndex); + return predicateIndex; + } + + static boolean removeStatement(long[] table, int index, int pRef, int oRef, + ClusterI.CompleteTypeEnum completeType, CompleteTable ct) + throws DatabaseException { + assert (0 != pRef); + assert (0 != oRef); + if (completeType != ClusterI.CompleteTypeEnum.NotComplete) { + int completeRef = ResourceElement.getCompleteObjectRef(table, index); + if (0 != completeRef) { + ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef); + if (completeType == completeType2) { + int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef); + int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef); + if (0 == clusterIndex) { + if (oRef == resourceIndex) { + ResourceElement.setCompleteObjectRef(table, index, 0); + return true; // statement removed + } + } else { + int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex); + if (oRef == externalRef) { + ResourceElement.setCompleteObjectRef(table, index, 0); + return true; // statement removed + } + } + } else if (completeType2 == ClusterI.CompleteTypeEnum.NotComplete) { // multiple complete type references + int cRef = makeCompleteObjectRef(oRef, completeType); + int oldSize = ct.getCompleteSetSize(completeRef); + int newSize = ct.removeComplete(completeRef, cRef); + if (oldSize == newSize) + return false; // not removed + else if (newSize == 1) { + cRef = ct.removeLast(completeRef); + ResourceElement.setCompleteObjectRef(table, index, cRef); + } + return true; + } + } + } + int i = STM_OFFSET + index; + int p1 = BitUtility.getHighInt(table[i]); + int o1 = BitUtility.getLowInt(table[i]); + if (0 == p1) + return false; // no statements cached + else if (p1 == pRef && o1 == oRef) { + table[i] = table[i + 1]; + // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away + table[i + 1] = 0; + return true; // statement removed + } + int p2 = BitUtility.getHighInt(table[++i]); + int o2 = BitUtility.getLowInt(table[i]); + if (0 == p2) + return false; // no match + else if (p2 == pRef && o2 == oRef) { + // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away + table[i] = 0; + return true; // statement removed + } + return false; + } +} + +public final class ResourceTable extends Table { + public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase) { + super(TableFactory.getLongFactory(), sizeListener, header, headerBase); + } + + public ResourceTable(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 = ResourceElement.getSizeOf(); + int resourceIndex = createNewElement(SIZE); + assert (0 != resourceIndex); + final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE); + ResourceElement.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 (ResourceElement.isEmpty(getTable(), realIndex)) + return; + } if (resourceIndex == tableCount+1) { + createResource(); + return; + } + throw new InternalError("Trying to create resource with illegal index=" + resourceIndex); + } + +// void deleteResource(int resourceIndex) { +// int realIndex = checkIndexAndGetRealIndex(resourceIndex); +// ResourceElement.destruct(getTable(), realIndex); +// decResourceCount(); +// } + + public int getCompleteObjectRef(int resourceIndex) { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + return ResourceElement.getCompleteObjectRef(getTable(), realIndex); + } + + public int getPredicateIndex(int resourceIndex) { + int i = (resourceIndex<<2) - 3 + offset; + return (int)table[i]; + } + + public void setPredicateIndex(int resourceIndex, int predicateIndex) { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + ResourceElement.setPredicateIndex(getTable(), realIndex, predicateIndex); + } + + public byte[] getValue(ValueTable valueTable, int resourceIndex) + throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + return ResourceElement.getValue(valueTable, getTable(), realIndex); + } + +//KRAA: +// int getString(ValueTable valueTable, int resourceIndex, char[] chars) +// throws DatabaseException { +// //int realIndex = checkIndexAndGetRealIndex(resourceIndex); +// return ResourceElement.getString(valueTable, getTable(), 4 * resourceIndex - 3 + offset, chars); +// } + + public boolean hasValue(int resourceIndex) { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + return ResourceElement.hasValue(getTable(), realIndex); + } + +// boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) { +// int realIndex = checkIndexAndGetRealIndex(resourceIndex); +// return ResourceElement.hasValue(valueTable, getTable(), realIndex, value); +// } + + public boolean removeValue(ValueTable valueTable, int resourceIndex) { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + boolean ret = ResourceElement.removeValue(valueTable, getTable(), realIndex); +// if (ret && !ResourceElement.isUsed(getTable(), realIndex)) +// decResourceCount(); + return ret; + } + + public void setValue(ValueTable valueTable, int resourceIndex, byte[] value, int length) { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + ResourceElement.setValue(valueTable, getTable(), realIndex, value, length); + } + + public boolean isValueEx(ValueTable valueTable, int resourceIndex) { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + return ResourceElement.isValueEx(valueTable, getTable(), realIndex); + } + + public void setValueEx(ValueTable valueTable, int resourceIndex) { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + ResourceElement.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); + } + void analyse() { + + final int tsize = getTableSize(); + final int esize = ResourceElement.getSizeOf(); + long[] table = getTable(); + for (int i = getTableBase(); i < getTableBase() + tsize; i += esize) { + if (ResourceElement.isUsed(getTable(), i)) { + System.out.println(" -" + Long.toHexString(table[i]) + " " + Long.toHexString(table[i+1]) + " " + Long.toHexString(table[i+2]) + " " + Long.toHexString(table[i+3])); + } + } + + } + + public boolean foreachResource(ClusterI.ObjectProcedure procedure, Context context, + ClusterSupport support, Modifier modifier) throws DatabaseException { + final int tsize = getTableSize(); +// final int rsize = getResourceCount(); + final int esize = ResourceElement.getSizeOf(); + //int count = 0; + int key = ZERO_SHIFT; + for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) { + if (ResourceElement.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 boolean foreachPredicate(int resourceIndex + , ClusterI.PredicateProcedure procedure, Context context + , ClusterSupport support, Modifier modifier, CompleteTable ct) + throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + return ResourceElement.foreachPredicate(getTable(), realIndex + , procedure, context, support, modifier, ct); + } + + public int getSingleObject(int resourceIndex, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException { +// return ResourceElement.getSingleObject(table, realIndex, support, pRef, pCompleteType, ct, modifier); + return ResourceElement.getSingleObject(table, 4 * resourceIndex - 3 + offset, support, pRef, pCompleteType, ct, modifier); + } + + public void foreachObject(int resourceIndex, ReadGraphImpl graph, + SyncMultiProcedure procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + ResourceElement.foreachObject(table, realIndex, graph, procedure, support, + pRef, pCompleteType, ct, modifier); + } + + public void foreachObject(int resourceIndex, ReadGraphImpl graph, C context, + SyncContextMultiProcedure procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + ResourceElement.foreachObject(table, realIndex, graph, context, procedure, support, + pRef, pCompleteType, ct, modifier); + } + + public boolean foreachObject(int resourceIndex + , ClusterI.ObjectProcedure procedure, Context context + , ClusterSupport support, Modifier modifier, + int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct) + throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + return ResourceElement.foreachObject(table, realIndex + , procedure, context, support, modifier + , pRef, completeType, ct); + } + public int addStatement(int resourceIndex, int pRef, int oRef, PredicateTable pt, ObjectTable ot + , ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct) + throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + return ResourceElement.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, pCompleteType, ct); + } + + public boolean removeStatementFromCache(int resourceIndex, int pRef, int oRef, + ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct) + throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + boolean ret = ResourceElement.removeStatement(getTable(), realIndex, pRef, oRef, pCompleteType, ct); +// if (ret && !ResourceElement.isUsed(getTable(), realIndex)) +// decResourceCount(); + return ret; + } + + public void removeStatement(int resourceIndex, int pRef, int oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, + PredicateTable pt, ObjectTable ot, ClusterBase cluster, ClusterSupport support) + throws DatabaseException { + int realIndex = checkIndexAndGetRealIndex(resourceIndex); + boolean removed = ResourceElement.removeStatement(getTable(), realIndex, + pRef, oRef, pCompleteType, ct); + if (!removed) + return; + int predicateIndex = ResourceElement.getPredicateIndex(getTable(), realIndex); + if (0 == predicateIndex) { +// if (!ResourceElement.isUsed(getTable(), realIndex)) +// decResourceCount(); + return; + } + GetStatements gs = new GetStatements(ot); + pt.foreachPredicate(predicateIndex, gs, null, null, null); + ArrayList 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)."); + int predicateKey = cluster.makeResourceKey(stm.pRef); + int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey); + ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt); + int pi = ResourceElement.addStatement(getTable(), realIndex, stm.pRef, stm.oIndex, + pt, ot, completeType, ct); + assert(0 >= pi); + } + assert(0 == pt.getPredicateSetSize(predicateIndex)); + ResourceElement.setPredicateIndex(getTable(), realIndex, 0); + } else { + for (int i = 0; i < SIZE; ++i) { + Statement stm = stms.get(i); + int predicateKey = cluster.makeResourceKey(stm.pRef); + int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey); + ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt); + int pIndex = ResourceElement.addStatement(getTable(), realIndex, + stm.pRef, stm.oIndex, pt, ot, completeType, 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 (!ResourceElement.isUsed(getTable(), realIndex)) +// decResourceCount(); + } + + //(i-1)*4+1 + 4 + private int checkIndexAndGetRealIndex(final int INDEX) { + assert(INDEX > 0); + assert(INDEX <= getTableCount()); +// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT; +// final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT; +// return checkIndexAndGetRealIndex(TABLE_INDEX, ResourceElement.getSizeOf()); + return 4 * INDEX - 3 + offset; + } + public void check(ClusterBase cluster) + throws DatabaseException { +// int count = 0; + cluster.checkValueInit(); + long[] table = getTable(); + int ps = getHeader().getOffset() + ZERO_SHIFT; + final int TABLE_SIZE = getTableSize(); + int pe = ps + TABLE_SIZE; + for (int p=ps; p TABLE_SIZE) + throw new ValidationException("Illegal resource index=" + ri); + } + } + int pi = ResourceElement.getPredicateIndex(table, p); + if (0 != pi) { + cluster.checkPredicateIndex(pi); + } + ResourceElement.ValueData vd = new ResourceElement.ValueData(); + ResourceElement.getValueCapacityAndIndex(vd, table, p); + cluster.checkValue(vd.capacity, vd.index); + } + cluster.checkValueFini(); + } + + @Override + public boolean foreach(int setIndex, Procedure procedure, Context context, + ClusterSupport support, Modifier modifier) throws DatabaseException { + throw new UnsupportedOperationException(); + } +} + +class Statement { + Statement(int pRef, int oIndex) { + this.pRef = pRef; + this.oIndex = oIndex; + } + final int pRef; + final int oIndex; +} + +class CalculateStatements +implements ClusterI.PredicateProcedure { + private ObjectTable ot; + private final int sRef; + + CalculateStatements(int sRef, ObjectTable ot) { + this.sRef = sRef; + this.ot = ot; + } + + @Override + public boolean execute(final 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 GetStatements implements PredicateProcedure, ObjectProcedure { + private ObjectTable ot; + private final ArrayList stms = new ArrayList(); + GetStatements(ObjectTable ot) { + this.ot = ot; + } + ArrayList 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 + } + +}