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