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.Procedure;
21 import org.simantics.db.impl.ClusterSupport;
22 import org.simantics.db.impl.Modifier;
23 import org.simantics.db.impl.Table;
24 import org.simantics.db.impl.TableFactory;
25 import org.simantics.db.impl.TableSizeListener;
27 public final class ValueTableSmall extends Table<byte[]> {
28 private static final boolean DEBUG = ClusterImpl.DEBUG;
29 public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {
30 super(TableFactory.getByteFactory(), sizeListener, header, headerBase);
32 public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, byte[] bytes) {
33 super(TableFactory.getByteFactory(), sizeListener, header, headerBase, bytes);
35 private static final class IndexAndSize {
36 int index; // Real index (zero based) to start of value data.
37 short size; // Size of value data.
39 private IndexAndSize checkIndexAndGetRealIndex(int index) {
40 if (index < ZERO_SHIFT) // Index starts with ZERO_SHIFT.
41 throw new IllegalArgumentException("Underflow, index=" + index);
42 int tableSize = getTableSize();
43 if (index >= tableSize) // Element size is at least two (one byte length and one byte data).
44 throw new IllegalArgumentException("Overflow, index=" + index);
45 int i = index + offset;
46 byte[] table = getTable();
47 IndexAndSize is = new IndexAndSize();
50 throw new IllegalArgumentException("Removed, index=" + index);
51 if (is.size < 0) // two byte size
52 is.size = (short)(((is.size & 0x7F) << 8) | (table[i++] & 0xFF));
54 if (is.index + is.size > tableSize) // Element size too big.
55 throw new IllegalArgumentException("Illegal size, index=" + is.index + " size=" + is.size);
58 public byte[] getValue(int valueIndex) {
59 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
60 byte[] value = new byte[is.size];
61 System.arraycopy(table, is.index, value, 0, is.size);
63 System.out.println("ValueTableSmall.getValue " + valueIndex + " " + Arrays.toString(value));
66 char[] getString(int valueIndex) {
67 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
68 final int size = is.size-1;
69 char[] t = new char[size];
71 for(int i=0; i<size; i++, ++start)
72 t[i] = (char)table[start];
75 int setValue(int valueIndex, byte[] value, int offset, int length) {
76 if (valueIndex != 0) // Modify old value.
77 removeValue(valueIndex);
78 return createValue(value, offset, length);
80 int createValue(byte[] value, int voffset, int vsize) {
81 if (vsize < 1 || vsize > (1<<15)-1)
82 throw new IllegalArgumentException("Illegal internal value size=" + vsize + ".");
88 int valueIndex = createNewElement(size);
89 int i = checkIndexAndGetRealIndex(valueIndex, 1);
91 table[i++] = (byte)((vsize >>> 8) | 1<<7); // msb
92 table[i++] = (byte)(vsize & 0xFF); // lsb
94 table[i++] = (byte)vsize;
95 System.arraycopy(value, voffset, table, i, vsize);
98 void removeValue(int valueIndex) {
99 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
100 int length = is.size;
101 int index = is.index;
102 if (is.size > 0x7F) {
111 deleteOldElement(valueIndex, length);
113 // boolean isEqual(int valueIndex, byte[] value, int voffset, int vsize) {
114 // return isEqual(valueIndex, value, 0, value.length);
116 private TreeMap<Integer, Integer> valueMap =
117 new TreeMap<Integer, Integer>();
119 private int VALUE_SIZE = 0;
120 private int VALUE_OFFSET = 0;
121 public void checkValueInit()
122 throws DatabaseException {
124 final int s = getTableSize();
125 final int c = getTableCapacity();
127 throw new ValidationException("Illegal value table size=" + s + " cap=" + c);
129 VALUE_OFFSET = getTableBase() - ValueTableSmall.ZERO_SHIFT;
131 public void checkValue(int capacity, int index)
132 throws DatabaseException {
133 if (0 == capacity && 0 == index)
136 throw new ValidationException("Illegal resource value capacity=" + capacity);
138 throw new ValidationException("Illegal resource value index=" + index);
139 if (VALUE_SIZE < capacity + index + VALUE_OFFSET)
140 throw new ValidationException("Illegal resource value c=" + capacity +
141 " i=" + index + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);
142 // Duplicate index is allowed because new index is created only if new size is greater than old.
143 Integer valueCap = valueMap.get(index);
144 if (null == valueCap)
145 valueMap.put(index, capacity);
146 else if (capacity > valueCap)
147 valueMap.put(index, capacity);
149 valueMap.put(index, valueCap);
151 public void checkValueFini()
152 throws DatabaseException {
154 for (Map.Entry<Integer, Integer> e : valueMap.entrySet()) {
156 int c = e.getValue();
157 int cur = VALUE_OFFSET + i;
159 throw new ValidationException("Index error with resource value c=" + c +
160 " i=" + i + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);
165 public <Context> boolean foreach(int setIndex, Procedure procedure, Context context, ClusterSupport support, Modifier modifier) throws DatabaseException {
166 throw new UnsupportedOperationException();