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