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