]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/PredicateTable.java
Fail safe import fixes made by Antti
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / PredicateTable.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.procore.cluster;
13
14 import gnu.trove.map.hash.TIntIntHashMap;
15 import gnu.trove.procedure.TIntIntProcedure;
16 import gnu.trove.set.hash.TIntHashSet;
17
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.exception.ValidationException;
20 import org.simantics.db.impl.ClusterBase;
21 import org.simantics.db.impl.ClusterI;
22 import org.simantics.db.impl.ClusterI.ObjectProcedure;
23 import org.simantics.db.impl.ClusterI.PredicateProcedure;
24 import org.simantics.db.impl.ClusterI.Procedure;
25 import org.simantics.db.impl.ClusterSupport;
26 import org.simantics.db.impl.Modifier;
27 import org.simantics.db.impl.Table;
28 import org.simantics.db.impl.TableFactory;
29 import org.simantics.db.impl.TableIntAllocatorAdapter;
30 import org.simantics.db.impl.TableSizeListener;
31 import org.simantics.db.procore.cluster.TableIntArraySet2.Tables;
32
33 public final class PredicateTable extends Table<int[]> {
34         
35         final TableIntAllocatorAdapter allocator;
36         
37     public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase) {
38         super(TableFactory.getIntFactory(), sizeListener, header, headerBase);
39         allocator = new TableIntAllocatorAdapter(this);
40     }
41     public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {
42         super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);
43         allocator = new TableIntAllocatorAdapter(this);
44     }
45     int createPredicateSet(int[] ps, int[] os)
46     throws DatabaseException {
47         int hashBase = TableIntArraySet2.create(ps, os, allocator);
48         return convertRealIndexToTableIndex(hashBase);
49     }
50     void deletePredicateSet(int predicateIndex) {
51         int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
52         if (TableIntArraySet2.isArraySet(getTable(), hashBase)) {
53             int capacity = TableIntArraySet2.getAllocatedSize(getTable(), hashBase);
54             int elementIndex = predicateIndex - TableIntArraySet2.HeaderSize;
55             deleteOldElement(elementIndex, capacity);
56         } else {
57             int capacity = TableIntSet2.getAllocatedSize(getTable(), hashBase);
58             int elementIndex = predicateIndex - TableIntSet2.HeaderSize;
59             deleteOldElement(elementIndex, capacity);
60         }
61     }
62     public int getPredicateSetSize(int predicateIndex) {
63         int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
64         if (TableIntArraySet2.isArraySet(getTable(), hashBase))
65             return TableIntArraySet2.getSize(getTable(), hashBase);
66         else
67             return TableIntSet2.getSize(getTable(), hashBase);
68     }
69     public int getObjectIndex(int predicateIndex, int pRef) {
70         int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
71         if (TableIntArraySet2.isArraySet(table, hashBase))
72             return TableIntArraySet2.get(table, hashBase, pRef);
73         else {
74             return TableIntSet2.get(table, hashBase, pRef);
75         }
76     }
77     private int addPredicateArray(int predicateIndex, int hashBase, int pReference, int oReference, ObjectTable ot)
78     throws DatabaseException {
79         int newHashBase;
80         int objectIndex = TableIntArraySet2.get(getTable(), hashBase, pReference);
81         if (0 == objectIndex) {
82             newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, oReference, allocator);
83         } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
84             int oRef = objectIndex;
85             if (oRef == oReference) {
86                 return 0; // old direct object
87             }
88             objectIndex = ot.createObjectSet(oRef, oReference);
89             assert(0 != objectIndex);
90             int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex);
91             newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);
92         } else {
93             int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference);
94             if (0 == newObjectIndex)
95                 return 0; // old indirect object
96             newObjectIndex = ClusterTraits.statementIndexMake(newObjectIndex);
97             newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);
98             if (newHashBase == 0)
99                 return hashBase;
100         }
101         int TABLE_SIZE = TableIntArraySet2.getSize(getTable(), newHashBase);
102         if (TABLE_SIZE > 5)
103             return convertToPredicateSet(predicateIndex, newHashBase);
104         return newHashBase;
105     }
106     private int convertToPredicateSet(int predicateIndex, int hashBase) {
107         Tables tables = TableIntArraySet2.getInts(getTable(), hashBase);
108         this.deletePredicateSet(predicateIndex);
109         int newHashBase = TableIntSet2.create(tables.keys, tables.vals, allocator);
110         assert(0 != newHashBase);
111         return newHashBase;
112     }
113     private int addPredicateSet(int hashBase, int pReference, int oReference, ObjectTable ot)
114     throws DatabaseException {
115         int objectIndex = TableIntSet2.get(getTable(), hashBase, pReference);
116         int newHashBase;
117         if (0 == objectIndex) {
118             newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, oReference, allocator);
119         } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
120             int oRef = objectIndex;
121             if (oRef == oReference) {
122                 return 0; // old direct object
123             }
124             objectIndex = ot.createObjectSet(oRef, oReference);
125             assert(0 != objectIndex);
126             int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex);
127             newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator);
128             assert(0 != newHashBase);
129         } else {
130             int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference);
131             if (0 == newObjectIndex)
132                 return 0; // old indirect object
133             int stmIndex = ClusterTraits.statementIndexMake(newObjectIndex);
134             newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, stmIndex, allocator);
135             if (newHashBase == 0)
136                 return hashBase; // new object added to old predicate (set)
137         }
138         return newHashBase;
139     }
140     /**
141      * @param predicateIndex
142      * @param pReference
143      * @return zero if element was not added or predicate index.
144      * Predicate index will change if new space is allocated.
145      */
146     public int addPredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot)
147     throws DatabaseException {
148         int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
149         int newHashBase;
150         if (TableIntArraySet2.isArraySet(getTable(), hashBase))
151            newHashBase = addPredicateArray(predicateIndex, hashBase, pReference, oReference, ot);
152         else
153            newHashBase = addPredicateSet(hashBase, pReference, oReference, ot);
154         if (0 == newHashBase)
155             return 0; // not modified
156         return convertRealIndexToTableIndex(newHashBase);
157     }
158     public enum Status {
159         NothingRemoved,
160         ObjectRemoved,
161         PredicateRemoved;
162     }
163     /**
164      * @param predicateIndex
165      * @param oResourceIndex
166      * @return null if nothing was removed. Status if either object or both
167      * object and predicate were removed. 
168      */
169     public Status removePredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot)
170     throws DatabaseException {
171         int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
172         int[] table = getTable();
173         if (TableIntArraySet2.isArraySet(table, hashBase)) {
174             int objectIndex = TableIntArraySet2.get(table, hashBase, pReference);
175             if (0 == objectIndex) {
176                 return Status.NothingRemoved;
177             } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
178                 int oRef = objectIndex;
179                 if (oRef != oReference)
180                     return Status.NothingRemoved;
181                 if (TableIntArraySet2.removeInt(table, hashBase, pReference))
182                     return Status.PredicateRemoved;
183                 else
184                     throw new DatabaseException("Internal error during remove.");
185             } else {
186                 int oIndex = ClusterTraits.statementIndexGet(objectIndex);
187                 int nO = ot.getObjectSetSize(oIndex);
188                 if (nO < 1)
189                     throw new DatabaseException("Illegal object set size="+nO);
190                 int nObject = ot.removeObject(objectIndex, oReference);
191                 if (nObject == 0) {
192                     ot.deleteObjectSet(oIndex);
193                     if (TableIntArraySet2.removeInt(table, hashBase, pReference))
194                         return Status.PredicateRemoved;
195                     else
196                         throw new DatabaseException("Internal error during remove (2).");
197                 } else if (nO == nObject)
198                     return Status.NothingRemoved;
199                 else
200                     return Status.ObjectRemoved;
201             }
202         } else {
203             int objectIndex = TableIntSet2.get(table, hashBase, pReference);
204             if (0 == objectIndex) {
205                 return Status.NothingRemoved;
206             } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) {
207                 int oRef = objectIndex;
208                 if (oRef != oReference)
209                     return Status.NothingRemoved;
210                 if (TableIntSet2.removeInt(table, hashBase, pReference))
211                     return Status.PredicateRemoved;
212                 else
213                     throw new DatabaseException("Internal error during remove (3).");
214             } else {
215                 int oIndex = ClusterTraits.statementIndexGet(objectIndex);
216                 int nO = ot.getObjectSetSize(oIndex);
217                 if (nO < 1)
218                     throw new DatabaseException("Illegal object set size="+nO);
219                 int nObject = ot.removeObject(objectIndex, oReference);
220                 if (nObject == 0) {
221                     ot.deleteObjectSet(oIndex);
222                     if (TableIntSet2.removeInt(table, hashBase, pReference))
223                         return Status.PredicateRemoved;
224                     else
225                         throw new DatabaseException("Internal error during remove (4).");
226                 } else if (nO == nObject)
227                     return Status.NothingRemoved;
228                 else
229                     return Status.ObjectRemoved;
230             }
231         }
232     }
233     public <Context> boolean foreachPredicate(int predicateIndex
234             , ClusterI.PredicateProcedure<Context> procedure
235             , Context context, ClusterSupport support, Modifier modifier)
236     throws DatabaseException {
237         final int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0);
238         boolean ret;
239         if (TableIntArraySet2.isArraySet(getTable(), hashBase))
240             ret = TableIntArraySet2.foreachInt(getTable(), hashBase, procedure, context, modifier);
241         else
242             ret = TableIntSet2.foreachInt(getTable(), hashBase, procedure, context, modifier);
243         return ret;
244     }
245     private void checkEntry(ClusterBase cluster, int[] table, int index)
246     throws DatabaseException {
247         assert(ClusterTraits.statementIndexIsDirect(table[index]));
248         int dr = table[index];
249         cluster.checkDirectReference(dr);
250         assert(table[index+1] != 0);
251         if (ClusterTraits.statementIndexIsDirect(table[index+1])) {
252                 cluster.checkDirectReference(table[index+1]);
253         } else {
254                 cluster.checkObjectSetReference(table[index+1]);
255         }
256     }
257     private TIntHashSet checkIndexSet = null;
258         public void check(ClusterBase cluster)
259         throws DatabaseException {
260         if (null == checkIndexSet)
261             checkIndexSet = new TIntHashSet();
262         else
263             checkIndexSet.clear();
264         int count = 0;
265         int[] table = getTable();
266         int ps = getHeader().getOffset() + ZERO_SHIFT;
267         int pe = ps + getTableSize();
268         for (int p=ps; p<pe;) {
269             int cap = p++;
270             if (table[cap] >= 0) {
271                 int use = p++;
272                 int fre = p++;
273                 int max = p++;
274                 assert(table[cap] >= table[use] + table[fre]);
275                 assert(table[max] == table[cap] >> 1);
276                 assert(table[max]+1 >= table[use]);
277                 checkIndexSet.add(p - ps);
278                 for (int e = p + table[cap]*2; p<e; p+=2) {
279                     if (!IntHashTrait.isFull(table[p])) 
280                         assert(table[p+1]==0);
281                     else
282                         checkEntry(cluster, table, p);
283                 }
284             } else {
285                 final int size = -table[cap];
286                 assert(size > 0);
287                 boolean free = false;
288                 checkIndexSet.add(p - ps);
289                 for (int e = p + size*2; p<e; p+=2) {
290                     if (free) {
291                         assert(table[p] == 0);
292                         assert(table[p+1] == 0);
293                     }
294                     else if (table[p] == 0) {
295                         assert(table[p+1] == 0);
296                         free = true;
297                     } else
298                         checkEntry(cluster, table, p);
299                 }
300             }
301             count++;
302         }
303                 assert(getHeader().getCount() <= count);  // deleted objects are not recognized
304         }
305     public final void checkPredicateSetIndex(ClusterBase cluster, int i)
306     throws DatabaseException {
307         if (null == checkIndexSet)
308             check(cluster); // builds checkIndexSet
309         if (!checkIndexSet.contains(i-ZERO_SHIFT))
310             throw new ValidationException("Illegal predicate set index=" + i);
311     }
312     public void printDebugInfo() {
313         //int count = 0;
314         int[] table = getTable();
315         int ps = getHeader().getOffset() + ZERO_SHIFT;
316         int pe = ps + getTableSize();
317         TIntIntHashMap stat = new TIntIntHashMap();
318         TIntIntHashMap stat2 = new TIntIntHashMap();
319         for (int p=ps; p<pe;) {
320             int cap = p++;
321             if (table[cap] >= 0) {
322                 int use = p++;
323                 int fre = p++;
324                 int max = p++;
325                 assert(table[cap] >= table[use] + table[fre]);
326                 assert(table[max] == table[cap] >> 1);
327                 p += table[cap]*2;
328                 int val = stat.get(table[use]) + 1;
329                 stat.put(table[use], val);
330             } else {
331                 final int size = -table[cap];
332                 int val = stat2.get(size) + 1;
333                 stat2.put(size, val);
334                 p += size*2;
335             }
336             //count++;
337         }
338         //assert(getHeader().getCount() == count);
339         stat.forEachEntry(new TIntIntProcedure() {
340             @Override
341             public boolean execute(int a, int b) {
342                 System.out.println("predicate set capacity " + a + " instance count " + b);
343                 return true;
344             }
345         });
346         stat2.forEachEntry(new TIntIntProcedure() {
347             @Override
348             public boolean execute(int a, int b) {
349                 System.out.println("predicate array set capacity " + a + " instance count " + b);
350                 return true;
351             }
352         });
353   }
354     @Override
355     public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
356             ClusterSupport support, Modifier modifier) throws DatabaseException {
357         return foreachPredicate(setIndex, (PredicateProcedure<Context>)procedure, context, support, modifier);
358     }
359 }