]> gerrit.simantics Code Review - simantics/platform.git/blob - db/impl/Table.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / db / impl / Table.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.impl;
13
14 import org.simantics.db.exception.DatabaseException;
15 import org.simantics.db.impl.ClusterI.Procedure;
16 import org.simantics.db.service.Bytes;
17
18 interface TableFactoryI<TableType> {
19     TableType newTable(int size);
20     boolean isEqual(TableType t1, int t1Start, int size, TableType t2, int t2Start);
21 }
22
23 class ByteFactory implements TableFactoryI<byte[]> {
24     @Override
25     public byte[] newTable(int size) {
26         return new byte[size];
27     }
28
29     @Override
30     public boolean isEqual(byte[] t1, int start, int size, byte[] t2, int start2) {
31         for (int i=0; i<size; ++i)
32             if (t1[start + i] != t2[start2 + i])
33                 return false;
34         return true;
35     }
36 }
37
38 class IntFactory implements TableFactoryI<int[]> {
39     @Override
40     public int[] newTable(int size) {
41         return new int[size];
42     }
43
44     @Override
45     public boolean isEqual(int[] t1, int start, int size, int[] t2, int start2) {
46         for (int i=0; i<size; ++i)
47             if (t1[start + i] != t2[start2 + i])
48                 return false;
49         return true;
50     }
51 }
52
53 class LongFactory implements TableFactoryI<long[]> {
54     @Override
55     public long[] newTable(int size) {
56         return new long[size];
57     }
58
59     @Override
60     public boolean isEqual(long[] t1, int start, int size, long[] t2, int start2) {
61         for (int i=0; i<size; ++i)
62             if (t1[start + i] != t2[start2 + i])
63                 return false;
64         return true;
65     }
66 }
67
68 public abstract class Table<TableType> {
69     private static final int INITIAL_SIZE = 100; // Initial size of the table. Must be greater or equal than header_size;
70     private static final int INCREMENT_SIZE = 1000; // Minimum increment size of the table.
71     protected static final int ZERO_SHIFT = 1; // Indexes are guaranteed not to be zero.
72     final private TableHeader header;
73     final private TableFactoryI<TableType> factory;
74     final private TableSizeListener sizeListener;
75     public int offset; // Offset of table in containing array.
76     public TableType table;
77     protected Table(TableFactoryI<TableType> factory, TableSizeListener sizeListener, int[] header, int headerBase) {
78         this.factory = factory;
79         this.sizeListener = sizeListener;
80         this.header = new TableHeader(header, headerBase);
81         this.offset = -ZERO_SHIFT;
82         newTable(INITIAL_SIZE);
83         this.header.setSize(0);
84         this.header.setCount(0);
85         this.header.setOffset(offset);
86     }
87
88 //    final int size(Object bytes) {
89 //        if(bytes instanceof byte[]) return ((byte[])bytes).length;
90 //        if(bytes instanceof int[]) return ((int[])bytes).length;
91 //        if(bytes instanceof long[]) return ((long[])bytes).length;
92 //        return 0;
93 //    }
94
95     protected Table(TableFactoryI<TableType> factory, TableSizeListener sizeListener, int[] header, int headerBase, TableType bytes) {
96 //        System.out.println("Table size=" + size(bytes) + " header = " + Arrays.toString(Arrays.copyOfRange(header, headerBase, headerBase + 4)));
97         this.factory = factory;
98         this.sizeListener = sizeListener;
99         this.header = new TableHeader(header, headerBase);
100         offset = this.header.getOffset();
101         this.table = bytes;
102     }
103     /**
104      * Create and initialize this with a new table.
105      *
106      * @param capacity of the table. How many elements the table can hold without allocating new space.
107      * @param size of the table. How many elements have been used.
108      * @param count of how many segments has been have been allocated.
109      * @return old table.
110      */
111     final protected TableType createNewTable(int capacity, int size, int count) {
112         TableType t = table;
113         this.offset = -ZERO_SHIFT;
114         newTable(capacity);
115         sizeListener.resized();
116         header.setSize(size);
117         header.setCount(count);
118         header.setOffset(offset);
119         return t;
120     }
121     public final int getTableCapacity() {
122         return header.getCapacity();
123     }
124     public final int getTableSize() {
125         return header.getSize();
126     }
127     public final int getTableCount() {
128         return header.getCount();
129     }
130     protected int convertRealIndexToTableIndex(int realIndex) {
131         return realIndex - offset;
132     }
133     protected final int checkIndexAndGetRealIndex(int index, int size)  {
134         if (index < ZERO_SHIFT)
135             throw new IllegalArgumentException("Underflow, index=" + index);
136         if ((size > 0 && index - ZERO_SHIFT + size > header.getSize()))
137             throw new IllegalArgumentException("Overflow, index=" + index + " size=" + size);
138         return index + offset;
139     }
140     protected final int checkIndexAndGetRealIndexEx(int index, int size)  {
141         if (index < ZERO_SHIFT || size < 1)
142             throw new IllegalArgumentException("Underflow, index=" + index + " size=" + size);
143         if (index - ZERO_SHIFT + size < header.getSize())
144             return index + offset;
145         else if (index - ZERO_SHIFT + size == header.getSize())
146             return -1;
147         else
148             throw new IllegalArgumentException("Underflow, index=" + index + " size=" + size);
149     }
150     final protected void getCopy(int index, byte[] to, int start, int size) {
151         int realIndex = checkIndexAndGetRealIndex(index, size);
152         if (size < 0)
153             throw new IllegalArgumentException("Illgal table size " + size);
154         System.arraycopy(table, realIndex, to, start, size);
155     }
156     final protected void getCopy(int index, char[] to, int start, int size) {
157 //        int realIndex = checkIndexAndGetRealIndex(index, size);
158 //        if (size < 0)
159 //            throw new IllegalArgumentException("Illgal table size " + size);
160         byte[] bs = (byte[])table;
161         start += index+offset+1;
162         for(int i=0;i<size;i++) to[i] = (char)bs[start++];
163 //        System.arraycopy(table, realIndex, to, start, size);
164     }
165     final protected void setCopy(int index, int size, TableType from, int fromStartIndex) {
166 //        System.out.println("setCopy index=" + index + " size=" + size + "fromStartIndex=" + fromStartIndex + "from.length=" + ((byte[])from).length + "table.length=" + ((byte[])table).length);
167         int realIndex = checkIndexAndGetRealIndex(index, size);
168         System.arraycopy(from, fromStartIndex, table, realIndex, size);
169     }
170     final protected boolean isEqual(int index, TableType to, int toStartIndex, int toSize) {
171         int realIndex = checkIndexAndGetRealIndex(index, toSize);
172         return factory.isEqual(table, realIndex, toSize, to, toStartIndex);
173     }
174     /**
175      * @param size of the element (how many table slots is allocated).
176      * @return table index not the real index. To get real index use checkIndexAndGetRealIndex.
177      */
178     final protected int createNewElement(int size) {
179         if (size < 0)
180             throw new IllegalArgumentException("Illegal table size " + size);
181         if (0 == size)
182             return ZERO_SHIFT;
183         int oldSize = header.getSize();
184         int newSize = oldSize + size;
185         if (newSize > header.getCapacity())
186             realloc(newSize);
187         header.setSize(newSize);
188         header.setCount(header.getCount()+1);
189         return ZERO_SHIFT + oldSize;
190     }
191     final protected void deleteOldElement(int index, int size) {
192         checkIndexAndGetRealIndex(index, size);
193         header.setCount(header.getCount()-1);
194     }
195     final protected TableHeader getHeader() {
196         return header;
197     }
198     final protected int getTableBase() {
199         return offset + ZERO_SHIFT;
200     }
201     final protected TableType getTable() {
202         return table;
203     }
204     final protected int getExtra(int index) {
205                 return header.getExtra(index);
206         }
207     final protected void setExtra(int index, int value) {
208                 header.setExtra(index, value);
209         }
210     final private void realloc(int newSize) {
211         int realCapacity = newSize + Math.max(INCREMENT_SIZE, newSize/10);
212         TableType oldTable = table;
213         newTable(realCapacity);
214         sizeListener.resized();
215         int oldBase = getTableBase();
216         offset = -ZERO_SHIFT;
217         header.setOffset(offset);
218         int oldSize = header.getSize();
219         // If zero can cause ArrayIndexOutOfBoundsException because oldBase
220         // (index) can be out of bounds in this case and it is checked even
221         // if olsSize is zero (i.e. number of copied bytes is zero).
222         if (oldSize > 0) {
223                 System.arraycopy(oldTable, oldBase, table, 0, oldSize);
224         }
225     }
226     final private void newTable(int capacity) {
227         table = factory.newTable(capacity);
228         header.setCapacity(capacity);
229         }
230     
231     public <T> int store(T _ret, int retPos) {
232         
233         int off = retPos;
234         
235         if(table instanceof byte[]) {
236             System.arraycopy(table, getTableBase(), _ret, retPos, getHeader().getSize());
237             retPos += getHeader().getSize();
238         } else if(table instanceof int[]) {
239             int[] t = (int[])table;
240             int[] ret = (int[])_ret;
241             for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
242                 int v = t[i];
243                 ret[retPos++] = v;
244 //              Bytes.writeLE(ret, retPos, v);
245 //              retPos += 4;
246             }
247         } else if(table instanceof long[]) {
248             long[] t = (long[])table;
249             long[] ret = (long[])_ret;
250             for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
251                 long v = t[i];
252                 ret[retPos++] = v;
253 //              Bytes.writeLE8(ret, retPos, v);
254 //              retPos += 8;
255             }
256         }
257         getHeader().setOffset(off-1);
258         getHeader().setCapacity(getHeader().getSize());
259         return retPos;
260     }
261     
262     public <T> int storeBytes(byte[] _ret, int off, int retPos) {
263         
264         //int off = retPos;
265         
266         if(table instanceof byte[]) {
267             System.arraycopy(table, getTableBase(), _ret, retPos, getHeader().getSize());
268             retPos += getHeader().getSize();
269         } else if(table instanceof int[]) {
270             int[] t = (int[])table;
271             for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
272                 int v = t[i];
273 //              ret[retPos++] = v;
274                 Bytes.writeLE(_ret, retPos, v);
275                 retPos += 4;
276             }
277         } else if(table instanceof long[]) {
278             long[] t = (long[])table;
279             for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
280                 long v = t[i];
281                 Bytes.writeLE8(_ret, retPos, v);
282                 retPos += 8;
283             }
284         }
285         
286         getHeader().setOffset(off-1);
287         getHeader().setCapacity(getHeader().getSize());
288         return retPos;
289         
290     }
291     
292     public abstract <Context> boolean foreach(int setIndex, Procedure procedure, final Context context, final ClusterSupport support, Modifier modifier) throws DatabaseException;
293     
294 }