1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.procore.cluster;
14 import java.util.Arrays;
16 import java.util.TreeMap;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.exception.ValidationException;
20 import org.simantics.db.impl.ClusterI.ObjectProcedure;
21 import org.simantics.db.impl.ClusterI.Procedure;
22 import org.simantics.db.impl.ClusterSupport;
23 import org.simantics.db.impl.Modifier;
24 import org.simantics.db.impl.Table;
25 import org.simantics.db.impl.TableFactory;
26 import org.simantics.db.impl.TableSizeListener;
28 public final class ValueTableSmall extends Table<byte[]> {
29 private static final boolean DEBUG = ClusterImpl.DEBUG;
30 public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {
31 super(TableFactory.getByteFactory(), sizeListener, header, headerBase);
33 public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, byte[] bytes) {
34 super(TableFactory.getByteFactory(), sizeListener, header, headerBase, bytes);
36 private static final class IndexAndSize {
37 int index; // Real index (zero based) to start of value data.
38 short size; // Size of value data.
40 private IndexAndSize checkIndexAndGetRealIndex(int index) {
41 if (index < ZERO_SHIFT) // Index starts with ZERO_SHIFT.
42 throw new IllegalArgumentException("Underflow, index=" + index);
43 int tableSize = getTableSize();
44 if (index >= tableSize) // Element size is at least two (one byte length and one byte data).
45 throw new IllegalArgumentException("Overflow, index=" + index);
46 int i = index + offset;
47 byte[] table = getTable();
48 IndexAndSize is = new IndexAndSize();
51 throw new IllegalArgumentException("Removed, index=" + index);
52 if (is.size < 0) // two byte size
53 is.size = (short)(((is.size & 0x7F) << 8) | (table[i++] & 0xFF));
55 if (is.index + is.size > tableSize) // Element size too big.
56 throw new IllegalArgumentException("Illegal size, index=" + is.index + " size=" + is.size);
59 public byte[] getValue(int valueIndex) {
60 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
61 byte[] value = new byte[is.size];
62 System.arraycopy(table, is.index, value, 0, is.size);
64 System.out.println("ValueTableSmall.getValue " + valueIndex + " " + Arrays.toString(value));
67 char[] getString(int valueIndex) {
68 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
69 final int size = is.size-1;
70 char[] t = new char[size];
72 for(int i=0; i<size; i++, ++start)
73 t[i] = (char)table[start];
76 int setValue(int valueIndex, byte[] value, int offset, int length) {
77 if (valueIndex != 0) // Modify old value.
78 removeValue(valueIndex);
79 return createValue(value, offset, length);
81 int createValue(byte[] value, int voffset, int vsize) {
82 if (vsize < 1 || vsize > (1<<15)-1)
83 throw new IllegalArgumentException("Illegal internal value size=" + vsize + ".");
89 int valueIndex = createNewElement(size);
90 int i = checkIndexAndGetRealIndex(valueIndex, 1);
92 table[i++] = (byte)((vsize >>> 8) | 1<<7); // msb
93 table[i++] = (byte)(vsize & 0xFF); // lsb
95 table[i++] = (byte)vsize;
96 System.arraycopy(value, voffset, table, i, vsize);
99 void removeValue(int valueIndex) {
100 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
101 int length = is.size;
102 int index = is.index;
103 if (is.size > 0x7F) {
112 deleteOldElement(valueIndex, length);
114 // boolean isEqual(int valueIndex, byte[] value, int voffset, int vsize) {
115 // return isEqual(valueIndex, value, 0, value.length);
117 private TreeMap<Integer, Integer> valueMap =
118 new TreeMap<Integer, Integer>();
120 private int VALUE_SIZE = 0;
121 private int VALUE_OFFSET = 0;
122 public void checkValueInit()
123 throws DatabaseException {
125 final int s = getTableSize();
126 final int c = getTableCapacity();
128 throw new ValidationException("Illegal value table size=" + s + " cap=" + c);
130 VALUE_OFFSET = getTableBase() - ValueTableSmall.ZERO_SHIFT;
132 public void checkValue(int capacity, int index)
133 throws DatabaseException {
134 if (0 == capacity && 0 == index)
137 throw new ValidationException("Illegal resource value capacity=" + capacity);
139 throw new ValidationException("Illegal resource value index=" + index);
140 if (VALUE_SIZE < capacity + index + VALUE_OFFSET)
141 throw new ValidationException("Illegal resource value c=" + capacity +
142 " i=" + index + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);
143 // Duplicate index is allowed because new index is created only if new size is greater than old.
144 Integer valueCap = valueMap.get(index);
145 if (null == valueCap)
146 valueMap.put(index, capacity);
147 else if (capacity > valueCap)
148 valueMap.put(index, capacity);
150 valueMap.put(index, valueCap);
152 public void checkValueFini()
153 throws DatabaseException {
155 for (Map.Entry<Integer, Integer> e : valueMap.entrySet()) {
157 int c = e.getValue();
158 int cur = VALUE_OFFSET + i;
160 throw new ValidationException("Index error with resource value c=" + c +
161 " i=" + i + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);
166 public <Context> boolean foreach(int setIndex, Procedure procedure, Context context, ClusterSupport support, Modifier modifier) throws DatabaseException {
167 throw new UnsupportedOperationException();