]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ResourceTableSmall.java
Fail safe import fixes made by Antti
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / ResourceTableSmall.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 java.util.ArrayList;
15
16 import org.simantics.db.Resource;
17 import org.simantics.db.common.utils.Logger;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.impl.ClusterBase;
20 import org.simantics.db.impl.ClusterI;
21 import org.simantics.db.impl.ClusterI.ObjectProcedure;
22 import org.simantics.db.impl.ClusterI.PredicateProcedure;
23 import org.simantics.db.impl.ClusterI.Procedure;
24 import org.simantics.db.impl.ClusterSupport;
25 import org.simantics.db.impl.ClusterTraitsBase;
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.TableSizeListener;
30 import org.simantics.db.impl.graph.ReadGraphImpl;
31 import org.simantics.db.procedure.AsyncContextMultiProcedure;
32 import org.simantics.db.procedure.AsyncMultiProcedure;
33 import org.simantics.db.procore.cluster.PredicateTable.Status;
34
35
36
37 public final class ResourceTableSmall extends Table<long[]> {
38     public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {
39         super(TableFactory.getLongFactory(), sizeListener, header, headerBase);
40     }
41
42     public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {
43         super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);
44     }
45
46     public int getUsedSize() {
47         return getTableCount();
48     }
49
50     public short createResource() {
51         final int INDEX = getTableCount();
52         final int SIZE = ResourceElementSmall.getSizeOf();
53         int resourceIndex = createNewElement(SIZE);
54         assert (0 != resourceIndex);
55         final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);
56         ResourceElementSmall.construct(getTable(), REAL_INDEX);
57         incResourceCount();
58         return (short)(INDEX + ZERO_SHIFT);
59     }
60
61     void createResource(int resourceIndex) {
62         final int tableCount = getTableCount();
63         if (resourceIndex <= tableCount) { // old index
64             int realIndex = checkIndexAndGetRealIndex(resourceIndex);
65             if (ResourceElementSmall.isEmpty(getTable(), realIndex))
66                 return;
67         } if (resourceIndex == tableCount+1) {
68             createResource();
69             return;
70         }
71         throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);
72     }
73
74     public short getCompleteObjectRef(int resourceIndex) {
75         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
76         return ResourceElementSmall.getCompleteObjectRef(getTable(), realIndex);
77     }
78     
79     public ClusterI.CompleteTypeEnum getCompleteType(int resourceIndex) {
80         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
81         return ResourceElementSmall.getCompleteType(getTable(), realIndex);
82     }
83     
84     public int getPredicateIndex(int resourceIndex) {
85         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
86         return ResourceElementSmall.getPredicateIndex(table, realIndex);
87     }
88
89     public void setPredicateIndex(int resourceIndex, int predicateIndex) {
90         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
91         ResourceElementSmall.setPredicateIndex(getTable(), realIndex, predicateIndex);
92     }
93
94     public byte[] getValue(ValueTableSmall valueTable, int resourceIndex)
95     throws DatabaseException {
96         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
97         return ResourceElementSmall.getValue(valueTable, getTable(), realIndex);
98     }
99 //KRAA:
100 //    char[] getString(ValueTableSmall valueTable, int resourceIndex) {
101 //        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
102 //        return ResourceElementSmall.getString(valueTable, getTable(), realIndex);
103 //    }
104
105     public boolean hasValue(int resourceIndex) {
106         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
107         return ResourceElementSmall.hasValue(getTable(), realIndex);
108     }
109
110 //    boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {
111 //        int realIndex = checkIndexAndGetRealIndex(resourceIndex);
112 //        return ResourceElementSmall.hasValue(valueTable, getTable(), realIndex, value);
113 //    }
114
115     public boolean removeValue(ValueTableSmall valueTable, int resourceIndex) {
116         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
117         boolean ret = ResourceElementSmall.removeValue(valueTable, getTable(), realIndex);
118 //        if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
119 //            decResourceCount();
120         return ret;
121     }
122
123     public void setValue(ValueTableSmall valueTable, int resourceIndex, byte[] value, int length)
124     throws OutOfSpaceException {
125         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
126         ResourceElementSmall.setValue(valueTable, getTable(), realIndex, value, length);
127     }
128
129     public boolean isValueEx(ValueTableSmall valueTable, int resourceIndex) {
130         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
131         return ResourceElementSmall.isValueEx(valueTable, getTable(), realIndex);
132     }
133
134     public void setValueEx(ValueTableSmall valueTable, int resourceIndex) {
135         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
136         ResourceElementSmall.setValueEx(valueTable, getTable(), realIndex);
137     }
138
139     static final int RESOURCE_COUNT_INDEX = 0;
140     static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.
141     static final int CLUSTER_STATUS_INDEX = 2;
142
143     int incResourceCount() {
144         int count = getExtra(RESOURCE_COUNT_INDEX) + 1;
145         setExtra(RESOURCE_COUNT_INDEX, count);
146         return count;
147     }
148
149 //    int decResourceCount() {
150 //        int count = getExtra(RESOURCE_COUNT_INDEX) - 1;
151 //        setExtra(RESOURCE_COUNT_INDEX, count);
152 //        return count;
153 //    }
154
155     public int getResourceCount() {
156         return getExtra(RESOURCE_COUNT_INDEX);
157     }
158     public int getClusterStatus() {
159         return getExtra(CLUSTER_STATUS_INDEX);
160     }
161     public void setClusterStatus(int value) {
162         setExtra(CLUSTER_STATUS_INDEX, value);
163     }
164
165     <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,
166             ClusterSupport support, Modifier modifier) throws DatabaseException {
167         final int tsize = getTableSize();
168 //        final int rsize = getResourceCount();
169         final int esize = ResourceElementSmall.getSizeOf();
170         //int count = 0;
171         int key = ZERO_SHIFT;
172         for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {
173             if (ResourceElementSmall.isUsed(getTable(), i)) {
174                 int ref;
175                 if (null == modifier)
176                     ref = key;
177                 else
178                     ref = modifier.execute(key);
179                 if (procedure.execute(context, ref))
180                     return true; // loop was broken by procedure
181 //                if (rsize == ++count)
182 //                    return false; // loop finished
183             }
184         }
185         //assert(rsize == count);
186         return false; // loop finished
187     }
188
189     public <Context> boolean foreachPredicate(int resourceIndex
190             , ClusterI.PredicateProcedure<Context> procedure, Context context
191             , ClusterSupport support, Modifier modifier, CompleteTable ct)
192     throws DatabaseException {
193         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
194         return ResourceElementSmall.foreachPredicate(getTable(), realIndex
195                 , procedure, context, support, modifier, ct);
196     }
197
198     public int getSingleObject(int resourceIndex, ClusterSupport support, short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
199         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
200         return ResourceElementSmall.getSingleObject(table, realIndex, support, pRef, completeType, ct, modifier);
201     }
202
203     public void foreachObject(int resourceIndex, ReadGraphImpl graph,
204             AsyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
205         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
206         ResourceElementSmall.foreachObject(table, realIndex, graph, procedure, support,
207                 pRef, completeType, ct, modifier);
208     }
209
210     public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,
211             AsyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
212         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
213         ResourceElementSmall.foreachObject(table, realIndex, graph, context, procedure, support,
214                 pRef, completeType, ct, modifier);
215     }
216
217     public <Context> boolean foreachObject(int resourceIndex
218             , ClusterI.ObjectProcedure<Context> procedure, Context context
219             , ClusterSupport support, Modifier modifier,
220             short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
221     throws DatabaseException {
222         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
223         return ResourceElementSmall.foreachObject(table, realIndex
224                 , procedure, context, support, modifier
225                 , pRef, completeType, ct);
226     }
227     public int addStatement(int resourceIndex, short pRef, short oRef, PredicateTable pt, ObjectTable ot
228             , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
229             throws DatabaseException {
230         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
231         return ResourceElementSmall.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, completeType, ct);
232     }
233
234     public boolean removeStatementFromCache(int resourceIndex, short pRef, short oRef,
235             ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
236     throws DatabaseException {
237         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
238         boolean ret = ResourceElementSmall.removeStatement(getTable(), realIndex, pRef, oRef, completeType, ct);
239 //        if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
240 //            decResourceCount();
241         return ret;
242     }
243     
244     public void removeStatement(int resourceIndex, short pRef, short oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,
245             PredicateTable pt, ObjectTable ot, ClusterSupport support)
246             throws DatabaseException {
247         int realIndex = checkIndexAndGetRealIndex(resourceIndex);
248         boolean removed = ResourceElementSmall.removeStatement(getTable(), realIndex,
249                 pRef, oRef, pCompleteType, ct);
250         if (!removed)
251             return;
252         int predicateIndex = ResourceElementSmall.getPredicateIndex(getTable(), realIndex);
253         if (0 == predicateIndex) {
254 //            if (!ResourceElementSmall.isUsed(getTable(), realIndex))
255 //                decResourceCount();
256             return;
257         } else if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
258             return; // Complete type statements are not kept in statement cache.
259         // We have one more statements in predicate table.
260         // Here we check if statement cache needs fixing.
261         GetStatementsSmall gs = new GetStatementsSmall(ot);
262         pt.foreachPredicate(predicateIndex, gs, null, null, null);
263         ArrayList<Statement> stms = gs.getStatements();
264
265         final int SIZE = stms.size();
266         if (SIZE < 3) {
267             for (int i = 0; i < SIZE; ++i) {
268                 Statement stm = stms.get(i);
269                 PredicateTable.Status ret = pt.removePredicate(predicateIndex,
270                         stm.pRef, stm.oIndex, ot);
271                 if (ret == Status.NothingRemoved)
272                     throw new DatabaseException("Internal error during statement cache fix (2).");
273                 assert(stm.pRef < (1<<16));
274                 assert(stm.oIndex < 1<<16);
275                 int pi = ResourceElementSmall.addStatement(getTable(), realIndex, (short)stm.pRef, (short)stm.oIndex,
276                         pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
277                 assert(0 >= pi);
278             }
279             assert(0 == pt.getPredicateSetSize(predicateIndex));
280             ResourceElementSmall.setPredicateIndex(getTable(), realIndex, 0);
281         } else {
282             for (int i = 0; i < SIZE; ++i) {
283                 Statement stm = stms.get(i);
284                 assert(stm.pRef < (1<<16));
285                 assert(stm.oIndex < 1<<16);
286                 int pIndex = ResourceElementSmall.addStatement(getTable(), realIndex,
287                         (short)stm.pRef, (short)stm.oIndex, pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
288                 if (pIndex > 0)
289                     return; // cache fixed and full, p and o sets in use
290             }
291             throw new DatabaseException("Internal error during statement cache fix (3).");
292         }
293 //        if (!ResourceElementSmall.isUsed(getTable(), realIndex))
294 //            decResourceCount();
295     }
296
297     private int checkIndexAndGetRealIndex(final int resourceIndex) {
298         if (ClusterTraitsBase.isIllegalResourceIndex(resourceIndex))
299             throw new RuntimeException("Illegal resource index. index=" + resourceIndex + ".");
300         if(resourceIndex > getTableCount())
301             throw new RuntimeException("Illegal resource index. index=" + resourceIndex + " table count=" + getTableCount());
302         final int SIZE = ResourceElementSmall.getSizeOf();
303         final int REAL_INDEX = resourceIndex * SIZE - (SIZE - ZERO_SHIFT) + offset;
304         return REAL_INDEX;
305     }
306     void check(ClusterImpl cluster)
307     throws DatabaseException {
308 //        throw new Error("Not implemented.//KRAA:");
309     }
310
311     public void toBig(ClusterBase big, final ClusterSupport support, final ClusterBase small)
312     throws DatabaseException {
313         int resourceIndex = 1;
314         long[] table = getTable();
315         int ps = getHeader().getOffset() + ZERO_SHIFT;
316         final int TABLE_SIZE = getTableSize();
317         int pe = ps + TABLE_SIZE;
318         for (int p=ps; p<pe; p+=ResourceElementSmall.getSizeOf(), ++resourceIndex) {
319             big.createResource(support);
320             int subjectKey = ClusterTraits.createResourceKey(small.clusterKey, resourceIndex);  
321             if (!ResourceElementSmall.isUsed(table, p))
322                 continue;
323             int cr = ResourceElementSmall.getCompleteObjectRef(table, p);
324             if (0 != cr) {
325                 ClusterI.CompleteTypeEnum ct = ResourceElementSmall.getCompleteType(table, p);
326                 if (ClusterI.CompleteTypeEnum.NotComplete != ct) {
327                     int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
328                     int oKey = small.getCompleteObjectKey(subjectKey, support);
329                     big.addRelation(subjectKey, pKey, oKey, support);
330                 } else {
331                     final class ForeachObject<Context>
332                     implements ClusterI.ObjectProcedure<Context> {
333                         int sKey;
334                         ClusterBase big;
335                         public ForeachObject(int sKey, ClusterBase big) {
336                             this.sKey = sKey;
337                             this.big = big;
338                         }
339                         @Override
340                         public boolean execute(Context context, int completeRef)
341                         throws DatabaseException {
342                             ClusterI.CompleteTypeEnum ct = ClusterTraitsSmall.completeRefAndTypeGetType(completeRef);
343                             int p = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
344                             int o = small.execute(completeRef & 0xFFFF);
345                             big.addRelation(sKey, p, o, support);
346                             return false; // Continue looping.
347                         }
348                     }
349                     ForeachObject<Object> op = new ForeachObject<Object>(subjectKey, big);
350                     small.getCompleteTable().foreach(cr & 0xFFFF, op, null, support, null);
351                 }
352             }
353             int pi = ResourceElementSmall.getPredicateIndex(table, p);
354             if (0 != pi) {
355                 ToBigStatements tbs = new ToBigStatements(small, big, support, subjectKey);
356                 small.getPredicateTable().foreach(pi, tbs, null, null, null);
357             } else {
358                 int p1 = ResourceElementSmall.getStm1Predicate(table, p);
359                 int o1 = ResourceElementSmall.getStm1Object(table, p);
360                 if (p1 != 0) {
361                     int pk1 = small.execute(p1);
362                     int ok1 = small.execute(o1);
363                     big.addRelation(subjectKey, pk1, ok1, support);
364                     int p2 = ResourceElementSmall.getStm2Predicate(table, p);
365                     int o2 = ResourceElementSmall.getStm2Object(table, p);
366                     if (p2 != 0) {
367                         int pk2 = small.execute(p2);
368                         int ok2 = small.execute(o2);
369                         big.addRelation(subjectKey, pk2, ok2, support);
370                     }
371                 }
372             }
373             int valueIndex = ResourceElementSmall.getValueIndex(table, p);
374             if (ClusterTraitsSmall.VALUE_INDEX_EX == valueIndex)
375               big.setValueEx(subjectKey);
376             else {
377                 byte[] value = ResourceElementSmall.getValue((ValueTableSmall)small.getValueTable(), table, p);
378                 if (null != value)
379                     big.setValue(subjectKey, value, value.length, support);
380             }
381         }
382     }
383
384     @Override
385     public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
386             ClusterSupport support, Modifier modifier) throws DatabaseException {
387         throw new UnsupportedOperationException();
388     }
389 }
390
391 class CalculateStatementsSmall
392 implements ClusterI.PredicateProcedure<CalculateStatements> {
393     private ObjectTable         ot;
394     private final int           sRef;
395
396     CalculateStatementsSmall(int sRef, ObjectTable ot) {
397         this.sRef = sRef;
398         this.ot = ot;
399     }
400
401     @Override
402     public boolean execute(CalculateStatements context
403             , final int pKey, int oIndex) {
404         if (ClusterTraits.statementIndexIsDirect(oIndex))
405             return false; // osize = 1
406         try {
407             oIndex = ClusterTraits.statementIndexGet(oIndex);
408         } catch (DatabaseException e) {
409             Logger.getDefault().logError("Missing object set for s="
410                     + sRef + " p=" + pKey, null);
411             return false; // continue looping
412         }
413         int osize = ot.getObjectSetSize(oIndex);
414         if (osize == 3 || osize > 9)
415             System.out.println("Resource " + sRef + " predicate " + pKey + " has "
416                     + osize + " objects.");
417         return true; // break loop
418     }
419 }
420
421 class GetStatementsSmall implements ClusterI.PredicateProcedure<Object>, ClusterI.ObjectProcedure<Integer> {
422     private ObjectTable         ot;
423     private final ArrayList<Statement> stms = new ArrayList<Statement>(); 
424     GetStatementsSmall(ObjectTable ot) {
425         this.ot = ot;
426     }
427     ArrayList<Statement> getStatements() {
428         return stms;
429     }
430     @Override
431     public boolean execute(Object context, int pRef, int oIndex) {
432         try {
433             ot.foreachObject(oIndex, this, pRef, null, null);
434         } catch (DatabaseException e) {
435             e.printStackTrace();
436             return false; // continue looping
437         }
438         if (stms.size() > 2)
439             return true; // break loop
440         return false; // continue looping
441     }
442     
443     @Override
444     public boolean execute(Integer pRef, int oRef) {
445         stms.add(new Statement(pRef, oRef));
446         if (stms.size() > 2)
447             return true; // break loop
448         return false; // continue looping
449     }
450 }
451
452 class ToBigStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {
453     private ClusterBase small;
454     private ClusterBase big;
455     private ClusterSupport support;
456     private int subjectKey;
457     ToBigStatements(ClusterBase small, ClusterBase big, ClusterSupport support, int subjectKey) {
458         this.small = small;
459         this.big = big;
460         this.support = support;
461         this.subjectKey = subjectKey;
462     }
463     @Override
464     public boolean execute(Object context, int pRef, int oIndex) {
465         try {
466             small.getObjectTable().foreach(oIndex, this, pRef, null, null);
467         } catch (DatabaseException e) {
468             e.printStackTrace();
469             return false; // continue looping
470         }
471         return false; // continue looping
472     }
473
474     @Override
475     public boolean execute(Integer pRef, int oRef)
476     throws DatabaseException {
477         int pKey = small.execute(pRef);
478         int oKey = small.execute(oRef);
479         big.addRelation(subjectKey, pKey, oKey, support);
480         return false; // continue looping
481     }
482     
483 }