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.util.ArrayList;
16 import org.simantics.db.Resource;
17 import org.simantics.db.common.utils.Logger;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.exception.ExternalValueException;
20 import org.simantics.db.exception.ValidationException;
21 import org.simantics.db.impl.ClusterBase;
22 import org.simantics.db.impl.ClusterI;
23 import org.simantics.db.impl.ClusterI.CompleteTypeEnum;
24 import org.simantics.db.impl.ClusterI.ObjectProcedure;
25 import org.simantics.db.impl.ClusterI.PredicateProcedure;
26 import org.simantics.db.impl.ClusterI.Procedure;
27 import org.simantics.db.impl.ClusterSupport;
28 import org.simantics.db.impl.ClusterTraitsBase;
29 import org.simantics.db.impl.Modifier;
30 import org.simantics.db.impl.ResourceImpl;
31 import org.simantics.db.impl.Table;
32 import org.simantics.db.impl.TableFactory;
33 import org.simantics.db.impl.TableSizeListener;
34 import org.simantics.db.impl.graph.ReadGraphImpl;
35 import org.simantics.db.procedure.AsyncContextMultiProcedure;
36 import org.simantics.db.procedure.SyncContextMultiProcedure;
37 import org.simantics.db.procedure.SyncMultiProcedure;
38 import org.simantics.db.procore.cluster.PredicateTable.Status;
41 final class ResourceElement {
42 private static final boolean DEBUG = ClusterImpl.DEBUG;
43 private static final int DESCRIPTOR_OFFSET = 0; // predicate descriptor
44 private static final int VALUE_OFFSET = 1; // value descriptor
45 private static final int STM_OFFSET = 2; // first statement
46 private static final int SIZE_OF = 4;
48 static void construct(long[] table, int index) {
49 int i = DESCRIPTOR_OFFSET + index;
50 table[i++] = 0; // predicate capacity & index
51 table[i++] = 0; // value capacity & index
52 table[i++] = 0; // stm1
53 table[i++] = 0; // stm2
56 static void destruct(long[] table, int index) {
57 int i = DESCRIPTOR_OFFSET + index;
58 table[i++] = 0; // predicate capacity & index
59 table[i++] = 0; // value capacity & index
60 table[i++] = 0; // stm1
61 table[i++] = 0; // stm2
64 static boolean isUsed(long[] table, int index) {
65 int i = DESCRIPTOR_OFFSET + index;
77 static int getSizeOf() {
81 static int getCompleteObjectRef(long[] table, int index) {
82 int i = DESCRIPTOR_OFFSET + index;
83 return BitUtility.getHighInt(table[i]);
86 static void setCompleteObjectRef(long[] table, int index, int ref) {
87 int i = DESCRIPTOR_OFFSET + index;
88 table[i] = BitUtility.setHighInt(table[i], ref);
91 static int getPredicateIndex(long[] table, int index) {
92 int i = DESCRIPTOR_OFFSET + index;
93 int predicateIndex = BitUtility.getLowInt(table[i]);
94 assert (predicateIndex >= 0);
95 return predicateIndex;
98 static void setPredicateIndex(long[] table, int index, int predicateIndex) {
99 assert (predicateIndex >= 0);
100 int i = DESCRIPTOR_OFFSET + index;
101 table[i] = BitUtility.setLowInt(table[i], predicateIndex);
104 static int copyValue(ValueTable valueTable, long[] table, int index, byte[] byteTable, int byteSize, int byteBase,
106 int i = VALUE_OFFSET + index;
107 if (0 == table[i] || -1 == table[i])
108 return byteCurrent; // no value or external value
109 // getValueCapacity call optimized away
110 int capacity = BitUtility.getLowInt(table[i]);
111 int valueIndex = getValueIndex(table, index);
114 valueTable.getValue(valueIndex, byteTable, byteCurrent, capacity);
115 valueIndex = byteCurrent - byteBase;
116 setValueIndex(table, index, valueIndex);
117 byteCurrent += capacity;
121 static byte[] getValue(ValueTable valueTable, long[] table, int index)
122 throws DatabaseException {
123 int i = VALUE_OFFSET + index;
125 return null; // no value
127 throw new ExternalValueException("Value stored externally.");
128 // getValueCapacity call optimized away
129 int capacity = BitUtility.getLowInt(table[i]);
130 byte[] t = new byte[capacity];
131 int valueIndex = getValueIndex(table, index);
132 valueTable.getValue(valueIndex, t, 0, capacity);
136 // static int getString(ValueTable valueTable, long[] table, int index, char[] t)
137 // throws DatabaseException {
138 // long l = table[index + VALUE_OFFSET];
140 // throw new ExternalValueException("String stored externally.");
141 // int capacity = (int)l;
142 // int valueIndex = (int) (l >>> 32);
143 //// char[] t = new char[capacity-1];
144 // valueTable.getString(valueIndex, t, 0, capacity-1);
145 // return capacity-1;
149 static boolean hasValue(long[] table, int index) {
150 int i = VALUE_OFFSET + index;
151 return 0 != table[i];
154 // static boolean hasValue(ValueTable valueTable, long[] table, int index, byte[] value) {
155 // int i = VALUE_OFFSET + index;
156 // if (0 == table[i])
158 // // getValueCapacity call optimized away
159 // int capacity = BitUtility.getLowInt(table[i]);
160 // if (capacity != value.length)
162 // int valueIndex = getValueIndex(table, index);
163 // return valueTable.isEqual(valueIndex, value);
166 static boolean removeValue(ValueTable valueTable, long[] table, int index) {
167 int i = VALUE_OFFSET + index;
170 else if (-1 != table[i]) {
171 // getValueCapacity call optimized away
172 int capacity = BitUtility.getLowInt(table[i]);
173 int valueIndex = getValueIndex(table, index);
174 valueTable.removeValue(valueIndex, capacity);
176 //setValueCapacityAndIndex(table, index, 0, 0); optimized away
181 public static void setValue(ValueTable valueTable, long[] table, int index, byte[] value, int length) {
182 int i = VALUE_OFFSET + index;
183 // getValueCapacity call optimized away
184 int capacity = BitUtility.getLowInt(table[i]);
185 int valueIndex = getValueIndex(table, index);
186 if (length <= capacity) {
187 valueTable.setValue(valueIndex, value, length);
188 // we "leak" memory TODO: add value size member to
189 // resource entry or value entry
190 setValueCapacity(table, index, length);
192 if (valueIndex != 0 && capacity > 0)
193 valueTable.removeValue(valueIndex, capacity);
194 valueIndex = valueTable.createValue(value, 0, length);
196 setValueCapacityAndIndex(table, index, capacity, valueIndex);
200 public static boolean isValueEx(ValueTable valueTable, long[] table, int index) {
201 int i = VALUE_OFFSET + index;
207 public static void setValueEx(ValueTable valueTable, long[] table, int index) {
208 int i = VALUE_OFFSET + index;
211 else if (0 != table[i]) {
212 int capacity = BitUtility.getLowInt(table[i]);
213 int valueIndex = getValueIndex(table, index);
214 valueTable.removeValue(valueIndex, capacity);
216 //setValueCapacityAndIndex(table, index, 0, 0); optimized away
219 static class ValueData {
222 // ValueData(int capacity, int index) {
223 // this.capacity = capacity;
224 // this.index = index;
227 static void getValueCapacityAndIndex(ValueData vd, long[] table, int index) {
228 int i = VALUE_OFFSET + index;
229 // getValueCapacity call optimized away
230 vd.capacity = BitUtility.getLowInt(table[i]);
231 vd.index = getValueIndex(table, index);
234 private static int getValueIndex(long[] table, int index) {
235 int i = VALUE_OFFSET + index;
236 return BitUtility.getHighInt(table[i]);
239 private static void setValueIndex(long[] table, int index, int valueIndex) {
240 int i = VALUE_OFFSET + index;
241 table[i] = BitUtility.setHighInt(table[i], valueIndex);
244 private static void setValueCapacity(long[] table, int index, int capacity) {
245 int i = VALUE_OFFSET + index;
246 table[i] = BitUtility.setLowInt(table[i], capacity);
249 private static void setValueCapacityAndIndex(long[] table, int index, int capacity, int valueIndex) {
250 int i = VALUE_OFFSET + index;
251 table[i] = BitUtility.setLowAndHighInt(table[i], capacity, valueIndex);
254 public static <Context> boolean foreachPredicate(long[] table, int index,
255 ClusterI.PredicateProcedure<Context> procedure,
256 Context context, ClusterSupport support, Modifier modifier,
258 throws DatabaseException {
260 System.out.println("ResourceElement.foreachPredicate: 1");
261 int completeRef = ResourceElement.getCompleteObjectRef(table, index);
262 if (0 != completeRef) {
263 if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements
264 boolean broken = ct.foreachPredicate(completeRef, procedure, context, support, modifier);
266 System.out.println("ResourceElement.foreachPredicate: multi-complete ci=" + completeRef + " break=" + broken);
268 return true; // loop broken by procedure
270 ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
271 if (ClusterI.CompleteTypeEnum.NotComplete != completeType) {
272 int key = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType);
273 boolean broken = procedure.execute(context, key, 0);
275 System.out.println("ResourceElement.foreachPredicate: complete rk=" + key + " break=" + broken);
277 return true; // loop broken by procedure
281 // If predicate set is in use it will contain also these statements.
282 if (0 != ResourceElement.getPredicateIndex(table, index)) {
284 System.out.println("ResourceElement.foreachPredicate: more than 2 objects");
287 int i = STM_OFFSET + index;
288 int p1 = BitUtility.getHighInt(table[i]);
291 System.out.println("ResourceElement.foreachPredicate: empty cache");
292 return false; // loop finished, no statements
295 if (null == modifier)
298 externalRef = modifier.execute(p1);
300 System.out.println("ResourceElement.foreachPredicate: cache1 pk=" + externalRef);
301 if (procedure.execute(context, externalRef, 0))
302 return true; // loop broken by procedure
303 int p2 = BitUtility.getHighInt(table[++i]);
304 if (0 == p2 || p1 == p2) {
306 System.out.println("ResourceElement.foreachPredicate: cache2 empty");
307 return false; // loop finished, one statement
308 } if (null == modifier)
311 externalRef = modifier.execute(p2);
313 System.out.println("ResourceElement.foreachPredicate: cache2 pk=" + externalRef);
314 if (procedure.execute(context, externalRef, 0))
315 return true; // loop broken by procedure
317 System.out.println("ResourceElement.foreachPredicate: not in cache");
318 return false; // loop finished, two statements
321 public static int getSingleObject(long[] table, int index, ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier)
322 throws DatabaseException {
324 System.out.println("ResourceElement.getSingleObject: index=" + index);
325 if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
326 int completeRef = getCompleteObjectRef(table, index);
327 if (0 == completeRef)
328 return 0; // no objects for given complete type
329 if (ClusterTraits.completeReferenceIsMultiple(completeRef)) {
330 // Multiple complete type elements.
332 System.out.println("ResourceElement.getSingleObject was complete 2");
334 implements ClusterI.ObjectProcedure<Integer> {
336 public boolean execute(Integer context, int completeRef)
337 throws DatabaseException {
338 ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);
339 if (pCompleteType == oCompleteType) { // we have a match
340 if (context != 0) { // we have an old match
341 context = 0; // multiple objects for given type
342 return true; // break loop
344 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
345 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
346 if (0 == clusterIndex) {
347 context = modifier.execute(resourceIndex);
349 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
350 context = modifier.execute(externalRef);
353 return true; // continue looping
357 ForeachObject t = new ForeachObject();
358 // CompleteRef is complete object set index.
360 ct.foreachComplete(completeRef, t, c, support, modifier);
363 // one complete type element
364 ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
365 if (pCompleteType != completeType)
367 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
368 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
369 if (0 == clusterIndex) {
370 return modifier.execute(resourceIndex);
372 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
373 return modifier.execute(externalRef);
376 int i = STM_OFFSET + index;
377 int p1 = BitUtility.getHighInt(table[i]);
379 return 0; // loop finished, no statements
382 int o1 = BitUtility.getLowInt(table[i]);
383 result = modifier.execute(o1);
384 // procedure.execute(graph, new ResourceImpl(null, modifier.execute(o1)));
386 // if (null == modifier)
389 // externalRef = modifier.execute(callerThread, o1);
390 // if (procedure.execute(callerThread, context, externalRef))
391 // return true; // loop broken by procedure
393 int p2 = BitUtility.getHighInt(table[++i]);
394 if (0 == p2 || pRef != p2)
395 return result; // loop finished, one statements
398 if (result != 0) return -1;
400 int o2 = BitUtility.getLowInt(table[i]);
401 return modifier.execute(o2);
404 // int o2 = BitUtility.getLowInt(table[i]);
406 // if (null == modifier)
409 // externalRef = modifier.execute(callerThread, o2);
410 // if (procedure.execute(callerThread, context, externalRef))
411 // return true; // loop broken by procedure
412 // return false; // loop finished
413 // procedure.execute(graph, new ResourceImpl(null, modifier.execute(o2)));
416 public static void foreachObject(long[] table, int index,
417 final ReadGraphImpl graph, final SyncMultiProcedure<Resource> procedure,
418 final ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier)
419 throws DatabaseException {
421 System.out.println("ResourceElement.foreachObject1: index=" + index);
422 if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
423 int completeRef = getCompleteObjectRef(table, index);
424 if (0 == completeRef) {
425 procedure.finished(graph);
426 // graph.state.dec(0);
427 return; // no objects for given complete type
429 if (ClusterTraits.completeReferenceIsMultiple(completeRef)) {
430 // Multiple complete type statements.
432 System.out.println("ResourceElement.was complete 2");
433 class ForeachObject implements ClusterI.ObjectProcedure<Object> {
435 public boolean execute(Object context, int completeRef) throws DatabaseException {
436 ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);
437 if (pCompleteType == oCompleteType) {
438 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
439 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
440 if (0 == clusterIndex) {
441 procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
443 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
444 procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
447 return false; // continue looping
451 ForeachObject t = new ForeachObject();
452 // CompleteRef is complete object set index.
453 ct.foreachComplete(completeRef, t, null, support, modifier);
454 procedure.finished(graph);
455 // graph.state.dec(0);
456 return; // loop finished
458 // one complete type element
459 ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
460 if (pCompleteType != completeType) {
461 procedure.finished(graph);
462 // graph.state.dec(0);
465 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
466 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
467 if (0 == clusterIndex) {
468 procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
470 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
471 procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
473 procedure.finished(graph);
474 // graph.state.dec(0);
475 return; // loop finished
477 int i = STM_OFFSET + index;
479 int p1 = (int) (l >>> 32);
481 procedure.finished(graph);
482 // graph.state.dec(0);
483 return; // loop finished, no statements
487 procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1)));
489 // if (null == modifier)
492 // externalRef = modifier.execute(callerThread, o1);
493 // if (procedure.execute(callerThread, context, externalRef))
494 // return true; // loop broken by procedure
496 long l2 = table[++i];
497 int p2 = (int) (l2 >>> 32);
499 procedure.finished(graph);
500 // graph.state.dec(0);
501 return; // loop finished, one statements
504 procedure.execute(graph, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2)));
505 procedure.finished(graph);
506 // graph.state.dec(0);
509 public static <C> void foreachObject(long[] table, int index,
510 final ReadGraphImpl graph, final C context, final SyncContextMultiProcedure<C, Resource> procedure,
511 final ClusterSupport support, final int pRef, final ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, final Modifier modifier)
512 throws DatabaseException {
514 System.out.println("ResourceElement.foreachObject1: index=" + index);
515 if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
516 int completeRef = getCompleteObjectRef(table, index);
517 if (0 == completeRef) {
518 procedure.finished(graph, context);
519 // graph.state.dec(0);
520 return; // no objects for given complete type
522 if (ClusterTraits.completeReferenceIsMultiple(completeRef)) {
523 // Multiple complete type statements.
525 System.out.println("ResourceElement.was complete 2");
526 class ForeachObject implements ClusterI.ObjectProcedure<Object> {
528 public boolean execute(Object _context, int completeRef) throws DatabaseException {
529 ClusterI.CompleteTypeEnum oCompleteType = ClusterTraits.completeReferenceGetType(completeRef);
530 if (pCompleteType == oCompleteType) {
531 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
532 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
533 if (0 == clusterIndex) {
534 procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
536 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
537 procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
540 return false; // continue looping
544 ForeachObject t = new ForeachObject();
545 // CompleteRef is complete object set index.
546 ct.foreachComplete(completeRef, t, null, support, modifier);
547 procedure.finished(graph, context);
548 // graph.state.dec(0);
549 return; // loop finished
551 // one complete type element
552 ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
553 if (pCompleteType != completeType) {
554 procedure.finished(graph, context);
555 // graph.state.dec(0);
558 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
559 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
560 if (0 == clusterIndex) {
561 procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(resourceIndex)));
563 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
564 procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(externalRef)));
566 procedure.finished(graph, context);
567 // graph.state.dec(0);
568 return; // loop finished
570 int i = STM_OFFSET + index;
572 int p1 = (int) (l >>> 32);
574 procedure.finished(graph, context);
575 // graph.state.dec(0);
576 return; // loop finished, no statements
580 procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o1)));
582 // if (null == modifier)
585 // externalRef = modifier.execute(callerThread, o1);
586 // if (procedure.execute(callerThread, context, externalRef))
587 // return true; // loop broken by procedure
589 long l2 = table[++i];
590 int p2 = (int) (l2 >>> 32);
592 procedure.finished(graph, context);
593 // graph.state.dec(0);
594 return; // loop finished, one statements
597 procedure.execute(graph, context, new ResourceImpl(graph.getResourceSupport(), modifier.execute(o2)));
598 procedure.finished(graph, context);
599 // graph.state.dec(0);
602 public static <Context> boolean foreachObject(long[] table, int index
603 , ClusterI.ObjectProcedure<Context> procedure
604 , Context context, ClusterSupport support, Modifier modifier
605 , final int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)
606 throws DatabaseException {
608 System.out.println("ResourceElement.foreachObject2: 1 ");
609 if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType) {
610 int completeRef = getCompleteObjectRef(table, index);
611 if (0 == completeRef) {
613 System.out.println("ResourceElement.foreachObject2: no complete");
614 return false; // no objects for given complete type
616 if (ClusterTraits.completeReferenceIsMultiple(completeRef)) { // multiple complete type elements
618 System.out.println("ResourceElement.foreachObject2: multi-complete ci=" + completeRef);
619 return ct.foreachObject(completeRef, procedure, context, support, modifier, pCompleteType);
621 // one complete type element
622 ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
623 if (pCompleteType != completeType) {
625 System.out.println("ResourceElement.foreachObject2: complete different predicate");
628 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
629 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
630 if (0 == clusterIndex) {
632 if (null == modifier)
633 externalRef = resourceIndex;
635 externalRef = modifier.execute(resourceIndex);
637 System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef);
638 if (procedure.execute(context, externalRef))
639 return true; // loop broken by procedure
641 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
642 if (null != modifier)
643 externalRef = modifier.execute(externalRef);
645 System.out.println("ResourceElement.foreachObject2: complete ok=" + externalRef);
646 if (procedure.execute(context, externalRef))
647 return true; // loop broken by procedure
649 return false; // loop finished
651 int i = STM_OFFSET + index;
652 int p1 = BitUtility.getHighInt(table[i]);
655 System.out.println("ResourceElement.foreachObject2: empty cache=");
656 return false; // loop finished, no statements
659 int o1 = BitUtility.getLowInt(table[i]);
661 if (null == modifier)
664 externalRef = modifier.execute(o1);
666 System.out.println("ResourceElement.foreachObject2: cache1 ok=" + externalRef);
667 if (procedure.execute(context, externalRef))
668 return true; // loop broken by procedure
670 int p2 = BitUtility.getHighInt(table[++i]);
671 if (0 == p2 || pRef != p2) {
673 System.out.println("ResourceElement.foreachObject2: not in cache1");
674 return false; // loop finished, one statements
676 int o2 = BitUtility.getLowInt(table[i]);
678 if (null == modifier)
681 externalRef = modifier.execute(o2);
683 System.out.println("ResourceElement.foreachObject2: cache2 ok=" + externalRef);
684 return procedure.execute(context, externalRef);
686 static boolean isEmpty(long[] table, int index) {
687 return getStatementCount(table, index) == 0 && !hasValue(table, index);
689 static int getStatementCount(long[] table, int index) {
690 int i = STM_OFFSET + index;
691 int p1 = BitUtility.getHighInt(table[i]);
692 int p2 = BitUtility.getLowInt(table[++i]);
697 int predicateIndex = getPredicateIndex(table, index);
698 if (0 == predicateIndex)
702 private static int makeCompleteObjectRef(int oRef, ClusterI.CompleteTypeEnum completeType) {
705 int resourceIndex = oRef;
706 int clusterIndex = 0;
707 ref = ClusterTraits.completeReferenceMake(completeType.getValue(), resourceIndex, clusterIndex);
710 assert(!ClusterTraits.isFlat(oRef));
711 ref = (completeType.getValue() <<30) | (oRef & 0x3FFFFFFF);
715 static int addStatement(long[] table, int index, int pRef, int oRef
716 , PredicateTable pt, ObjectTable ot
717 , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
718 throws DatabaseException {
721 if (ClusterI.CompleteTypeEnum.NotComplete != completeType) {
722 int cRef = makeCompleteObjectRef(oRef, completeType);
723 int ctr = getCompleteObjectRef(table, index);
725 setCompleteObjectRef(table, index, cRef);
729 return -1; // old complete
730 else if (ClusterTraits.completeReferenceIsMultiple(ctr)) {
731 nRef = ct.addComplete(ctr, cRef);
733 return -1; // old complete
735 nRef = ct.createCompleteArraySet(ctr, cRef);
737 setCompleteObjectRef(table, index, nRef);
739 return 0; // added to complete
741 int i = STM_OFFSET + index;
742 int p1 = BitUtility.getHighInt(table[i]);
743 int o1 = BitUtility.getLowInt(table[i]);
745 table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef);
746 return 0; // added to stm cache
747 } else if (p1 == pRef && o1 == oRef)
748 return -1; // same statement
749 int p2 = BitUtility.getHighInt(table[++i]);
750 int o2 = BitUtility.getLowInt(table[i]);
752 table[i] = BitUtility.setLowAndHighInt(table[i], oRef, pRef);
753 return 0; // added to stm cache
754 } else if (p2 == pRef && o2 == oRef)
755 return -1; // same statement
756 int predicateIndex = getPredicateIndex(table, index);
757 if (0 == predicateIndex) {
759 int objectIndex = ot.createObjectSet(o1, o2);
760 assert (0 != objectIndex);
761 int[] os = new int[1];
762 os[0] = ClusterTraits.statementIndexMake(objectIndex);
763 int[] ps = new int[1];
765 predicateIndex = pt.createPredicateSet(ps, os);
767 int[] os = new int[2];
770 int[] ps = new int[2];
773 predicateIndex = pt.createPredicateSet(ps, os);
775 assert (0 != predicateIndex);
776 setPredicateIndex(table, index, predicateIndex);
778 assert (0 != predicateIndex);
779 return predicateIndex;
782 static boolean removeStatement(long[] table, int index, int pRef, int oRef,
783 ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
784 throws DatabaseException {
787 if (completeType != ClusterI.CompleteTypeEnum.NotComplete) {
788 int completeRef = ResourceElement.getCompleteObjectRef(table, index);
789 if (0 != completeRef) {
790 ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef);
791 if (completeType == completeType2) {
792 int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
793 int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
794 if (0 == clusterIndex) {
795 if (oRef == resourceIndex) {
796 ResourceElement.setCompleteObjectRef(table, index, 0);
797 return true; // statement removed
800 int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
801 if (oRef == externalRef) {
802 ResourceElement.setCompleteObjectRef(table, index, 0);
803 return true; // statement removed
806 } else if (completeType2 == ClusterI.CompleteTypeEnum.NotComplete) { // multiple complete type references
807 int cRef = makeCompleteObjectRef(oRef, completeType);
808 int oldSize = ct.getCompleteSetSize(completeRef);
809 int newSize = ct.removeComplete(completeRef, cRef);
810 if (oldSize == newSize)
811 return false; // not removed
812 else if (newSize == 1) {
813 cRef = ct.removeLast(completeRef);
814 ResourceElement.setCompleteObjectRef(table, index, cRef);
820 int i = STM_OFFSET + index;
821 int p1 = BitUtility.getHighInt(table[i]);
822 int o1 = BitUtility.getLowInt(table[i]);
824 return false; // no statements cached
825 else if (p1 == pRef && o1 == oRef) {
826 table[i] = table[i + 1];
827 // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away
829 return true; // statement removed
831 int p2 = BitUtility.getHighInt(table[++i]);
832 int o2 = BitUtility.getLowInt(table[i]);
834 return false; // no match
835 else if (p2 == pRef && o2 == oRef) {
836 // BitUtility.setLowAndHighInt(table[i], 0, 0); optimized away
838 return true; // statement removed
844 public final class ResourceTable extends Table<long[]> {
845 public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase) {
846 super(TableFactory.getLongFactory(), sizeListener, header, headerBase);
849 public ResourceTable(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {
850 super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);
853 public int getUsedSize() {
854 return getTableCount();
857 public short createResource() {
858 final int INDEX = getTableCount();
859 final int SIZE = ResourceElement.getSizeOf();
860 int resourceIndex = createNewElement(SIZE);
861 assert (0 != resourceIndex);
862 final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);
863 ResourceElement.construct(getTable(), REAL_INDEX);
865 return (short)(INDEX + ZERO_SHIFT);
868 void createResource(int resourceIndex) {
869 final int tableCount = getTableCount();
870 if (resourceIndex <= tableCount) { // old index
871 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
872 if (ResourceElement.isEmpty(getTable(), realIndex))
874 } if (resourceIndex == tableCount+1) {
878 throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);
881 // void deleteResource(int resourceIndex) {
882 // int realIndex = checkIndexAndGetRealIndex(resourceIndex);
883 // ResourceElement.destruct(getTable(), realIndex);
884 // decResourceCount();
887 public int getCompleteObjectRef(int resourceIndex) {
888 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
889 return ResourceElement.getCompleteObjectRef(getTable(), realIndex);
892 public int getPredicateIndex(int resourceIndex) {
893 int i = (resourceIndex<<2) - 3 + offset;
894 return (int)table[i];
897 public void setPredicateIndex(int resourceIndex, int predicateIndex) {
898 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
899 ResourceElement.setPredicateIndex(getTable(), realIndex, predicateIndex);
902 public byte[] getValue(ValueTable valueTable, int resourceIndex)
903 throws DatabaseException {
904 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
905 return ResourceElement.getValue(valueTable, getTable(), realIndex);
909 // int getString(ValueTable valueTable, int resourceIndex, char[] chars)
910 // throws DatabaseException {
911 // //int realIndex = checkIndexAndGetRealIndex(resourceIndex);
912 // return ResourceElement.getString(valueTable, getTable(), 4 * resourceIndex - 3 + offset, chars);
915 public boolean hasValue(int resourceIndex) {
916 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
917 return ResourceElement.hasValue(getTable(), realIndex);
920 // boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {
921 // int realIndex = checkIndexAndGetRealIndex(resourceIndex);
922 // return ResourceElement.hasValue(valueTable, getTable(), realIndex, value);
925 public boolean removeValue(ValueTable valueTable, int resourceIndex) {
926 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
927 boolean ret = ResourceElement.removeValue(valueTable, getTable(), realIndex);
928 // if (ret && !ResourceElement.isUsed(getTable(), realIndex))
929 // decResourceCount();
933 public void setValue(ValueTable valueTable, int resourceIndex, byte[] value, int length) {
934 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
935 ResourceElement.setValue(valueTable, getTable(), realIndex, value, length);
938 public boolean isValueEx(ValueTable valueTable, int resourceIndex) {
939 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
940 return ResourceElement.isValueEx(valueTable, getTable(), realIndex);
943 public void setValueEx(ValueTable valueTable, int resourceIndex) {
944 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
945 ResourceElement.setValueEx(valueTable, getTable(), realIndex);
948 static final int RESOURCE_COUNT_INDEX = 0;
949 static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.
950 static final int CLUSTER_STATUS_INDEX = 2;
952 int incResourceCount() {
953 int count = getExtra(RESOURCE_COUNT_INDEX) + 1;
954 setExtra(RESOURCE_COUNT_INDEX, count);
958 // int decResourceCount() {
959 // int count = getExtra(RESOURCE_COUNT_INDEX) - 1;
960 // setExtra(RESOURCE_COUNT_INDEX, count);
964 public int getResourceCount() {
965 return getExtra(RESOURCE_COUNT_INDEX);
967 public int getClusterStatus() {
968 return getExtra(CLUSTER_STATUS_INDEX);
970 public void setClusterStatus(int value) {
971 setExtra(CLUSTER_STATUS_INDEX, value);
975 final int tsize = getTableSize();
976 final int esize = ResourceElement.getSizeOf();
977 long[] table = getTable();
978 for (int i = getTableBase(); i < getTableBase() + tsize; i += esize) {
979 if (ResourceElement.isUsed(getTable(), i)) {
980 System.out.println(" -" + Long.toHexString(table[i]) + " " + Long.toHexString(table[i+1]) + " " + Long.toHexString(table[i+2]) + " " + Long.toHexString(table[i+3]));
986 public <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,
987 ClusterSupport support, Modifier modifier) throws DatabaseException {
988 final int tsize = getTableSize();
989 // final int rsize = getResourceCount();
990 final int esize = ResourceElement.getSizeOf();
992 int key = ZERO_SHIFT;
993 for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {
994 if (ResourceElement.isUsed(getTable(), i)) {
996 if (null == modifier)
999 ref = modifier.execute(key);
1000 if (procedure.execute(context, ref))
1001 return true; // loop was broken by procedure
1002 // if (rsize == ++count)
1003 // return false; // loop finished
1006 //assert(rsize == count);
1007 return false; // loop finished
1010 public <Context> boolean foreachPredicate(int resourceIndex
1011 , ClusterI.PredicateProcedure<Context> procedure, Context context
1012 , ClusterSupport support, Modifier modifier, CompleteTable ct)
1013 throws DatabaseException {
1014 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
1015 return ResourceElement.foreachPredicate(getTable(), realIndex
1016 , procedure, context, support, modifier, ct);
1019 public int getSingleObject(int resourceIndex, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {
1020 // return ResourceElement.getSingleObject(table, realIndex, support, pRef, pCompleteType, ct, modifier);
1021 return ResourceElement.getSingleObject(table, 4 * resourceIndex - 3 + offset, support, pRef, pCompleteType, ct, modifier);
1024 public void foreachObject(int resourceIndex, ReadGraphImpl graph,
1025 SyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {
1026 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
1027 ResourceElement.foreachObject(table, realIndex, graph, procedure, support,
1028 pRef, pCompleteType, ct, modifier);
1031 public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,
1032 SyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct, Modifier modifier) throws DatabaseException {
1033 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
1034 ResourceElement.foreachObject(table, realIndex, graph, context, procedure, support,
1035 pRef, pCompleteType, ct, modifier);
1038 public <Context> boolean foreachObject(int resourceIndex
1039 , ClusterI.ObjectProcedure<Context> procedure, Context context
1040 , ClusterSupport support, Modifier modifier,
1041 int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
1042 throws DatabaseException {
1043 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
1044 return ResourceElement.foreachObject(table, realIndex
1045 , procedure, context, support, modifier
1046 , pRef, completeType, ct);
1048 public int addStatement(int resourceIndex, int pRef, int oRef, PredicateTable pt, ObjectTable ot
1049 , ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)
1050 throws DatabaseException {
1051 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
1052 return ResourceElement.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, pCompleteType, ct);
1055 public boolean removeStatementFromCache(int resourceIndex, int pRef, int oRef,
1056 ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct)
1057 throws DatabaseException {
1058 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
1059 boolean ret = ResourceElement.removeStatement(getTable(), realIndex, pRef, oRef, pCompleteType, ct);
1060 // if (ret && !ResourceElement.isUsed(getTable(), realIndex))
1061 // decResourceCount();
1065 public void removeStatement(int resourceIndex, int pRef, int oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,
1066 PredicateTable pt, ObjectTable ot, ClusterBase cluster, ClusterSupport support)
1067 throws DatabaseException {
1068 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
1069 boolean removed = ResourceElement.removeStatement(getTable(), realIndex,
1070 pRef, oRef, pCompleteType, ct);
1073 int predicateIndex = ResourceElement.getPredicateIndex(getTable(), realIndex);
1074 if (0 == predicateIndex) {
1075 // if (!ResourceElement.isUsed(getTable(), realIndex))
1076 // decResourceCount();
1079 GetStatements gs = new GetStatements(ot);
1080 pt.foreachPredicate(predicateIndex, gs, null, null, null);
1081 ArrayList<Statement> stms = gs.getStatements();
1083 final int SIZE = stms.size();
1085 for (int i = 0; i < SIZE; ++i) {
1086 Statement stm = stms.get(i);
1087 PredicateTable.Status ret = pt.removePredicate(predicateIndex,
1088 stm.pRef, stm.oIndex, ot);
1089 if (ret == Status.NothingRemoved)
1090 throw new DatabaseException("Internal error during statement cache fix (2).");
1091 int predicateKey = cluster.makeResourceKey(stm.pRef);
1092 int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);
1093 ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt);
1094 int pi = ResourceElement.addStatement(getTable(), realIndex, stm.pRef, stm.oIndex,
1095 pt, ot, completeType, ct);
1098 assert(0 == pt.getPredicateSetSize(predicateIndex));
1099 ResourceElement.setPredicateIndex(getTable(), realIndex, 0);
1101 for (int i = 0; i < SIZE; ++i) {
1102 Statement stm = stms.get(i);
1103 int predicateKey = cluster.makeResourceKey(stm.pRef);
1104 int completeTypeInt = ClusterTraitsBase.getCompleteTypeIntFromResourceKey(predicateKey);
1105 ClusterI.CompleteTypeEnum completeType = CompleteTypeEnum.make(completeTypeInt);
1106 int pIndex = ResourceElement.addStatement(getTable(), realIndex,
1107 stm.pRef, stm.oIndex, pt, ot, completeType, ct);
1109 return; // cache fixed and full, p and o sets in use
1111 throw new DatabaseException("Internal error during statement cache fix (3).");
1113 // if (!ResourceElement.isUsed(getTable(), realIndex))
1114 // decResourceCount();
1118 private int checkIndexAndGetRealIndex(final int INDEX) {
1120 assert(INDEX <= getTableCount());
1121 // final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT;
1122 // final int TABLE_INDEX = (INDEX - ZERO_SHIFT) * ResourceElement.getSizeOf() + ZERO_SHIFT;
1123 // return checkIndexAndGetRealIndex(TABLE_INDEX, ResourceElement.getSizeOf());
1124 return 4 * INDEX - 3 + offset;
1126 public void check(ClusterBase cluster)
1127 throws DatabaseException {
1129 cluster.checkValueInit();
1130 long[] table = getTable();
1131 int ps = getHeader().getOffset() + ZERO_SHIFT;
1132 final int TABLE_SIZE = getTableSize();
1133 int pe = ps + TABLE_SIZE;
1134 for (int p=ps; p<pe; p+=ResourceElement.getSizeOf()) {
1135 if (!ResourceElement.isUsed(table, p))
1137 int cr = ResourceElement.getCompleteObjectRef(table, p);
1139 if (ClusterTraits.completeReferenceIsMultiple(cr))
1140 cluster.checkCompleteSetReference(cr);
1142 int fi = ClusterTraits.completeReferenceGetForeignIndex(cr);
1143 int ri = ClusterTraits.completeReferenceGetResourceIndex(cr);
1145 cluster.checkForeingIndex(fi);
1146 else if (ri < 1 || ri > TABLE_SIZE)
1147 throw new ValidationException("Illegal resource index=" + ri);
1150 int pi = ResourceElement.getPredicateIndex(table, p);
1152 cluster.checkPredicateIndex(pi);
1154 ResourceElement.ValueData vd = new ResourceElement.ValueData();
1155 ResourceElement.getValueCapacityAndIndex(vd, table, p);
1156 cluster.checkValue(vd.capacity, vd.index);
1158 cluster.checkValueFini();
1162 public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
1163 ClusterSupport support, Modifier modifier) throws DatabaseException {
1164 throw new UnsupportedOperationException();
1169 Statement(int pRef, int oIndex) {
1171 this.oIndex = oIndex;
1177 class CalculateStatements
1178 implements ClusterI.PredicateProcedure<CalculateStatements> {
1179 private ObjectTable ot;
1180 private final int sRef;
1182 CalculateStatements(int sRef, ObjectTable ot) {
1188 public boolean execute(final CalculateStatements context
1189 , final int pKey, int oIndex) {
1190 if (ClusterTraits.statementIndexIsDirect(oIndex))
1191 return false; // osize = 1
1193 oIndex = ClusterTraits.statementIndexGet(oIndex);
1194 } catch (DatabaseException e) {
1195 Logger.getDefault().logError("Missing object set for s="
1196 + sRef + " p=" + pKey, null);
1197 return false; // continue looping
1199 int osize = ot.getObjectSetSize(oIndex);
1200 if (osize == 3 || osize > 9)
1201 System.out.println("Resource " + sRef + " predicate " + pKey + " has "
1202 + osize + " objects.");
1203 return true; // break loop
1207 class GetStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {
1208 private ObjectTable ot;
1209 private final ArrayList<Statement> stms = new ArrayList<Statement>();
1210 GetStatements(ObjectTable ot) {
1213 ArrayList<Statement> getStatements() {
1217 public boolean execute(Object context, int pRef, int oIndex) {
1219 ot.foreachObject(oIndex, this, pRef, null, null);
1220 } catch (DatabaseException e) {
1221 e.printStackTrace();
1222 return false; // continue looping
1224 if (stms.size() > 2)
1225 return true; // break loop
1226 return false; // continue looping
1230 public boolean execute(Integer pRef, int oRef) {
1231 stms.add(new Statement(pRef, oRef));
1232 if (stms.size() > 2)
1233 return true; // break loop
1234 return false; // continue looping