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