]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ValueTableSmall.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / ValueTableSmall.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.db.procore.cluster;\r
13 \r
14 import java.util.Arrays;\r
15 import java.util.Map;\r
16 import java.util.TreeMap;\r
17 \r
18 import org.simantics.db.exception.DatabaseException;\r
19 import org.simantics.db.exception.ValidationException;\r
20 import org.simantics.db.impl.ClusterI.ObjectProcedure;\r
21 import org.simantics.db.impl.ClusterI.Procedure;\r
22 import org.simantics.db.impl.ClusterSupport;\r
23 import org.simantics.db.impl.Modifier;\r
24 import org.simantics.db.impl.Table;\r
25 import org.simantics.db.impl.TableFactory;\r
26 import org.simantics.db.impl.TableSizeListener;\r
27 \r
28 public final class ValueTableSmall extends Table<byte[]> {\r
29     private static final boolean DEBUG = ClusterImpl.DEBUG;\r
30     public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {\r
31         super(TableFactory.getByteFactory(), sizeListener, header, headerBase);\r
32     }\r
33     public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, byte[] bytes) {\r
34         super(TableFactory.getByteFactory(), sizeListener, header, headerBase, bytes);\r
35     }\r
36     private static final class IndexAndSize {\r
37         int index; // Real index (zero based) to start of value data.\r
38         short size; // Size of value data.\r
39     }\r
40     private IndexAndSize checkIndexAndGetRealIndex(int index) {\r
41         if (index < ZERO_SHIFT) // Index starts with ZERO_SHIFT.\r
42             throw new IllegalArgumentException("Underflow, index=" + index);\r
43         int tableSize = getTableSize();\r
44         if (index >= tableSize) // Element size is at least two (one byte length and one byte data).\r
45             throw new IllegalArgumentException("Overflow, index=" + index);\r
46         int i = index + offset;\r
47         byte[] table = getTable();\r
48         IndexAndSize is = new IndexAndSize();\r
49         is.size = table[i++]; \r
50         if (is.size == 0)\r
51                 throw new IllegalArgumentException("Removed, index=" + index);\r
52         if (is.size < 0) // two byte size\r
53                 is.size = (short)(((is.size & 0x7F) << 8) | (table[i++] & 0xFF));\r
54         is.index = i;\r
55         if (is.index + is.size > tableSize) // Element size too big.\r
56                 throw new IllegalArgumentException("Illegal size, index=" + is.index + " size=" + is.size);\r
57         return is;\r
58     }\r
59     public byte[] getValue(int valueIndex) {\r
60         IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);\r
61         byte[] value = new byte[is.size];\r
62         System.arraycopy(table, is.index, value, 0, is.size);\r
63         if (DEBUG)\r
64             System.out.println("ValueTableSmall.getValue " + valueIndex + " " + Arrays.toString(value));\r
65         return value;\r
66     }\r
67     char[] getString(int valueIndex) {\r
68         IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);\r
69         final int size = is.size-1;\r
70         char[] t = new char[size];\r
71         int start = is.index;\r
72         for(int i=0; i<size; i++, ++start)\r
73             t[i] = (char)table[start];\r
74         return t;\r
75     }\r
76     int setValue(int valueIndex, byte[] value, int offset, int length) {\r
77         if (valueIndex != 0) // Modify old value.\r
78                 removeValue(valueIndex);\r
79         return createValue(value, offset, length); \r
80     }\r
81     int createValue(byte[] value, int voffset, int vsize) {\r
82         if (vsize < 1 || vsize > (1<<15)-1)\r
83                 throw new IllegalArgumentException("Illegal internal value size=" + vsize + ".");\r
84         int size = vsize;\r
85         if (vsize > 0x7F)\r
86                 size += 2;\r
87         else\r
88                 size += 1;\r
89         int valueIndex = createNewElement(size);\r
90         int i = checkIndexAndGetRealIndex(valueIndex, 1);\r
91         if (vsize > 0x7F) {\r
92                 table[i++] = (byte)((vsize >>> 8) | 1<<7); // msb\r
93                 table[i++] = (byte)(vsize & 0xFF); // lsb\r
94         } else\r
95                 table[i++] = (byte)vsize;\r
96         System.arraycopy(value, voffset, table, i, vsize);\r
97         return valueIndex;\r
98     }\r
99     void removeValue(int valueIndex) {\r
100         IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);\r
101         int length = is.size;\r
102         int index = is.index;\r
103         if (is.size > 0x7F) {\r
104                 length += 2;\r
105                 index -= 2;\r
106                 table[index+1] = 0;\r
107         } else {\r
108                 length += 1;\r
109                 index -= 1;\r
110         }\r
111         table[index] = 0;\r
112         deleteOldElement(valueIndex, length);\r
113     }\r
114 //    boolean isEqual(int valueIndex, byte[] value, int voffset, int vsize) {\r
115 //        return isEqual(valueIndex, value, 0, value.length);\r
116 //    }\r
117     private TreeMap<Integer, Integer> valueMap =\r
118         new TreeMap<Integer, Integer>();\r
119     \r
120     private int VALUE_SIZE = 0;\r
121     private int VALUE_OFFSET = 0;\r
122     public void checkValueInit()\r
123     throws DatabaseException {\r
124         valueMap.clear();\r
125         final int s = getTableSize();\r
126         final int c = getTableCapacity();\r
127         if (s < 0 || s > c)\r
128             throw new ValidationException("Illegal value table size=" + s + " cap=" + c);\r
129         VALUE_SIZE = s;\r
130         VALUE_OFFSET = getTableBase() - ValueTableSmall.ZERO_SHIFT; \r
131     }\r
132     public void checkValue(int capacity, int index)\r
133     throws DatabaseException {\r
134         if (0 == capacity && 0 == index)\r
135             return;\r
136         if (capacity < 1)\r
137             throw new ValidationException("Illegal resource value capacity=" + capacity);\r
138         if (index < 1)\r
139             throw new ValidationException("Illegal resource value index=" + index);\r
140         if (VALUE_SIZE < capacity + index + VALUE_OFFSET)\r
141             throw new ValidationException("Illegal resource value c=" + capacity +\r
142                     " i=" + index + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);\r
143         // Duplicate index is allowed because new index is created only if new size is greater than old.\r
144         Integer valueCap = valueMap.get(index);\r
145         if (null == valueCap)\r
146             valueMap.put(index, capacity);\r
147         else if (capacity > valueCap)\r
148             valueMap.put(index, capacity);\r
149         else\r
150             valueMap.put(index, valueCap);\r
151     }\r
152     public void checkValueFini()\r
153     throws DatabaseException {\r
154         int last = 0;\r
155         for (Map.Entry<Integer, Integer> e : valueMap.entrySet()) {\r
156             int i = e.getKey();\r
157             int c = e.getValue();\r
158             int cur = VALUE_OFFSET + i;\r
159             if (last > cur)\r
160                 throw new ValidationException("Index error with resource value c=" + c +\r
161                         " i=" + i + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);\r
162             last = cur + c;\r
163         }\r
164     }\r
165     @Override\r
166     public <Context> boolean foreach(int setIndex, Procedure procedure, Context context, ClusterSupport support, Modifier modifier) throws DatabaseException {\r
167         throw new UnsupportedOperationException();\r
168     }\r
169 \r
170 }\r