]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/ClusterBig.java
Multiple reader thread support for db client
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / ClusterBig.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.io.ByteArrayInputStream;
15 import java.io.InputStream;
16 import java.util.function.Consumer;
17
18 import org.simantics.db.Resource;
19 import org.simantics.db.exception.DatabaseException;
20 import org.simantics.db.exception.ExternalValueException;
21 import org.simantics.db.exception.ValidationException;
22 import org.simantics.db.impl.ClusterI;
23 import org.simantics.db.impl.ClusterI.PredicateProcedure;
24 import org.simantics.db.impl.ClusterSupport;
25 import org.simantics.db.impl.ClusterTraitsBase;
26 import org.simantics.db.impl.ForEachObjectContextProcedure;
27 import org.simantics.db.impl.ForEachObjectProcedure;
28 import org.simantics.db.impl.ForPossibleRelatedValueContextProcedure;
29 import org.simantics.db.impl.ForPossibleRelatedValueProcedure;
30 import org.simantics.db.impl.Table;
31 import org.simantics.db.impl.TableHeader;
32 import org.simantics.db.impl.graph.ReadGraphImpl;
33 import org.simantics.db.impl.query.QueryProcessor;
34 import org.simantics.db.procedure.SyncContextMultiProcedure;
35 import org.simantics.db.procedure.SyncMultiProcedure;
36 import org.simantics.db.service.ClusterUID;
37
38 import fi.vtt.simantics.procore.DebugPolicy;
39 import fi.vtt.simantics.procore.internal.ClusterChange;
40 import fi.vtt.simantics.procore.internal.ClusterStream;
41 import fi.vtt.simantics.procore.internal.SessionImplSocket;
42
43 final public class ClusterBig extends ClusterImpl {
44     private static final int TABLE_HEADER_SIZE = TableHeader.HEADER_SIZE + TableHeader.EXTRA_SIZE;
45     private static final int RESOURCE_TABLE_OFFSET = 0;
46     private static final int PREDICATE_TABLE_OFFSET = RESOURCE_TABLE_OFFSET + TABLE_HEADER_SIZE;
47     private static final int OBJECT_TABLE_OFFSET = PREDICATE_TABLE_OFFSET + TABLE_HEADER_SIZE;
48     private static final int VALUE_TABLE_OFFSET = OBJECT_TABLE_OFFSET + TABLE_HEADER_SIZE;
49     private static final int FLAT_TABLE_OFFSET = VALUE_TABLE_OFFSET + TABLE_HEADER_SIZE;
50     private static final int COMPLETE_TABLE_OFFSET = FLAT_TABLE_OFFSET + TABLE_HEADER_SIZE;
51     private static final int FOREIGN_TABLE_OFFSET = COMPLETE_TABLE_OFFSET + TABLE_HEADER_SIZE;
52     private static final int INT_HEADER_SIZE = FOREIGN_TABLE_OFFSET + TABLE_HEADER_SIZE;
53     private final int clusterBits;
54     final private ResourceTable resourceTable;
55     //final private ResourceTable movedResourceTable;
56     final private PredicateTable predicateTable;
57     final private ObjectTable objectTable;
58     final private ValueTable valueTable;
59     final private FlatTable flatTable;
60     final private ForeignTable foreignTable;
61     final private CompleteTable completeTable;
62     final private ClusterMap clusterMap;
63     final private int[] headerTable;
64     final private ClusterSupport clusterSupport;
65     public ClusterBig(ClusterUID clusterUID, int clusterKey, ClusterSupport support) {
66         super(clusterUID, clusterKey, support);
67         if(DebugPolicy.REPORT_CLUSTER_EVENTS)
68             new Exception(getClusterUID().toString()).printStackTrace();
69         this.headerTable = new int[INT_HEADER_SIZE];
70         this.resourceTable = new ResourceTable(this, headerTable, RESOURCE_TABLE_OFFSET);
71         this.foreignTable = new ForeignTable(this, headerTable, FOREIGN_TABLE_OFFSET);
72         this.predicateTable = new PredicateTable(this, headerTable, PREDICATE_TABLE_OFFSET);
73         this.objectTable = new ObjectTable(this, headerTable, OBJECT_TABLE_OFFSET);
74         this.valueTable = new ValueTable(this, headerTable, VALUE_TABLE_OFFSET);
75         this.completeTable = new CompleteTable(this, headerTable, COMPLETE_TABLE_OFFSET);
76         this.flatTable = null;
77         this.clusterMap = new ClusterMap(foreignTable, flatTable);
78         this.clusterSupport = support;
79         this.clusterBits = ClusterTraitsBase.getClusterBits(clusterKey);
80         this.importance = 0;
81 //        clusterTable.setDirtySizeInBytes(true);
82     }
83     protected ClusterBig(long[] longs, int[] ints, byte[] bytes, ClusterSupport support, int clusterKey)
84     throws DatabaseException {
85         super(checkValidity(0, longs, ints, bytes), clusterKey, support);
86         if(DebugPolicy.REPORT_CLUSTER_EVENTS)
87             new Exception(getClusterUID().toString()).printStackTrace();
88         if (ints.length < INT_HEADER_SIZE)
89             throw new IllegalArgumentException("Too small integer table for cluster.");
90         this.headerTable = ints;
91         this.resourceTable = new ResourceTable(this, ints, RESOURCE_TABLE_OFFSET, longs);
92         this.foreignTable = new ForeignTable(this, headerTable, FOREIGN_TABLE_OFFSET, longs);
93         this.predicateTable = new PredicateTable(this, ints, PREDICATE_TABLE_OFFSET, ints);
94         this.objectTable = new ObjectTable(this, ints, OBJECT_TABLE_OFFSET, ints);
95         this.valueTable = new ValueTable(this, ints, VALUE_TABLE_OFFSET, bytes);
96         this.flatTable = null;
97         this.completeTable = new CompleteTable(this, headerTable, COMPLETE_TABLE_OFFSET, ints);
98         this.clusterMap = new ClusterMap(foreignTable, flatTable);
99         this.clusterSupport = support;
100         this.clusterBits = ClusterTraitsBase.getClusterBits(clusterKey);
101         this.importance = -clusterTable.timeCounter();
102         clusterTable.markImmutable(this, getImmutable());
103     }
104     void analyse() {
105         System.out.println("Cluster " + clusterId);
106         System.out.println("-size:" + getUsedSpace());
107         System.out.println(" -rt:" + (resourceTable.getTableCapacity() * 8 + 8));
108         System.out.println(" -ft:" + foreignTable.getTableCapacity() * 8);
109         System.out.println(" -pt:" + predicateTable.getTableCapacity() * 4);
110         System.out.println(" -ot:" + objectTable.getTableCapacity() * 4);
111         System.out.println(" -ct:" + completeTable.getTableCapacity() * 4);
112         System.out.println(" -vt:" + valueTable.getTableCapacity());
113
114         System.out.println("-resourceTable:");
115         System.out.println(" -resourceCount=" + resourceTable.getResourceCount());
116         System.out.println(" -size=" + resourceTable.getTableSize());
117         System.out.println(" -capacity=" + resourceTable.getTableCapacity());
118         System.out.println(" -count=" + resourceTable.getTableCount());
119         System.out.println(" -size=" + resourceTable.getTableSize());
120         //resourceTable.analyse();
121     }
122     public void checkDirectReference(int dr)
123     throws DatabaseException {
124         if (!ClusterTraits.statementIndexIsDirect(dr))
125             throw new ValidationException("Reference is not direct. Reference=" + dr);
126         if (ClusterTraits.isFlat(dr))
127             throw new ValidationException("Reference is flat. Reference=" + dr);
128         if (ClusterTraits.isLocal(dr)) {
129             if (dr < 1 || dr > resourceTable.getUsedSize())
130                 throw new ValidationException("Illegal local reference. Reference=" + dr);
131         } else {
132             int fi = ClusterTraits.getForeignIndexFromReference(dr);
133             int ri = ClusterTraits.getResourceIndexFromForeignReference(dr);
134             if (fi < 1 || fi > foreignTable.getUsedSize())
135                 throw new ValidationException("Illegal foreign reference. Reference=" + dr + " foreign index=" + fi);
136             if (ri < 1 || ri > ClusterTraits.getMaxNumberOfResources())
137                 throw new ValidationException("Illegal foreign reference. Reference=" + dr + " resource index=" + ri);
138         }
139     }
140     public void checkPredicateIndex(int pi)
141     throws DatabaseException {
142         predicateTable.checkPredicateSetIndex(this, pi);
143     }
144     public void checkObjectSetReference(int or)
145     throws DatabaseException {
146         if (ClusterTraits.statementIndexIsDirect(or))
147             throw new ValidationException("Illegal object set reference. Reference=" + or);
148         int oi = ClusterTraits.statementIndexGet(or);
149         this.objectTable.checkObjectSetIndex(this, oi);
150     }
151
152     public void checkValueInit()
153     throws DatabaseException {
154         valueTable.checkValueInit();
155     }
156     public void checkValue(int capacity, int index)
157     throws DatabaseException {
158         valueTable.checkValue(capacity, index);
159     }
160     public void checkValueFini()
161     throws DatabaseException {
162         valueTable.checkValueFini();
163     }
164     public void checkForeingIndex(int fi)
165     throws DatabaseException {
166         if (fi<1 || fi > foreignTable.getUsedSize())
167             throw new ValidationException("Illegal foreign index=" + fi);
168     }
169     public void checkCompleteSetReference(int cr)
170     throws DatabaseException {
171         if (!ClusterTraits.completeReferenceIsMultiple(cr))
172             throw new ValidationException("Illegal complete set reference. Reference=" + cr);
173         int ci = cr;
174         this.completeTable.checkCompleteSetIndex(this, ci);
175     }
176     public void check()
177     throws DatabaseException {
178         this.completeTable.check(this);
179         this.objectTable.check(this);
180         // Must be after object table check.
181         this.predicateTable.check(this);
182         this.resourceTable.check(this);
183     }
184     @Override
185     public CompleteTypeEnum getCompleteType(int resourceKey, ClusterSupport support)
186     throws DatabaseException {
187         final int resourceRef = getLocalReference(resourceKey);
188         int completeRef = resourceTable.getCompleteObjectRef(resourceRef);
189         CompleteTypeEnum ct = ClusterTraits.completeReferenceGetType(completeRef);
190         if (DEBUG)
191             System.out.println("Cluster.getCompleteType rk=" + resourceKey + " ct=" + ct);
192         int i = ct.getValue();
193         switch (i) {
194             case 0: return CompleteTypeEnum.NotComplete;
195             case 1: return CompleteTypeEnum.InstanceOf;
196             case 2: return CompleteTypeEnum.Inherits;
197             case 3: return CompleteTypeEnum.SubrelationOf;
198             default: throw new DatabaseException("Illegal complete type enumeration.");
199         }
200     }
201
202     @Override
203     public int getCompleteObjectKey(int resourceKey, ClusterSupport support)
204     throws DatabaseException {
205         final int resourceRef = getLocalReference(resourceKey);
206         int completeRef = resourceTable.getCompleteObjectRef(resourceRef);
207         int clusterIndex;
208         int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
209
210         ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
211         if (completeType == ClusterI.CompleteTypeEnum.NotComplete)
212             throw new DatabaseException("Resource has multiple complete objects. Resource key=" + resourceKey + ".");
213
214         if (ClusterTraits.completeReferenceIsLocal(completeRef)) {
215             clusterIndex = clusterKey;
216         } else {
217             int foreignIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
218 //            System.err.println("completeRef=" + completeRef + " foreignIndex=" + foreignIndex );
219             ClusterUID clusterUID = foreignTable.getResourceUID(foreignIndex).asCID();
220             ClusterI c = support.getClusterByClusterUIDOrMake(clusterUID);
221             clusterIndex = c.getClusterKey();
222         }
223         int key = ClusterTraits.createResourceKey(clusterIndex, resourceIndex);
224         if (DEBUG)
225             System.out.println("Cluster.complete object rk=" + resourceKey + " ck=" + key);
226         return key;
227     }
228
229     @Override
230     public boolean isComplete(int resourceKey, ClusterSupport support)
231     throws DatabaseException {
232         final int resourceRef = getLocalReference(resourceKey);
233         int completeRef = resourceTable.getCompleteObjectRef(resourceRef);
234         ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
235         boolean complete = completeType != ClusterI.CompleteTypeEnum.NotComplete;
236         if (DEBUG)
237             System.out.println("Cluster.key=" + resourceKey + " isComplete=" + complete);
238         return complete;
239     }
240
241     public int getSingleObject(int resourceKey, int predicateKey, int objectIndex, ClusterSupport support) throws DatabaseException {
242         if (DEBUG)
243             System.out.println("Cluster.getSingleObject: rk=" + resourceKey + " pk=" + predicateKey);
244         if (0 == objectIndex) {
245             final int resourceIndex = getLocalReference(resourceKey);
246             final int pRef = getInternalReferenceOrZero(predicateKey, support);
247             final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
248             return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
249         }
250         return objectTable.getSingleObject(objectIndex, support, this);
251     }
252
253     public void forObjects(int resourceKey, int predicateKey, int objectIndex, QueryProcessor processor, ReadGraphImpl graph, SyncMultiProcedure<Resource> procedure,
254             ClusterSupport support) throws DatabaseException {
255         if (DEBUG)
256             System.out.println("Cluster.forObjects1: rk=" + resourceKey + " pk=" + predicateKey);
257         if (0 == objectIndex) {
258             final int resourceIndex = getLocalReference(resourceKey);
259             final int pRef = getInternalReferenceOrZero(predicateKey, support);
260             final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
261             resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
262             return;
263         }
264         objectTable.foreachObject(graph, objectIndex, procedure, this);
265     }
266     public <C> void forObjects(int resourceKey, int predicateKey, int objectIndex, QueryProcessor processor, ReadGraphImpl graph, C context, SyncContextMultiProcedure<C, Resource> procedure,
267             ClusterSupport support) throws DatabaseException {
268         if (DEBUG)
269             System.out.println("Cluster.forObjects1: rk=" + resourceKey + " pk=" + predicateKey);
270         if (0 == objectIndex) {
271             final int resourceIndex = getLocalReference(resourceKey);
272             final int pRef = getInternalReferenceOrZero(predicateKey, support);
273             final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
274             resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);
275             return;
276         }
277         objectTable.foreachObject(graph, objectIndex, context, procedure, this);
278     }
279     @Override
280     public <Context> boolean forObjects(int resourceKey, int predicateKey, int objectIndex, ObjectProcedure<Context> procedure,
281             Context context, ClusterSupport support) throws DatabaseException {
282         if (DEBUG)
283             System.out.println("Cluster.forObjects2: rk=" + resourceKey + " pk=" + predicateKey);
284         if (0 == objectIndex) {
285             final int resourceIndex = getLocalReference(resourceKey);
286             final int pRef = getInternalReferenceOrZero(predicateKey, support);
287             final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
288             return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);
289         }
290         return objectTable.foreachObject(objectIndex, procedure, context, support, this);
291     }
292
293     @Override
294     public int getSingleObject(int resourceKey, int predicateKey, ClusterSupport support) throws DatabaseException {
295         if (DEBUG)
296             System.out.println("Cluster.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey);
297         final int resourceIndex = getLocalReference(resourceKey);
298         final int pRef = getInternalReferenceOrZero(predicateKey, support);
299         final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
300         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
301             return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
302         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
303         if (0 == predicateIndex)
304             return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
305         int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef);
306         return getSingleObject(resourceKey, predicateKey, objectIndex, support);
307     }
308
309     @Override
310     public <T> int getSingleObject(int resourceKey, ForPossibleRelatedValueProcedure<T> procedure, ClusterSupport support) throws DatabaseException {
311         final int predicateKey = procedure.predicateKey;
312         if (DEBUG)
313             System.out.println("Cluster.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey);
314         final int resourceIndex = getLocalReference(resourceKey);
315         final int pRef = getInternalReferenceOrZero(predicateKey, support);
316         final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
317         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
318             return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
319         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
320         if (0 == predicateIndex)
321             return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
322         int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef);
323         return getSingleObject(resourceKey, predicateKey, objectIndex, support);
324     }
325
326     @Override
327     public <C, T> int getSingleObject(int resourceKey, ForPossibleRelatedValueContextProcedure<C, T> procedure, ClusterSupport support) throws DatabaseException {
328         final int predicateKey = procedure.predicateKey;
329         if (DEBUG)
330             System.out.println("Cluster.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey);
331         final int resourceIndex = getLocalReference(resourceKey);
332         final int pRef = getInternalReferenceOrZero(predicateKey, support);
333         final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
334         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
335             return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
336         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
337         if (0 == predicateIndex)
338             return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
339         int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef);
340         return getSingleObject(resourceKey, predicateKey, objectIndex, support);
341     }
342
343     @Override
344     public void forObjects(ReadGraphImpl graph, int resourceKey,
345             int predicateKey, SyncMultiProcedure<Resource> procedure)
346             throws DatabaseException {
347
348         SessionImplSocket session = (SessionImplSocket)graph.getSession();
349         ClusterSupport support = session.clusterTranslator;
350
351         if (DEBUG)
352             System.out.println("Cluster.forObjects3: rk=" + resourceKey + " pk=" + predicateKey);
353         final int resourceIndex = getLocalReference(resourceKey);
354         final int pRef = getInternalReferenceOrZero(predicateKey, support);
355         final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
356         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
357             resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
358             return;
359         }
360         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
361         if (0 == predicateIndex) {
362             resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
363             return;
364         }
365         int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef);
366         forObjects(resourceKey, predicateKey, objectIndex, graph.processor, graph, procedure, support);
367
368     }
369
370     @Override
371     public void forObjects(ReadGraphImpl graph, int resourceKey, ForEachObjectProcedure procedure) throws DatabaseException {
372         SessionImplSocket session = (SessionImplSocket)graph.getSession();
373         ClusterSupport support = session.clusterTranslator;
374         final int predicateKey = procedure.predicateKey;
375         if (DEBUG)
376             System.out.println("Cluster.forObjects3: rk=" + resourceKey + " pk=" + predicateKey);
377         final int resourceIndex = getLocalReference(resourceKey);
378         final int pRef = getInternalReferenceOrZero(predicateKey, support);
379         final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
380         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
381             resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
382             return;
383         }
384         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
385         if (0 == predicateIndex) {
386             resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
387             return;
388         }
389         int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef);
390         forObjects(resourceKey, predicateKey, objectIndex, graph.processor, graph, procedure, support);
391
392     }
393     @Override
394     public <C> void forObjects(ReadGraphImpl graph, int resourceKey, C context,
395             ForEachObjectContextProcedure<C> procedure) throws DatabaseException {
396
397         SessionImplSocket session = (SessionImplSocket)graph.getSession();
398         ClusterSupport support = session.clusterTranslator;
399
400         final int predicateKey = procedure.predicateKey;
401
402         if (DEBUG)
403             System.out.println("Cluster.forObjects3: rk=" + resourceKey + " pk=" + predicateKey);
404         final int resourceIndex = getLocalReference(resourceKey);
405         final int pRef = getInternalReferenceOrZero(predicateKey, support);
406         final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
407         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
408             resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);
409             return;
410         }
411         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
412         if (0 == predicateIndex) {
413             resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);
414             return;
415         }
416         int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef);
417         forObjects(resourceKey, predicateKey, objectIndex, graph.processor, graph, context, procedure, support);
418
419     }
420
421     @Override
422     public <Context> boolean forObjects(int resourceKey, int predicateKey,
423             ObjectProcedure<Context> procedure, Context context, ClusterSupport support)
424     throws DatabaseException {
425         if (DEBUG)
426             System.out.println("Cluster.forObjects4: rk=" + resourceKey + " pk=" + predicateKey);
427         final int resourceIndex = getLocalReference(resourceKey);
428         final int pRef = getInternalReferenceOrZero(predicateKey, support);
429         final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
430         if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
431             return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);
432         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
433         if (0 == predicateIndex)
434             return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);
435         int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef);
436         return forObjects(resourceKey, predicateKey, objectIndex, procedure, context, support);
437     }
438     @Override
439     public <Context> boolean forPredicates(int resourceKey,
440             PredicateProcedure<Context> procedure, Context context, ClusterSupport support)
441     throws DatabaseException {
442         if (DEBUG)
443             System.out.println("Cluster.forPredicates: rk=" + resourceKey);
444         final int resourceIndex = getLocalReference(resourceKey);
445         final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
446         if (0 == predicateIndex)
447             return resourceTable.foreachPredicate(resourceIndex,
448                     procedure, context, support, this, completeTable);
449         else {
450             boolean broken = resourceTable.foreachPredicate(resourceIndex,
451                     procedure, context, support, this, completeTable);
452             if (broken)
453                 return true;
454         }
455         return predicateTable.foreachPredicate(predicateIndex, procedure, context, support, this);
456     }
457     @Override
458     public ClusterI addRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)
459     throws DatabaseException {
460         if (DEBUG)
461             System.out.println("add rk=" + sResourceKey + " pk=" + pResourceKey + " ok=" + oResourceKey);
462         int sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.ADD_OPERATION);
463         int pri = getReferenceOrCreateIfForeign(pResourceKey, support, ClusterStream.NULL_OPERATION);
464         int ori = getReferenceOrCreateIfForeign(oResourceKey, support, ClusterStream.NULL_OPERATION);
465         ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);
466         boolean ret = addRelationInternal(sri, pri, ori, completeType);
467 //      check();
468         if (ret) {
469             support.addStatement(this);
470             return this;
471         } else {
472             support.cancelStatement(this);
473             return null;
474         }
475     }
476     @Override
477     public boolean removeRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)
478     throws DatabaseException {
479 //        check();
480         int sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.REMOVE_OPERATION);
481         int pri = getInternalReferenceOrZeroAnd(pResourceKey, support, ClusterStream.NULL_OPERATION);
482         int ori = getInternalReferenceOrZeroAnd(oResourceKey, support, ClusterStream.NULL_OPERATION);
483         boolean ret = false;
484         if (0 != pri && 0 != ori) {
485             ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);
486             ret = removeRelationInternal(sri, pri, ori, completeType, support);
487         }
488         if (ret)
489             support.removeStatement(this);
490         else
491             support.cancelStatement(this);
492 //        check();
493         return ret;
494     }
495     @Override
496     public void denyRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)
497     throws DatabaseException {
498         int sri = checkResourceKeyIsOursAndGetResourceIndexIf(sResourceKey, support);
499         ResourceIndexAndId p = checkResourceKeyAndGetResourceIndexIf(pResourceKey, support);
500         ResourceIndexAndId o = checkResourceKeyAndGetResourceIndexIf(oResourceKey, support);
501         if (0 == sri || 0 == p.index || 0 == o.index)
502             return;
503 //        check();
504         ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);
505         boolean ret = removeRelationInternal(sri, p.reference, o.reference, completeType, support);
506         if (ret) {
507             support.addStatementIndex(this, sResourceKey, getClusterUID(), ClusterChange.REMOVE_OPERATION);
508             support.addStatementIndex(this, pResourceKey, p.clusterUID, ClusterStream.NULL_OPERATION);
509             support.addStatementIndex(this, oResourceKey, o.clusterUID, ClusterStream.NULL_OPERATION);
510             support.removeStatement(this);
511         }
512 //        check();
513         return;
514     }
515     @Override
516     public InputStream getValueStream(int rResourceId, ClusterSupport support) throws DatabaseException {
517         if (DEBUG)
518             System.out.println("ClusterBig.getValue " + rResourceId);
519         int resourceIndex = getLocalReference(rResourceId);
520         try {
521             byte[] buffer = resourceTable.getValue(valueTable, resourceIndex);
522             if(buffer == null) return null;
523             return new ByteArrayInputStream(buffer);
524         } catch (ExternalValueException e) {
525             return support.getValueStreamEx(resourceIndex, clusterId);
526         }
527     }
528     @Override
529     public byte[] getValue(int rResourceId, ClusterSupport support)
530     throws DatabaseException {
531         if (DEBUG)
532             System.out.println("ClusterBig.getValue " + rResourceId);
533         int resourceIndex = getLocalReference(rResourceId);
534         try {
535             return resourceTable.getValue(valueTable, resourceIndex);
536         } catch (ExternalValueException e) {
537             return support.getValueEx(resourceIndex, clusterId);
538         }
539     }
540     @Override
541     public boolean hasValue(int rResourceId, ClusterSupport support)
542     throws DatabaseException {
543         int resourceIndex = getLocalReference(rResourceId);
544         return resourceTable.hasValue(resourceIndex);
545     }
546     @Override
547     public boolean removeValue(int rResourceId, ClusterSupport support)
548     throws DatabaseException {
549         int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterChange.DELETE_OPERATION);
550         support.removeValue(this);
551         return resourceTable.removeValue(valueTable, resourceIndex);
552     }
553
554     @Override
555     public ClusterI setValue(int rResourceId, byte[] value, int length, ClusterSupport support)
556     throws DatabaseException {
557         int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.SET_OPERATION);
558         support.setValue(this, getClusterId(), value, length);
559         resourceTable.setValue(valueTable, resourceIndex, value, length);
560         return this;
561     }
562     @Override
563     public ClusterI modiValueEx(int rResourceId, long voffset, int length, byte[] value, int offset, ClusterSupport support)
564     throws DatabaseException {
565         int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.MODI_OPERATION);
566         support.modiValue(this, getClusterId(), voffset, length, value, offset);
567         resourceTable.setValueEx(valueTable, resourceIndex);
568         return this;
569     }
570     @Override
571     public byte[] readValueEx(int rResourceId, long voffset, int length, ClusterSupport support)
572     throws DatabaseException {
573         int resourceIndex = getLocalReference(rResourceId);
574         boolean isExternal = resourceTable.isValueEx(valueTable, resourceIndex);
575         if (!isExternal)
576             throw new DatabaseException("ClusterI.readValue supported only for external value. Resource key=" + rResourceId);
577         return support.getValueEx(resourceIndex, getClusterId(), voffset, length);
578     }
579     @Override
580     public long getValueSizeEx(int resourceKey, ClusterSupport support)
581     throws DatabaseException, ExternalValueException {
582         int resourceIndex = getLocalReference(resourceKey);
583         boolean isExternal = resourceTable.isValueEx(valueTable, resourceIndex);
584         if (!isExternal)
585             throw new ExternalValueException("ClusterI.getSize supported only for external value. Resource key=" + resourceKey);
586         return support.getValueSizeEx(resourceIndex, getClusterId());
587     }
588     public boolean isValueEx(int resourceKey)
589     throws DatabaseException {
590         int resourceIndex = getLocalReference(resourceKey);
591         return resourceTable.isValueEx(valueTable, resourceIndex);
592     }
593     @Override
594     public void setValueEx(int resourceKey)
595     throws DatabaseException {
596         int resourceIndex = getLocalReference(resourceKey);
597         resourceTable.setValueEx(valueTable, resourceIndex);
598     }
599     @Override
600     public int createResource(ClusterSupport support)
601     throws DatabaseException {
602         short resourceIndex = resourceTable.createResource();
603
604         if(DebugPolicy.REPORT_RESOURCE_ID_ALLOCATION)
605             System.out.println("[RID_ALLOCATION]: ClusterBig[" + clusterId + "] allocates " + resourceIndex);
606
607         support.createResource(this, resourceIndex, clusterId);
608         return ClusterTraits.createResourceKey(clusterKey, resourceIndex);
609     }
610     @Override
611     public boolean hasResource(int resourceKey, ClusterSupport support) {
612         int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(resourceKey);
613         if (this.clusterKey != clusterKey) // foreign resource
614             return false;
615         int resourceIndex;
616         try {
617             resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
618         } catch (DatabaseException e) {
619             return false;
620         }
621         if (resourceIndex > 0 & resourceIndex <= resourceTable.getTableCount())
622             return true;
623         else
624             return false;
625     }
626     @Override
627     public int getNumberOfResources(ClusterSupport support) {
628         return resourceTable.getUsedSize();
629     }
630     @Override
631     public long getUsedSpace() {
632         long rt = resourceTable.getTableCapacity() * 8 + 8; // (8 = cluster id)
633         long ft = foreignTable.getTableCapacity() * 8;
634         long pt = predicateTable.getTableCapacity() * 4;
635         long ot = objectTable.getTableCapacity() * 4;
636         long ct = completeTable.getTableCapacity() * 4;
637         long vt = valueTable.getTableCapacity() * 1;
638         long cm = clusterMap.getUsedSpace();
639
640         return rt + ft + pt + ot + ct + vt + cm;
641 //        System.out.println("resource table " + rt);
642 //        System.out.println("foreign table (non flat cluster table) " + ft);
643 //        System.out.println("predicate table " + pt);
644 //        long pt2 = getRealSizeOfPredicateTable() * 4;
645 //        System.out.println("predicate table real size " + pt2);
646 //        System.out.println("object table " + ot);
647 //        long ot2 = getRealSizeOfObjectTable() * 4;
648 //        System.out.println("object table real size " + ot2);
649 //        System.out.println("value table " + vt);
650     }
651     int getRealSizeOfPredicateTable() throws DatabaseException {
652         SizeOfPredicateTable proc = new SizeOfPredicateTable(resourceTable, predicateTable);
653         resourceTable.foreachResource(proc, 0, null, null);
654         return proc.getSize();
655     }
656     int getRealSizeOfObjectTable() throws DatabaseException {
657         SizeOfObjectTable proc = new SizeOfObjectTable(resourceTable, predicateTable, objectTable);
658         resourceTable.foreachResource(proc, 0, null, null);
659         return proc.getSize();
660     }
661     @Override
662     public boolean isEmpty() {
663         return resourceTable.getTableCount() == 0;
664     }
665     @Override
666     public void printDebugInfo(String message, ClusterSupport support)
667     throws DatabaseException {
668         predicateTable.printDebugInfo();
669         objectTable.printDebugInfo();
670         ClusterPrintDebugInfo proc = new ClusterPrintDebugInfo(this
671                 , resourceTable, predicateTable, support, objectTable);
672         resourceTable.foreachResource(proc, 0, null, null);
673     }
674     private int getInternalReferenceOrZero(int resourceKey, ClusterSupport support)
675     throws DatabaseException {
676         int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
677         int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
678         if (this.clusterKey != clusterKey) { // foreign resource
679             ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);
680             ClusterUID clusterUID = foreignCluster.getClusterUID();
681             int foreignResourceIndex = clusterMap.getForeignReferenceOrZero(resourceIndex, clusterUID);
682             return foreignResourceIndex;
683         }
684         return resourceIndex;
685     }
686     private int getInternalReferenceOrZeroAnd(int resourceKey, ClusterSupport support, byte op)
687     throws DatabaseException {
688         int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
689         int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
690         if (this.clusterKey != clusterKey) { // foreign resource
691             ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);
692             ClusterUID clusterUID = foreignCluster.getClusterUID();
693             int foreignResourceIndex = clusterMap.getForeignReferenceOrZero(resourceIndex, clusterUID);
694             support.addStatementIndex(this, resourceKey, clusterUID, op);
695             return foreignResourceIndex;
696         }
697         support.addStatementIndex(this, resourceKey, getClusterUID(), op);
698         return resourceIndex;
699     }
700     private short getLocalReference(int resourceKey) throws DatabaseException {
701         return ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);
702     }
703     private int getLocalReferenceAnd(int resourceKey, ClusterSupport support, byte op)
704     throws DatabaseException {
705         int resourceIndex = getLocalReference(resourceKey);
706         support.addStatementIndex(this, resourceKey, getClusterUID(), op);
707         return resourceIndex;
708     }
709     private int checkResourceKeyIsOursAndGetResourceIndexIf(int resourceKey, ClusterSupport support)
710     throws DatabaseException {
711         int clusterShortId = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
712         if (this.clusterKey != clusterShortId)
713             return 0;
714         int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
715         return resourceIndex;
716     }
717     private int getReferenceOrCreateIfForeign(int resourceKey, ClusterSupport support, byte op)
718     throws DatabaseException {
719         int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
720         int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
721         if (this.clusterKey != clusterKey) {
722             ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);
723             ClusterUID clusterUID = foreignCluster.getClusterUID();
724             support.addStatementIndex(this, resourceKey, clusterUID, op);
725             return clusterMap.getForeignReferenceOrCreateByResourceKey(resourceKey, clusterUID);
726         }
727         support.addStatementIndex(this, resourceKey, getClusterUID(), op);
728         return resourceIndex;
729     }
730     private class ResourceIndexAndId {
731         ResourceIndexAndId(int reference, int index, ClusterUID clusterUID) {
732             this.reference = reference;
733             this.index = index;
734             this.clusterUID = clusterUID;
735         }
736         public final int reference;
737         public final int index;
738         public final ClusterUID clusterUID;
739     }
740     private ResourceIndexAndId checkResourceKeyAndGetResourceIndexIf(int resourceKey, ClusterSupport support)
741     throws DatabaseException {
742         int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
743         int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
744         if (this.clusterKey != clusterKey) { // foreign resource
745             ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);
746             ClusterUID clusterUID = foreignCluster.getClusterUID();
747             int ref = clusterMap.getForeignReferenceOrCreateByResourceIndex(resourceIndex, clusterUID);
748             return new ResourceIndexAndId(ref, resourceIndex, clusterUID);
749         }
750         return new ResourceIndexAndId(resourceIndex, resourceIndex, getClusterUID());
751     }
752
753     @Override
754     final public int execute(int resourceIndex) throws DatabaseException {
755         int key;
756         if(resourceIndex > 0) {
757             key = clusterBits | resourceIndex;
758         } else {
759             ClusterUID clusterUID = clusterMap.getResourceUID(resourceIndex).asCID();
760             ClusterI cluster = clusterSupport.getClusterByClusterUIDOrMake(clusterUID);
761             int foreingResourceIndex =  clusterMap.getForeignResourceIndex(resourceIndex);
762             key = ClusterTraits.createResourceKey(cluster.getClusterKey(), foreingResourceIndex);
763         }
764         if (DEBUG)
765             System.out.println("Cluster.execute key=" + key);
766         return key;
767     }
768
769     private boolean addRelationInternal(int sReference, int pReference, int oReference, ClusterI.CompleteTypeEnum completeType)
770     throws DatabaseException {
771         int predicateIndex = resourceTable.addStatement(sReference, pReference,
772                 oReference, predicateTable, objectTable, completeType, completeTable);
773         if (0 == predicateIndex)
774             return true; // added to resourceTable
775         else if (0 > predicateIndex)
776             return false; // old complete statemenent
777         int newPredicateIndex = predicateTable.addPredicate(predicateIndex,
778                 pReference, oReference, objectTable);
779         if (0 == newPredicateIndex)
780             return false;
781         if (predicateIndex != newPredicateIndex)
782             resourceTable.setPredicateIndex(sReference, newPredicateIndex);
783         return true;
784     }
785     private boolean removeRelationInternal(int sResourceIndex, int pResourceIndex,
786             int oResourceIndex, ClusterI.CompleteTypeEnum completeType, ClusterSupport support)
787     throws DatabaseException {
788         int predicateIndex = resourceTable.getPredicateIndex(sResourceIndex);
789         if (0 == predicateIndex || ClusterI.CompleteTypeEnum.NotComplete != completeType)
790             return resourceTable.removeStatementFromCache(sResourceIndex,
791                     pResourceIndex, oResourceIndex, completeType, completeTable);
792         PredicateTable.Status ret = predicateTable.removePredicate(predicateIndex, pResourceIndex, oResourceIndex, objectTable);
793         switch (ret) {
794             case NothingRemoved:
795                 return false;
796             case PredicateRemoved: {
797                 if (0 == predicateTable.getPredicateSetSize(predicateIndex))
798                     resourceTable.setPredicateIndex(sResourceIndex, 0);
799                 // intentionally dropping to next case
800             } default:
801                 break;
802         }
803         resourceTable.removeStatement(sResourceIndex,
804                 pResourceIndex, oResourceIndex,
805                 completeType, completeTable,
806                 predicateTable, objectTable, this, support);
807         return true;
808     }
809     @Override
810     public void load() {
811         throw new Error("Not supported.");
812     }
813
814     @Override
815     public void load(Consumer<DatabaseException> r) {
816         throw new Error("Not supported.");
817     }
818
819     public int makeResourceKey(int resourceIndex) throws DatabaseException {
820         int key = 0;
821 //        if (ClusterTraitsBase.isIllegalResourceIndex(resourceIndex))
822 //            throw new DatabaseException("Illegal resource key " + resourceIndex);
823         if (resourceIndex > 0) // local resource
824             key = ClusterTraits.createResourceKey(clusterKey, resourceIndex);
825         else {
826             ClusterUID clusterUID = clusterMap.getResourceUID(resourceIndex).asCID();
827             ClusterI cluster = clusterSupport.getClusterByClusterUIDOrMake(clusterUID);
828             int foreingResourceIndex =  clusterMap.getForeignResourceIndex(resourceIndex);
829             key = ClusterTraits.createResourceKey(cluster.getClusterKey(), foreingResourceIndex);
830         }
831         if (0 == key)
832             throw new DatabaseException("Failed to make resource key from " + resourceIndex);
833         return key;
834     }
835     @Override
836     public ClusterBig toBig(ClusterSupport support) throws DatabaseException {
837         throw new Error("Not implemented");
838     }
839     @Override
840     public void load(ClusterSupport session, Runnable callback) {
841         throw new Error("Not implemented");
842     }
843     @Override
844     public ClusterI getClusterByResourceKey(int resourceKey,
845             ClusterSupport support) {
846         throw new Error("Not implemented");
847     }
848     @Override
849     public void increaseReferenceCount(int amount) {
850         throw new Error("Not implemented");
851     }
852     @Override
853
854     public void decreaseReferenceCount(int amount) {
855         throw new Error("Not implemented");
856     }
857     @Override
858     public int getReferenceCount() {
859         throw new Error("Not implemented");
860     }
861     @Override
862     public void releaseMemory() {
863     }
864     @Override
865     public void compact() {
866         clusterMap.compact();
867     }
868     public boolean contains(int resourceKey) {
869         return ClusterTraitsBase.isCluster(clusterBits, resourceKey);
870     }
871     @Override
872     public ClusterTypeEnum getType() {
873         return ClusterTypeEnum.BIG;
874     }
875     @Override
876     public boolean getImmutable() {
877         int status = resourceTable.getClusterStatus();
878         return (status & ClusterStatus.ImmutableMaskSet) == ClusterStatus.ImmutableMaskSet;
879     }
880     @Override
881     public void setImmutable(boolean immutable, ClusterSupport support) {
882         int status = resourceTable.getClusterStatus();
883         if (immutable)
884             status |= ClusterStatus.ImmutableMaskSet;
885         else
886             status &= ClusterStatus.ImmutableMaskClear;
887         resourceTable.setClusterStatus(status);
888         support.setImmutable(this, immutable);
889     }
890     @Override
891     public boolean getDeleted() {
892         int status = resourceTable.getClusterStatus();
893         return (status & ClusterStatus.DeletedMaskSet) == ClusterStatus.DeletedMaskSet;
894     }
895     @Override
896     public void setDeleted(boolean deleted, ClusterSupport support) {
897         int status = resourceTable.getClusterStatus();
898         if (deleted)
899             status |= ClusterStatus.DeletedMaskSet;
900         else
901             status &= ClusterStatus.DeletedMaskClear;
902         resourceTable.setClusterStatus(status);
903         support.setDeleted(this, deleted);
904     }
905     @Override
906     public Table<?> getPredicateTable() {
907         return predicateTable;
908     }
909     @Override
910     public Table<?> getForeignTable() {
911         return foreignTable;
912     }
913     @Override
914     public Table<?> getCompleteTable() {
915         return completeTable;
916     }
917     @Override
918     public Table<?> getValueTable() {
919         return valueTable;
920     }
921     @Override
922     public Table<?> getObjectTable() {
923         return objectTable;
924     }
925 }
926
927 class SizeOfPredicateTable implements ClusterI.ObjectProcedure<Integer> {
928     private final ResourceTable mrResourceTable;
929     private final PredicateTable mrPredicateTable;
930     private int size = 0;
931     SizeOfPredicateTable(ResourceTable resourceTable
932             , PredicateTable predicateTable) {
933         mrResourceTable = resourceTable;
934         mrPredicateTable = predicateTable;
935     }
936     @Override
937     public boolean execute(Integer i, int resourceRef) {
938         int predicateIndex = mrResourceTable.getPredicateIndex(resourceRef);
939         if (0 == predicateIndex)
940             return false; // continue loop
941         size += mrPredicateTable.getPredicateSetSize(predicateIndex);
942         return false; // continue loop
943     }
944
945     public int getSize() {
946         return size;
947     }
948 }
949
950 class SizeOfObjectTable implements ClusterI.ObjectProcedure<Integer> {
951     private final ResourceTable mrResourceTable;
952     private final PredicateTable mrPredicateTable;
953     private final ObjectTable mrObjectTable;
954     private int size = 0;
955     SizeOfObjectTable(ResourceTable resourceTable
956             , PredicateTable predicateTable, ObjectTable objectTable) {
957         mrResourceTable = resourceTable;
958         mrPredicateTable = predicateTable;
959         mrObjectTable = objectTable;
960     }
961
962     @Override
963     public boolean execute(Integer i, int resourceRef) {
964         int predicateIndex = mrResourceTable.getPredicateIndex(resourceRef);
965         if (0 == predicateIndex)
966             return false; // continue loop
967         ClusterI.PredicateProcedure<Object> procedure = new PredicateProcedure<Object>() {
968             @Override
969             public boolean execute(Object context, int pRef, int oIndex) {
970                 if (ClusterTraits.statementIndexIsDirect(oIndex))
971                     return false; // no table space reserved, continue looping
972                 int objectIndex;
973                 try {
974                     objectIndex = ClusterTraits.statementIndexGet(oIndex);
975                     size += mrObjectTable.getObjectSetSize(objectIndex);
976                 } catch (DatabaseException e) {
977                     e.printStackTrace();
978                 }
979                 return false; // continue looping
980             }
981         };
982         try {
983             mrPredicateTable.foreachPredicate(predicateIndex, procedure, null, null, null);
984         } catch (DatabaseException e) {
985             e.printStackTrace();
986         }
987         return false; // continue loop
988     }
989
990     public int getSize() {
991         return size;
992     }
993
994 }