1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.procore.cluster;
14 import java.io.ByteArrayInputStream;
15 import java.io.InputStream;
16 import java.util.function.Consumer;
18 import org.simantics.db.Resource;
19 import org.simantics.db.exception.DatabaseException;
20 import org.simantics.db.exception.ExternalValueException;
21 import org.simantics.db.exception.ValidationException;
22 import org.simantics.db.impl.ClusterI;
23 import org.simantics.db.impl.ClusterSupport;
24 import org.simantics.db.impl.ClusterTraitsBase;
25 import org.simantics.db.impl.ForEachObjectContextProcedure;
26 import org.simantics.db.impl.ForEachObjectProcedure;
27 import org.simantics.db.impl.ForPossibleRelatedValueContextProcedure;
28 import org.simantics.db.impl.ForPossibleRelatedValueProcedure;
29 import org.simantics.db.impl.Table;
30 import org.simantics.db.impl.TableHeader;
31 import org.simantics.db.impl.graph.ReadGraphImpl;
32 import org.simantics.db.procedure.AsyncContextMultiProcedure;
33 import org.simantics.db.procedure.AsyncMultiProcedure;
34 import org.simantics.db.service.ClusterUID;
35 import org.simantics.db.service.ResourceUID;
37 import fi.vtt.simantics.procore.DebugPolicy;
38 import fi.vtt.simantics.procore.internal.ClusterChange;
39 import fi.vtt.simantics.procore.internal.ClusterStream;
40 import fi.vtt.simantics.procore.internal.ClusterTable;
41 import fi.vtt.simantics.procore.internal.SessionImplSocket;
42 import gnu.trove.map.hash.TIntShortHashMap;
43 import gnu.trove.set.hash.TIntHashSet;
45 final public class ClusterSmall extends ClusterImpl {
47 private static final int TABLE_HEADER_SIZE = TableHeader.HEADER_SIZE + TableHeader.EXTRA_SIZE;
48 private static final int RESOURCE_TABLE_OFFSET = 0;
49 private static final int PREDICATE_TABLE_OFFSET = RESOURCE_TABLE_OFFSET + TABLE_HEADER_SIZE;
50 private static final int OBJECT_TABLE_OFFSET = PREDICATE_TABLE_OFFSET + TABLE_HEADER_SIZE;
51 private static final int VALUE_TABLE_OFFSET = OBJECT_TABLE_OFFSET + TABLE_HEADER_SIZE;
52 private static final int FLAT_TABLE_OFFSET = VALUE_TABLE_OFFSET + TABLE_HEADER_SIZE;
53 private static final int COMPLETE_TABLE_OFFSET = FLAT_TABLE_OFFSET + TABLE_HEADER_SIZE;
54 private static final int FOREIGN_TABLE_OFFSET = COMPLETE_TABLE_OFFSET + TABLE_HEADER_SIZE;
55 private static final int INT_HEADER_SIZE = FOREIGN_TABLE_OFFSET + TABLE_HEADER_SIZE;
56 private final int clusterBits;
57 public final ResourceTableSmall resourceTable;
58 private PredicateTable predicateTable;
59 final ObjectTable objectTable;
60 public final ValueTableSmall valueTable;
61 public final ForeignTableSmall foreignTable;
62 private final CompleteTableSmall completeTable;
63 private final ClusterMapSmall clusterMap;
64 private final int[] headerTable;
65 private final ClusterSupport clusterSupport;
66 private boolean proxy;
67 private boolean deleted = false;
69 public ClusterSmall(ClusterUID clusterUID, int clusterKey, ClusterTable clusterTable, ClusterSupport support) {
70 super(clusterUID, clusterKey, support);
71 if(DebugPolicy.REPORT_CLUSTER_EVENTS)
72 new Exception(clusterUID.toString()).printStackTrace();
74 this.headerTable = null;
75 this.resourceTable = null;
76 this.foreignTable = null;
77 this.predicateTable = null;
78 this.objectTable = null;
79 this.valueTable = null;
80 this.completeTable = null;
81 this.clusterMap = null;
82 this.clusterSupport = null;
86 public ClusterSmall(ClusterUID clusterUID, int clusterKey, ClusterSupport support) {
87 super(clusterUID, clusterKey, support);
88 if(DebugPolicy.REPORT_CLUSTER_EVENTS)
89 new Exception(clusterUID.toString()).printStackTrace();
91 this.headerTable = new int[INT_HEADER_SIZE];
92 this.resourceTable = new ResourceTableSmall(this, headerTable, RESOURCE_TABLE_OFFSET);
93 this.foreignTable = new ForeignTableSmall(this, headerTable, FOREIGN_TABLE_OFFSET);
94 this.predicateTable = new PredicateTable(this, headerTable, PREDICATE_TABLE_OFFSET);
95 this.objectTable = new ObjectTable(this, headerTable, OBJECT_TABLE_OFFSET);
96 this.valueTable = new ValueTableSmall(this, headerTable, VALUE_TABLE_OFFSET);
97 this.completeTable = new CompleteTableSmall(this, headerTable, COMPLETE_TABLE_OFFSET);
98 this.clusterMap = new ClusterMapSmall(this, foreignTable);
99 this.clusterSupport = support;
100 this.clusterBits = ClusterTraitsBase.getClusterBits(clusterKey);
101 this.importance = -clusterTable.timeCounter();
103 protected ClusterSmall(long[] longs, int[] ints, byte[] bytes, ClusterSupport support, int clusterKey)
104 throws DatabaseException {
105 super(checkValidity(-1, longs, ints, bytes), clusterKey, support);
107 if (ints.length < INT_HEADER_SIZE)
108 throw new IllegalArgumentException("Too small integer table for cluster.");
109 this.headerTable = ints;
110 if(DebugPolicy.REPORT_CLUSTER_EVENTS) new Exception(Long.toString(clusterId)).printStackTrace();
111 this.resourceTable = new ResourceTableSmall(this, ints, RESOURCE_TABLE_OFFSET, longs);
112 this.foreignTable = new ForeignTableSmall(this, headerTable, FOREIGN_TABLE_OFFSET, longs);
113 this.predicateTable = new PredicateTable(this, ints, PREDICATE_TABLE_OFFSET, ints);
114 this.objectTable = new ObjectTable(this, ints, OBJECT_TABLE_OFFSET, ints);
115 this.valueTable = new ValueTableSmall(this, ints, VALUE_TABLE_OFFSET, bytes);
116 this.completeTable = new CompleteTableSmall(this, headerTable, COMPLETE_TABLE_OFFSET, ints);
117 this.clusterMap = new ClusterMapSmall(this, foreignTable);
118 this.clusterSupport = support;
119 this.clusterBits = ClusterTraitsBase.getClusterBits(clusterKey);
120 this.importance = clusterTable.timeCounter();
121 clusterTable.markImmutable(this, getImmutable());
124 System.out.println("Cluster " + clusterId);
125 System.out.println("-size:" + getUsedSpace());
126 System.out.println(" -rt:" + (resourceTable.getTableCapacity() * 8 + 8));
127 System.out.println(" -ft:" + foreignTable.getTableCapacity() * 8);
128 System.out.println(" -pt:" + predicateTable.getTableCapacity() * 4);
129 System.out.println(" -ot:" + objectTable.getTableCapacity() * 4);
130 System.out.println(" -ct:" + completeTable.getTableCapacity() * 4);
131 System.out.println(" -vt:" + valueTable.getTableCapacity());
133 System.out.println("-resourceTable:");
134 System.out.println(" -resourceCount=" + resourceTable.getResourceCount());
135 System.out.println(" -size=" + resourceTable.getTableSize());
136 System.out.println(" -capacity=" + resourceTable.getTableCapacity());
137 System.out.println(" -count=" + resourceTable.getTableCount());
138 System.out.println(" -size=" + resourceTable.getTableSize());
139 //resourceTable.analyse();
141 public void checkDirectReference(int dr)
142 throws DatabaseException {
144 if (!ClusterTraits.statementIndexIsDirect(dr))
145 throw new ValidationException("Reference is not direct. Reference=" + dr);
146 if (ClusterTraits.isFlat(dr))
147 throw new ValidationException("Reference is flat. Reference=" + dr);
148 if (ClusterTraits.isLocal(dr)) {
149 if (dr < 1 || dr > resourceTable.getUsedSize())
150 throw new ValidationException("Illegal local reference. Reference=" + dr);
152 int fi = ClusterTraits.getForeignIndexFromReference(dr);
153 int ri = ClusterTraits.getResourceIndexFromForeignReference(dr);
154 if (fi < 1 || fi > foreignTable.getUsedSize())
155 throw new ValidationException("Illegal foreign reference. Reference=" + dr + " foreign index=" + fi);
156 if (ri < 1 || ri > ClusterTraits.getMaxNumberOfResources())
157 throw new ValidationException("Illegal foreign reference. Reference=" + dr + " resource index=" + ri);
160 public void checkPredicateIndex(int pi)
161 throws DatabaseException {
163 // predicateTable.checkPredicateSetIndex(this, pi);
165 public void checkObjectSetReference(int or)
166 throws DatabaseException {
168 if (ClusterTraits.statementIndexIsDirect(or))
169 throw new ValidationException("Illegal object set reference. Reference=" + or);
170 int oi = ClusterTraits.statementIndexGet(or);
171 this.objectTable.checkObjectSetIndex(this, oi);
174 public void checkValueInit()
175 throws DatabaseException {
176 valueTable.checkValueInit();
178 public void checkValue(int capacity, int index)
179 throws DatabaseException {
180 valueTable.checkValue(capacity, index);
182 public void checkValueFini()
183 throws DatabaseException {
184 valueTable.checkValueFini();
186 public void checkForeingIndex(int fi)
187 throws DatabaseException {
189 if (fi<1 || fi > foreignTable.getUsedSize())
190 throw new ValidationException("Illegal foreign index=" + fi);
192 public void checkCompleteSetReference(int cr)
193 throws DatabaseException {
194 if (!ClusterTraits.completeReferenceIsMultiple(cr))
195 throw new ValidationException("Illegal complete set reference. Reference=" + cr);
197 this.completeTable.checkCompleteSetIndex(this, ci);
200 throws DatabaseException {
202 // this.completeTable.check(this);
203 // this.objectTable.check(this);
204 // // Must be after object table check.
205 // this.predicateTable.check(this);
206 // this.resourceTable.check(this);
209 public CompleteTypeEnum getCompleteType(int resourceKey, ClusterSupport support)
210 throws DatabaseException {
211 if (deleted) return CompleteTypeEnum.NotComplete;
212 final int resourceRef = getLocalReference(resourceKey);
213 CompleteTypeEnum ct = resourceTable.getCompleteType(resourceRef);
215 System.out.println("ClusterSmall.getCompleteType rk=" + resourceKey + " ct=" + ct);
220 public int getCompleteObjectKey(int resourceKey, ClusterSupport support)
221 throws DatabaseException {
222 if (deleted) return 0;
223 final int resourceIndexOld = getLocalReference(resourceKey);
224 short completeRef = resourceTable.getCompleteObjectRef(resourceIndexOld);
227 if (0 == completeRef)
228 throw new DatabaseException("Resource's complete object refernce is null. Resource key=" + resourceKey + ".");
229 ClusterI.CompleteTypeEnum completeType = resourceTable.getCompleteType(resourceIndexOld);
230 if (completeType == ClusterI.CompleteTypeEnum.NotComplete)
231 throw new DatabaseException("Resource has multiple complete objects. Resource key=" + resourceKey + ".");
232 if (ClusterTraitsSmall.resourceRefIsLocal(completeRef)) {
233 clusterIndex = clusterKey;
234 resourceIndex = completeRef;
235 } else { // Resource has one complete statement.
236 ResourceUID resourceUID = clusterMap.getForeignResourceUID(completeRef);
237 ClusterI c = support.getClusterByClusterUIDOrMake(resourceUID.asCID());
238 clusterIndex = c.getClusterKey();
239 resourceIndex = resourceUID.getIndex();
241 int key = ClusterTraits.createResourceKey(clusterIndex, resourceIndex);
243 System.out.println("ClusterSmall.complete object rk=" + resourceKey + " ck=" + key);
248 public boolean isComplete(int resourceKey, ClusterSupport support)
249 throws DatabaseException {
250 if (deleted) return false;
251 final int resourceRef = getLocalReference(resourceKey);
252 final ClusterI.CompleteTypeEnum completeType = resourceTable.getCompleteType(resourceRef);
253 boolean complete = completeType != ClusterI.CompleteTypeEnum.NotComplete;
255 System.out.println("ClusterSmall.key=" + resourceKey + " isComplete=" + complete);
258 public int getSingleObject(int resourceKey, int predicateKey, int objectIndex, ClusterSupport support) throws DatabaseException {
260 System.out.println("ClusterSmall.getSingleObject: rk=" + resourceKey + " pk=" + predicateKey);
261 if (deleted) return 0;
262 if (0 == objectIndex) {
263 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);
264 final short pRef = getInternalReferenceOrZero2(predicateKey, support);
265 final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
266 return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
268 return objectTable.getSingleObject(objectIndex, support, this);
271 public void forObjects(ReadGraphImpl graph, int resourceKey, int predicateKey, int objectIndex, AsyncMultiProcedure<Resource> procedure,
272 ClusterSupport support) throws DatabaseException {
275 System.out.println("ClusterSmall.forObjects1: rk=" + resourceKey + " pk=" + predicateKey);
276 if (0 == objectIndex) {
277 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
278 final int pRef = getInternalReferenceOrZero2(predicateKey, support);
279 final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
280 resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
283 objectTable.foreachObject(graph, objectIndex, procedure, this);
286 public <C> void forObjects(ReadGraphImpl graph, int resourceKey, int predicateKey, int objectIndex, C context, AsyncContextMultiProcedure<C, Resource> procedure,
287 ClusterSupport support) throws DatabaseException {
289 System.out.println("ClusterSmall.forObjects1: rk=" + resourceKey + " pk=" + predicateKey);
291 if (0 == objectIndex) {
292 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
293 final int pRef = getInternalReferenceOrZero2(predicateKey, support);
294 final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
295 resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);
298 objectTable.foreachObject(graph, objectIndex, context, procedure, this);
302 public <Context> boolean forObjects(int resourceKey, int predicateKey, int objectIndex, ObjectProcedure<Context> procedure,
303 Context context, ClusterSupport support) throws DatabaseException {
305 System.out.println("ClusterSmall.forObjects2: rk=" + resourceKey + " pk=" + predicateKey);
306 if (deleted) return false;
307 if (0 == objectIndex) {
308 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
309 final short pRef = getInternalReferenceOrZero2(predicateKey, support);
310 final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
311 return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);
313 return objectTable.foreachObject(objectIndex, procedure, context, support, this);
317 public int getSingleObject(int resourceKey, int predicateKey, ClusterSupport support) throws DatabaseException {
319 System.out.println("ClusterSmall.getSingleObject2: rk=" + resourceKey + " pk=" + predicateKey);
320 if (deleted) return 0;
321 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
322 final short pRef = getInternalReferenceOrZero2(predicateKey, support);
323 final int completeType = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);
324 final ClusterI.CompleteTypeEnum pCompleteType = CompleteTypeEnum.make(completeType);
325 if (completeType > 0)
326 return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
327 final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;
328 if (0 == predicateIndex) // All relevant data is in resource table.
329 return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
330 int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);
331 return getSingleObject(resourceKey, predicateKey, objectIndex, support);
335 public <T> int getSingleObject(int resourceKey, ForPossibleRelatedValueProcedure<T> procedure, ClusterSupport support) throws DatabaseException {
336 if (deleted) return 0;
337 final short resourceIndex = (short)ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
338 final int predicateKey = procedure.predicateKey;
339 int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);
341 if(procedure.clusterKey[0] == clusterKey) {
342 pRef = (short)procedure.predicateReference[0];
344 pRef = getInternalReferenceOrZero2(predicateKey, support);
345 procedure.clusterKey[0] = clusterKey;
346 procedure.predicateReference[0] = pRef;
349 final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;
350 if (CompleteTypeEnum.NotComplete != pCompleteType)
351 return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
352 final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;
353 if (0 == predicateIndex) // All relevant data is in resource table.
354 return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
355 int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);
356 return getSingleObject(resourceKey, predicateKey, objectIndex, support);
360 public <C, T> int getSingleObject(int resourceKey, ForPossibleRelatedValueContextProcedure<C, T> procedure, ClusterSupport support) throws DatabaseException {
361 if (deleted) return 0;
362 final short resourceIndex = (short)ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
363 final int predicateKey = procedure.predicateKey;
364 int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);
366 if(procedure.clusterKey[0] == clusterKey) {
367 pRef = (short)procedure.predicateReference[0];
369 pRef = getInternalReferenceOrZero2(predicateKey, support);
370 procedure.clusterKey[0] = clusterKey;
371 procedure.predicateReference[0] = pRef;
373 final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;
374 if (CompleteTypeEnum.NotComplete != pCompleteType)
375 return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
376 final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;
377 if (0 == predicateIndex) // All relevant data is in resource table.
378 return resourceTable.getSingleObject(resourceIndex, support, pRef, pCompleteType, completeTable, this);
379 int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);
380 return getSingleObject(resourceKey, predicateKey, objectIndex, support);
384 public void forObjects(ReadGraphImpl graph, int resourceKey,
385 int predicateKey, AsyncMultiProcedure<Resource> procedure) throws DatabaseException {
387 SessionImplSocket session = (SessionImplSocket)graph.getSession();
388 ClusterSupport support = session.clusterTranslator;
390 System.out.println("ClusterSmall.forObjects3: rk=" + resourceKey + " pk=" + predicateKey);
391 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
392 final int pRef = getInternalReferenceOrZero2(predicateKey, support);
393 final int completeType = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);
394 final ClusterI.CompleteTypeEnum pCompleteType = CompleteTypeEnum.make(completeType);
395 if (completeType > 0) {
396 resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
399 final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;
400 if (0 == predicateIndex) {
401 resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
404 int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);
405 forObjects(graph, resourceKey, predicateKey, objectIndex, procedure, support);
408 public void forObjects(ReadGraphImpl graph, int resourceKey, ForEachObjectProcedure procedure) throws DatabaseException {
410 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
411 final int predicateKey = procedure.predicateKey;
412 int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);
414 if(procedure.clusterKey[0] == clusterKey) {
415 pRef = procedure.predicateReference[0];
417 SessionImplSocket session = (SessionImplSocket)graph.getSession();
418 ClusterSupport support = session.clusterTranslator;
419 pRef = getInternalReferenceOrZero2(predicateKey, support);
420 procedure.clusterKey[0] = clusterKey;
421 procedure.predicateReference[0] = pRef;
423 final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;
424 if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
425 SessionImplSocket session = (SessionImplSocket)graph.getSession();
426 ClusterSupport support = session.clusterTranslator;
427 resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
430 final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;
431 if (0 == predicateIndex) {
432 SessionImplSocket session = (SessionImplSocket)graph.getSession();
433 ClusterSupport support = session.clusterTranslator;
434 resourceTable.foreachObject(resourceIndex, graph, procedure, support, pRef, pCompleteType, completeTable, this);
437 int hashBase = predicateIndex + predicateTable.offset;
438 if (predicateTable.table[hashBase-1] < 0) {
439 int objectIndex = TableIntArraySet2.get(predicateTable.table, hashBase, pRef & 0xFFFF);
440 //int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);
441 SessionImplSocket session = (SessionImplSocket)graph.getSession();
442 ClusterSupport support = session.clusterTranslator;
443 forObjects(graph, resourceKey, predicateKey, objectIndex, procedure, support);
445 procedure.finished(graph);
450 public <C> void forObjects(ReadGraphImpl graph, int resourceKey, C context, ForEachObjectContextProcedure<C> procedure) throws DatabaseException {
452 final int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
453 final int predicateKey = procedure.predicateKey;
454 int clusterKey = ClusterTraitsBase.getClusterMaskFromResourceKey(resourceKey);
456 if(procedure.clusterKey[0] == clusterKey) {
457 pRef = procedure.predicateReference[0];
459 SessionImplSocket session = (SessionImplSocket)graph.getSession();
460 ClusterSupport support = session.clusterTranslator;
461 pRef = getInternalReferenceOrZero2(predicateKey, support);
462 procedure.clusterKey[0] = clusterKey;
463 procedure.predicateReference[0] = pRef;
466 final ClusterI.CompleteTypeEnum pCompleteType = procedure.completeType;
467 if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
468 SessionImplSocket session = (SessionImplSocket)graph.getSession();
469 ClusterSupport support = session.clusterTranslator;
470 resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);
473 final int predicateIndex = (int)resourceTable.table[(resourceIndex<<1) - 1 + resourceTable.offset] & 0xFFFFFF;
474 if (0 == predicateIndex) {
475 SessionImplSocket session = (SessionImplSocket)graph.getSession();
476 ClusterSupport support = session.clusterTranslator;
477 resourceTable.foreachObject(resourceIndex, graph, context, procedure, support, pRef, pCompleteType, completeTable, this);
480 int hashBase = predicateIndex + predicateTable.offset;
481 if(predicateTable.table[hashBase-1] < 0) {
482 int objectIndex = TableIntArraySet2.get(predicateTable.table, hashBase, pRef & 0xFFFF);
483 SessionImplSocket session = (SessionImplSocket)graph.getSession();
484 ClusterSupport support = session.clusterTranslator;
485 forObjects(graph, resourceKey, predicateKey, objectIndex, context, procedure, support);
487 int objectIndex = TableIntSet2.get(predicateTable.table, hashBase, pRef & 0xFFFF);
488 SessionImplSocket session = (SessionImplSocket)graph.getSession();
489 ClusterSupport support = session.clusterTranslator;
490 forObjects(graph, resourceKey, predicateKey, objectIndex, context, procedure, support);
494 public <Context> boolean forObjects(int resourceKey, int predicateKey,
495 ObjectProcedure<Context> procedure, Context context, ClusterSupport support)
496 throws DatabaseException {
498 System.out.println("ClusterSmall.forObjects4: rk=" + resourceKey + " pk=" + predicateKey);
499 if (deleted) return false;
500 final short resourceIndex = (short)ClusterTraitsBase.getResourceIndexFromResourceKey(resourceKey);
501 final short pRef = getInternalReferenceOrZero2(predicateKey, support);
502 final ClusterI.CompleteTypeEnum pCompleteType = ClusterTraitsBase.getCompleteTypeFromResourceKey(predicateKey);
503 // PredicateType is complete i.e. all relevant data is in resource table.
504 if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
506 System.out.println("ClusterSmall.forObjects: complete type was " + pCompleteType + " cluster=" + getClusterUID());
507 return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);
509 final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
510 if (0 == predicateIndex) { // All relevant data is in resource table.
512 System.out.println("ClusterSmall.forObjects: no predicate table " + pCompleteType);
513 return resourceTable.foreachObject(resourceIndex, procedure, context, support, this, pRef, pCompleteType, completeTable);
515 int objectIndex = predicateTable.getObjectIndex(predicateIndex, pRef & 0xFFFF);
516 return forObjects(resourceKey, predicateKey, objectIndex, procedure, context, support);
519 public <Context> boolean forPredicates(int resourceKey,
520 PredicateProcedure<Context> procedure, Context context, ClusterSupport support)
521 throws DatabaseException {
523 System.out.println("ClusterSmall.forPredicates: rk=" + resourceKey );
524 if (deleted) return false;
525 final int resourceIndex = getLocalReference(resourceKey);
526 final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
527 if (0 == predicateIndex)
528 return resourceTable.foreachPredicate(resourceIndex,
529 procedure, context, support, this, completeTable);
531 boolean broken = resourceTable.foreachPredicate(resourceIndex,
532 procedure, context, support, this, completeTable);
536 return predicateTable.foreachPredicate(predicateIndex,
537 procedure, context, support, this);
540 public ClusterI addRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)
541 throws DatabaseException {
543 System.out.println("add rk=" + sResourceKey + " pk=" + pResourceKey + " ok=" + oResourceKey);
544 if (deleted) return null;
546 ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);
547 return cluster.addRelation(sResourceKey, pResourceKey, oResourceKey, support);
553 short sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.ADD_OPERATION);
554 short pri = getReferenceOrCreateIfForeign(pResourceKey, support, ClusterStream.NULL_OPERATION);
555 short ori = getReferenceOrCreateIfForeign(oResourceKey, support, ClusterStream.NULL_OPERATION);
556 ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);
557 ret = addRelationInternal(sri, pri, ori, completeType);
558 calculateModifiedId();
559 } catch (OutOfSpaceException e) {
560 boolean streamOff = support.getStreamOff();
562 support.cancelStatement(this);
563 support.setStreamOff(true);
565 ClusterI cluster = toBig(support);
567 support.setStreamOff(false);
568 ClusterI cluster2 = cluster.addRelation(sResourceKey, pResourceKey, oResourceKey, support);
569 if (cluster != cluster2)
570 throw new DatabaseException("Internal error. Contact application support.");
575 support.addStatement(this);
578 support.cancelStatement(this);
583 public boolean removeRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)
584 throws DatabaseException {
585 if (deleted) return false;
586 short sri = getLocalReferenceAnd(sResourceKey, support, ClusterChange.REMOVE_OPERATION);
587 short pri = getInternalReferenceOrZeroAnd(pResourceKey, support, ClusterStream.NULL_OPERATION);
588 short ori = getInternalReferenceOrZeroAnd(oResourceKey, support, ClusterStream.NULL_OPERATION);
590 if (0 != pri && 0 != ori) {
591 ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);
592 ret = removeRelationInternal(sri, pri, ori, completeType, support);
593 calculateModifiedId();
596 support.removeStatement(this);
598 support.cancelStatement(this);
603 public void denyRelation(int sResourceKey, int pResourceKey, int oResourceKey, ClusterSupport support)
604 throws DatabaseException {
606 short s = checkResourceKeyIsOursAndGetResourceIndexIf(sResourceKey, support);
607 ResourceReferenceAndCluster p = checkResourceKeyAndGetResourceIndexIf(pResourceKey, support);
608 ResourceReferenceAndCluster o = checkResourceKeyAndGetResourceIndexIf(oResourceKey, support);
609 if (0 == s || 0 == p.reference || 0 == o.reference)
612 ClusterI.CompleteTypeEnum completeType = ClusterTraitsBase.getCompleteTypeFromResourceKey(pResourceKey);
613 boolean ret = removeRelationInternal(s, p.reference, o.reference, completeType, support);
615 support.addStatementIndex(this, sResourceKey, getClusterUID(), ClusterChange.REMOVE_OPERATION);
616 support.addStatementIndex(this, pResourceKey, p.clusterUID, ClusterStream.NULL_OPERATION);
617 support.addStatementIndex(this, oResourceKey, o.clusterUID, ClusterStream.NULL_OPERATION);
618 support.removeStatement(this);
620 calculateModifiedId();
625 public InputStream getValueStream(int resourceKey, ClusterSupport support) throws DatabaseException {
627 System.out.println("ClusterSmall.getValue " + resourceKey);
628 if (deleted) return null;
629 int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);
631 byte[] buffer = resourceTable.getValue(valueTable, resourceIndex);
632 if(buffer == null) return null;
633 return new ByteArrayInputStream(buffer);
634 } catch (ExternalValueException e) {
635 return support.getValueStreamEx(resourceIndex, clusterId);
639 public byte[] getValue(int resourceKey, ClusterSupport support)
640 throws DatabaseException {
642 System.out.println("ClusterSmall.getValue " + resourceKey);
643 if (deleted) return null;
644 int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);
646 return resourceTable.getValue(valueTable, resourceIndex);
647 } catch (ExternalValueException e) {
648 return support.getValueEx(resourceIndex, clusterId);
652 public boolean hasValue(int resourceKey, ClusterSupport support)
653 throws DatabaseException {
654 if (deleted) return false;
655 int resourceIndex = getLocalReference(resourceKey);
656 return resourceTable.hasValue(resourceIndex);
659 public boolean removeValue(int resourceKey, ClusterSupport support)
660 throws DatabaseException {
661 if (deleted) return false;
662 int resourceIndex = getLocalReferenceAnd(resourceKey, support, ClusterChange.DELETE_OPERATION);
663 support.removeValue(this);
664 calculateModifiedId();
665 return resourceTable.removeValue(valueTable, resourceIndex);
668 public ClusterI setValue(int rResourceId, byte[] value, int length, ClusterSupport support)
669 throws DatabaseException {
670 if (deleted) return null;
671 int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.SET_OPERATION);
672 support.setValue(this, getClusterId(), value, length);
674 resourceTable.setValue(valueTable, resourceIndex, value, length);
675 calculateModifiedId();
677 } catch (OutOfSpaceException e) {
678 boolean streamOff = support.getStreamOff();
680 support.setStreamOff(true);
681 ClusterI cluster = toBig(support);
682 cluster.setValue(rResourceId, value, length, support);
684 support.setStreamOff(false);
689 public ClusterI modiValueEx(int rResourceId, long voffset, int length, byte[] value, int offset, ClusterSupport support)
690 throws DatabaseException {
691 if (deleted) return null;
692 int resourceIndex = getLocalReferenceAnd(rResourceId, support, ClusterStream.MODI_OPERATION);
693 support.modiValue(this, getClusterId(), voffset, length, value, offset);
694 resourceTable.setValueEx(valueTable, resourceIndex);
695 calculateModifiedId();
699 public byte[] readValueEx(int rResourceId, long voffset, int length, ClusterSupport support)
700 throws DatabaseException {
701 if (deleted) return null;
702 int resourceIndex = getLocalReference(rResourceId);
703 boolean isExternal = resourceTable.isValueEx(valueTable, resourceIndex);
705 throw new DatabaseException("ClusterI.readValue supported only for external value. Resource key=" + rResourceId);
706 return support.getValueEx(resourceIndex, getClusterId(), voffset, length);
709 public long getValueSizeEx(int rResourceId, ClusterSupport support)
710 throws DatabaseException, ExternalValueException {
711 if (deleted) return 0;
712 int resourceIndex = getLocalReference(rResourceId);
713 boolean isExternal = resourceTable.isValueEx(valueTable, resourceIndex);
715 throw new ExternalValueException("ClusterI.getValueSizeEx supported only for external value. Resource key=" + rResourceId);
716 return support.getValueSizeEx(resourceIndex, getClusterId());
719 public void setValueEx(int rResourceId)
720 throws DatabaseException {
721 int resourceIndex = getLocalReference(rResourceId);
722 resourceTable.setValueEx(valueTable, resourceIndex);
725 public int createResource(ClusterSupport support)
726 throws DatabaseException {
727 if (deleted) return 0;
729 ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);
730 return cluster.createResource(support);
733 short resourceIndex = resourceTable.createResource();
734 calculateModifiedId();
735 if(DebugPolicy.REPORT_RESOURCE_ID_ALLOCATION)
736 System.out.println("[RID_ALLOCATION]: ClusterSmall[" + clusterId + "] allocates " + resourceIndex);
737 support.createResource(this, resourceIndex, getClusterId());
738 return ClusterTraits.createResourceKey(clusterKey, resourceIndex);
741 public boolean hasResource(int resourceKey, ClusterSupport support) {
742 if (deleted) return false;
743 int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(resourceKey);
744 if (this.clusterKey != clusterKey) // foreign resource
748 resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
749 } catch (DatabaseException e) {
752 if (resourceIndex > 0 & resourceIndex <= resourceTable.getTableCount())
758 public int getNumberOfResources(ClusterSupport support)
759 throws DatabaseException {
760 if (deleted) return 0;
762 ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);
763 return cluster.getNumberOfResources(support);
766 return resourceTable.getUsedSize();
769 public int getNumberOfResources() {
770 if (deleted || proxy)
772 return resourceTable.getUsedSize();
776 public long getUsedSpace() {
777 if (deleted) return 0;
778 if(isEmpty()) return 0;
779 long rt = resourceTable.getTableCapacity() * 8 + 8; // (8 = cluster id)
780 long ft = foreignTable.getTableCapacity() * 8;
781 long pt = predicateTable.getTableCapacity() * 4;
782 long ot = objectTable.getTableCapacity() * 4;
783 long ct = completeTable.getTableCapacity() * 4;
784 long vt = valueTable.getTableCapacity() * 1;
785 long cm = clusterMap.getUsedSpace();
786 return rt + ft + pt + ot + ct + vt + cm;
789 public boolean isEmpty() {
790 if (deleted) return true; // Deleted cluster is always empty.
791 if(resourceTable == null) return true;
792 return resourceTable.getTableCount() == 0;
795 public void printDebugInfo(String message, ClusterSupport support)
796 throws DatabaseException {
798 throw new DatabaseException("Not implemented!");
800 private short getInternalReferenceOrZero2(int resourceKey, ClusterSupport support) throws DatabaseException {
801 int resourceIndex = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);
802 if (!ClusterTraitsBase.isCluster(clusterBits, resourceKey)) {
803 return clusterMap.getForeignReferenceOrZero(resourceKey);
805 return (short)resourceIndex;
808 private short getInternalReferenceOrZeroAnd(int resourceKey, ClusterSupport support, byte op)
809 throws DatabaseException {
810 int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
811 int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
812 if (this.clusterKey != clusterKey) { // foreign resource
813 ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);
814 ClusterUID clusterUID = foreignCluster.getClusterUID();
815 short foreignRef = clusterMap.getForeignReferenceOrZero(resourceKey);
816 support.addStatementIndex(this, resourceKey, clusterUID, op);
819 support.addStatementIndex(this, resourceKey, getClusterUID(), op);
820 return (short)resourceIndex;
822 private final short getLocalReference(int resourceKey) throws DatabaseException {
823 return ClusterTraits.getResourceIndexFromResourceKeyNoThrow(resourceKey);
825 private final short getLocalReferenceAnd(int resourceKey, ClusterSupport support, byte op)
826 throws DatabaseException {
827 short resourceIndex = getLocalReference(resourceKey);
828 support.addStatementIndex(this, resourceKey, getClusterUID(), op);
829 return resourceIndex;
831 private short checkResourceKeyIsOursAndGetResourceIndexIf(int resourceKey, ClusterSupport support)
832 throws DatabaseException {
833 int clusterShortId = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
834 if (this.clusterKey != clusterShortId)
836 int resourceIndex = ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
837 return (short)resourceIndex;
839 private short getReferenceOrCreateIfForeign(int resourceKey, ClusterSupport support, byte op)
840 throws DatabaseException {
841 int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
842 short resourceIndex = (short)ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
843 if (this.clusterKey != clusterKey) {
844 ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);
845 ClusterUID clusterUID = foreignCluster.getClusterUID();
846 support.addStatementIndex(this, resourceKey, clusterUID, op);
847 short ref = clusterMap.getForeignReferenceOrCreateByResourceKey(resourceKey, clusterUID);
850 support.addStatementIndex(this, resourceKey, getClusterUID(), op);
851 return resourceIndex;
853 private class ResourceReferenceAndCluster {
854 ResourceReferenceAndCluster(short reference, ClusterUID clusterUID) {
855 this.reference = reference;
856 this.clusterUID = clusterUID;
858 public final short reference;
859 public final ClusterUID clusterUID;
861 private ResourceReferenceAndCluster checkResourceKeyAndGetResourceIndexIf(int resourceKey, ClusterSupport support)
862 throws DatabaseException {
863 int clusterKey = ClusterTraits.getClusterKeyFromResourceKey(resourceKey);
864 short resourceIndex = (short)ClusterTraits.getResourceIndexFromResourceKey(resourceKey);
865 if (this.clusterKey != clusterKey) { // foreign resource
866 ClusterI foreignCluster = support.getClusterByClusterKey(clusterKey);
867 ClusterUID clusterUID = foreignCluster.getClusterUID();
868 short ref = clusterMap.getForeignReferenceOrZero(resourceKey);
869 return new ResourceReferenceAndCluster(ref, clusterUID);
871 return new ResourceReferenceAndCluster(resourceIndex, getClusterUID());
874 static long fTime = 0;
876 int executeIndex = 0;
877 long clusterUID1 = 0;
878 long clusterUID2 = 0;
881 final public int execute(int resourceReference) throws DatabaseException {
883 if (deleted) return 0;
884 short resourceRef = (short)resourceReference;
886 if (ClusterTraitsSmall.resourceRefIsLocal(resourceRef)) {
887 key = clusterBits | resourceRef;
889 foreignTable.fillResourceUID(ClusterTraitsSmall.resourceRefGetForeignIndex((short)resourceRef), this);
890 key = ClusterTraitsBase.createResourceKey(clusterSupport.getClusterKeyByClusterUIDOrMake(clusterUID1, clusterUID2), executeIndex);
893 System.out.println("ClusterSmall.execute key=" + key);
897 private boolean addRelationInternal(short sReference, short pReference, short oReference, ClusterI.CompleteTypeEnum completeType)
898 throws DatabaseException {
899 int predicateIndex = resourceTable.addStatement(sReference, pReference, oReference, predicateTable, objectTable, completeType, completeTable);
900 if (0 == predicateIndex)
901 return true; // added to resourceTable
902 else if (0 > predicateIndex)
903 return false; // old complete statemenent
904 int newPredicateIndex = predicateTable.addPredicate(predicateIndex, 0xFFFF & pReference, 0xFFFF & oReference, objectTable);
905 if (0 == newPredicateIndex)
907 if (predicateIndex != newPredicateIndex)
908 resourceTable.setPredicateIndex(sReference, newPredicateIndex);
911 private boolean removeRelationInternal(int sResourceIndex, short pResourceIndex,
912 short oResourceIndex, ClusterI.CompleteTypeEnum completeType, ClusterSupport support)
913 throws DatabaseException {
914 int predicateIndex = resourceTable.getPredicateIndex(sResourceIndex);
915 if (0 == predicateIndex || ClusterI.CompleteTypeEnum.NotComplete != completeType)
916 return resourceTable.removeStatementFromCache(sResourceIndex,
917 pResourceIndex, oResourceIndex, completeType, completeTable);
918 PredicateTable.Status ret = predicateTable.removePredicate(predicateIndex, 0xFFFF & pResourceIndex, 0xFFFF & oResourceIndex, objectTable);
922 case PredicateRemoved: {
923 if (0 == predicateTable.getPredicateSetSize(predicateIndex))
924 resourceTable.setPredicateIndex(sResourceIndex, 0);
925 // intentionally dropping to next case
929 resourceTable.removeStatement(sResourceIndex,
930 pResourceIndex, oResourceIndex,
931 completeType, completeTable,
932 predicateTable, objectTable, support);
938 throw new Error("Not supported.");
942 public void load(Consumer<DatabaseException> r) {
944 throw new Error("Not supported.");
947 public boolean contains(int resourceKey) {
948 if (deleted) return false;
949 return ClusterTraitsBase.isCluster(clusterBits, resourceKey);
952 public void load(final ClusterSupport support, final Runnable callback) {
955 clusterTable.load2(clusterId, clusterKey);
957 } catch (DatabaseException e) {
963 public ClusterI getClusterByResourceKey(int resourceKey,
964 ClusterSupport support) {
965 if (deleted) return null;
969 public void increaseReferenceCount(int amount) {
974 public void decreaseReferenceCount(int amount) {
979 public int getReferenceCount() {
980 if (deleted) return 0;
984 public void releaseMemory() {
987 public void compact() {
989 clusterMap.compact();
992 public boolean isLoaded() {
993 return !proxy || deleted; // Deleted cluster is always loaded.
996 public ClusterImpl tryLoad(SessionImplSocket sessionImpl) throws DatabaseException {
997 if (deleted) return this; // Never load deleted cluster.
998 return clusterTable.tryLoad(clusterId, clusterKey);
1003 public ClusterBig toBig(ClusterSupport support)
1004 throws DatabaseException {
1006 System.out.println("DEBUG: toBig cluster=" + clusterId);
1007 new Exception().printStackTrace();
1009 if (deleted) return null; // Can't convert deleted cluster to big.
1010 ClusterBig big = new ClusterBig(getClusterUID(), clusterKey, support);
1011 big.setImportance(importance);
1013 big.cc.clusterImpl = this;
1014 resourceTable.toBig(big, support, this);
1015 big.foreignLookup = this.foreignLookup;
1016 big.change = this.change;
1018 this.foreignLookup = null;
1024 public ClusterTypeEnum getType() {
1025 return ClusterTypeEnum.SMALL;
1028 public boolean getImmutable() {
1029 if (deleted) return false;
1030 if (null == resourceTable)
1032 int status = resourceTable.getClusterStatus();
1033 return (status & ClusterStatus.ImmutableMaskSet) == ClusterStatus.ImmutableMaskSet;
1036 public void setImmutable(boolean immutable, ClusterSupport support) {
1037 if (deleted) return;
1038 if(resourceTable != null) {
1039 int status = resourceTable.getClusterStatus();
1041 status |= ClusterStatus.ImmutableMaskSet;
1043 status &= ClusterStatus.ImmutableMaskClear;
1044 resourceTable.setClusterStatus(status);
1046 support.setImmutable(this, immutable);
1049 public boolean getDeleted() {
1050 if (deleted) return true;
1051 int status = resourceTable.getClusterStatus();
1052 return (status & ClusterStatus.DeletedMaskSet) == ClusterStatus.DeletedMaskSet;
1055 public void setDeleted(boolean set, ClusterSupport support) {
1057 if(resourceTable != null) {
1058 int status = resourceTable.getClusterStatus();
1060 status |= ClusterStatus.DeletedMaskSet;
1062 status &= ClusterStatus.DeletedMaskClear;
1063 resourceTable.setClusterStatus(status);
1065 if (null != support)
1066 support.setDeleted(this, set);
1069 public String toString() {
1070 if (deleted) return "ClusterSmall[" + getClusterId() + " - has been deleted or hasn't been created.]";
1072 ForeignTableSmall ft = foreignTable;
1074 return "ClusterSmall[" + getClusterId() + " - " + getNumberOfResources() + "]";
1075 TIntShortHashMap map = ft.getResourceHashMap();
1076 TIntHashSet set = new TIntHashSet();
1077 map.forEachKey(value -> {
1078 set.add(value & 0xfffff000);
1081 return "ClusterSmall[" + getClusterId() + " - " + getNumberOfResources() + " - " + foreignTable.getResourceHashMap().size() + " - " + set.size() + "]";
1082 } catch (Throwable e) {
1083 return "ClusterSmall[" + getNumberOfResources() + "]";
1087 public Table<?> getPredicateTable() {
1088 return predicateTable;
1091 public Table<?> getForeignTable() {
1092 return foreignTable;
1095 public int makeResourceKey(int pRef) throws DatabaseException {
1096 throw new UnsupportedOperationException();
1099 public Table<?> getCompleteTable() {
1100 return completeTable;
1103 public Table<?> getValueTable() {
1107 public Table<?> getObjectTable() {
1113 class ClusterStatus {
1114 public static final int ImmutableMaskClear = 0xFFFFFFFE;
1115 public static final int ImmutableMaskSet = 0x00000001;
1116 public static final int DeletedMaskClear = 0xFFFFFFFD;
1117 public static final int DeletedMaskSet = 0x00000002;