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.exception.DatabaseException;
18 import org.simantics.db.impl.ClusterBase;
19 import org.simantics.db.impl.ClusterI;
20 import org.simantics.db.impl.ClusterI.ObjectProcedure;
21 import org.simantics.db.impl.ClusterI.PredicateProcedure;
22 import org.simantics.db.impl.ClusterI.Procedure;
23 import org.simantics.db.impl.ClusterSupport;
24 import org.simantics.db.impl.ClusterTraitsBase;
25 import org.simantics.db.impl.Modifier;
26 import org.simantics.db.impl.Table;
27 import org.simantics.db.impl.TableFactory;
28 import org.simantics.db.impl.TableSizeListener;
29 import org.simantics.db.impl.graph.ReadGraphImpl;
30 import org.simantics.db.procedure.SyncContextMultiProcedure;
31 import org.simantics.db.procedure.SyncMultiProcedure;
32 import org.simantics.db.procore.cluster.PredicateTable.Status;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
38 public final class ResourceTableSmall extends Table<long[]> {
39 public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {
40 super(TableFactory.getLongFactory(), sizeListener, header, headerBase);
43 public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {
44 super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);
47 public int getUsedSize() {
48 return getTableCount();
51 public short createResource() {
52 final int INDEX = getTableCount();
53 final int SIZE = ResourceElementSmall.getSizeOf();
54 int resourceIndex = createNewElement(SIZE);
55 assert (0 != resourceIndex);
56 final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);
57 ResourceElementSmall.construct(getTable(), REAL_INDEX);
59 return (short)(INDEX + ZERO_SHIFT);
62 void createResource(int resourceIndex) {
63 final int tableCount = getTableCount();
64 if (resourceIndex <= tableCount) { // old index
65 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
66 if (ResourceElementSmall.isEmpty(getTable(), realIndex))
68 } if (resourceIndex == tableCount+1) {
72 throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);
75 public short getCompleteObjectRef(int resourceIndex) {
76 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
77 return ResourceElementSmall.getCompleteObjectRef(getTable(), realIndex);
80 public ClusterI.CompleteTypeEnum getCompleteType(int resourceIndex) {
81 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
82 return ResourceElementSmall.getCompleteType(getTable(), realIndex);
85 public int getPredicateIndex(int resourceIndex) {
86 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
87 return ResourceElementSmall.getPredicateIndex(table, realIndex);
90 public void setPredicateIndex(int resourceIndex, int predicateIndex) {
91 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
92 ResourceElementSmall.setPredicateIndex(getTable(), realIndex, predicateIndex);
95 public byte[] getValue(ValueTableSmall valueTable, int resourceIndex)
96 throws DatabaseException {
97 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
98 return ResourceElementSmall.getValue(valueTable, getTable(), realIndex);
101 // char[] getString(ValueTableSmall valueTable, int resourceIndex) {
102 // int realIndex = checkIndexAndGetRealIndex(resourceIndex);
103 // return ResourceElementSmall.getString(valueTable, getTable(), realIndex);
106 public boolean hasValue(int resourceIndex) {
107 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
108 return ResourceElementSmall.hasValue(getTable(), realIndex);
111 // boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {
112 // int realIndex = checkIndexAndGetRealIndex(resourceIndex);
113 // return ResourceElementSmall.hasValue(valueTable, getTable(), realIndex, value);
116 public boolean removeValue(ValueTableSmall valueTable, int resourceIndex) {
117 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
118 boolean ret = ResourceElementSmall.removeValue(valueTable, getTable(), realIndex);
119 // if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
120 // decResourceCount();
124 public void setValue(ValueTableSmall valueTable, int resourceIndex, byte[] value, int length)
125 throws OutOfSpaceException {
126 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
127 ResourceElementSmall.setValue(valueTable, getTable(), realIndex, value, length);
130 public boolean isValueEx(ValueTableSmall valueTable, int resourceIndex) {
131 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
132 return ResourceElementSmall.isValueEx(valueTable, getTable(), realIndex);
135 public void setValueEx(ValueTableSmall valueTable, int resourceIndex) {
136 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
137 ResourceElementSmall.setValueEx(valueTable, getTable(), realIndex);
140 static final int RESOURCE_COUNT_INDEX = 0;
141 static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.
142 static final int CLUSTER_STATUS_INDEX = 2;
144 int incResourceCount() {
145 int count = getExtra(RESOURCE_COUNT_INDEX) + 1;
146 setExtra(RESOURCE_COUNT_INDEX, count);
150 // int decResourceCount() {
151 // int count = getExtra(RESOURCE_COUNT_INDEX) - 1;
152 // setExtra(RESOURCE_COUNT_INDEX, count);
156 public int getResourceCount() {
157 return getExtra(RESOURCE_COUNT_INDEX);
159 public int getClusterStatus() {
160 return getExtra(CLUSTER_STATUS_INDEX);
162 public void setClusterStatus(int value) {
163 setExtra(CLUSTER_STATUS_INDEX, value);
166 <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,
167 ClusterSupport support, Modifier modifier) throws DatabaseException {
168 final int tsize = getTableSize();
169 // final int rsize = getResourceCount();
170 final int esize = ResourceElementSmall.getSizeOf();
172 int key = ZERO_SHIFT;
173 for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {
174 if (ResourceElementSmall.isUsed(getTable(), i)) {
176 if (null == modifier)
179 ref = modifier.execute(key);
180 if (procedure.execute(context, ref))
181 return true; // loop was broken by procedure
182 // if (rsize == ++count)
183 // return false; // loop finished
186 //assert(rsize == count);
187 return false; // loop finished
190 public <Context> boolean foreachPredicate(int resourceIndex
191 , ClusterI.PredicateProcedure<Context> procedure, Context context
192 , ClusterSupport support, Modifier modifier, CompleteTable ct)
193 throws DatabaseException {
194 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
195 return ResourceElementSmall.foreachPredicate(getTable(), realIndex
196 , procedure, context, support, modifier, ct);
199 public int getSingleObject(int resourceIndex, ClusterSupport support, short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
200 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
201 return ResourceElementSmall.getSingleObject(table, realIndex, support, pRef, completeType, ct, modifier);
204 public void foreachObject(int resourceIndex, ReadGraphImpl graph,
205 SyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
206 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
207 ResourceElementSmall.foreachObject(table, realIndex, graph, procedure, support,
208 pRef, completeType, ct, modifier);
211 public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,
212 SyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
213 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
214 ResourceElementSmall.foreachObject(table, realIndex, graph, context, procedure, support,
215 pRef, completeType, ct, modifier);
218 public <Context> boolean foreachObject(int resourceIndex
219 , ClusterI.ObjectProcedure<Context> procedure, Context context
220 , ClusterSupport support, Modifier modifier,
221 short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
222 throws DatabaseException {
223 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
224 return ResourceElementSmall.foreachObject(table, realIndex
225 , procedure, context, support, modifier
226 , pRef, completeType, ct);
228 public int addStatement(int resourceIndex, short pRef, short oRef, PredicateTable pt, ObjectTable ot
229 , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
230 throws DatabaseException {
231 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
232 return ResourceElementSmall.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, completeType, ct);
235 public boolean removeStatementFromCache(int resourceIndex, short pRef, short oRef,
236 ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
237 throws DatabaseException {
238 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
239 boolean ret = ResourceElementSmall.removeStatement(getTable(), realIndex, pRef, oRef, completeType, ct);
240 // if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
241 // decResourceCount();
245 public void removeStatement(int resourceIndex, short pRef, short oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,
246 PredicateTable pt, ObjectTable ot, ClusterSupport support)
247 throws DatabaseException {
248 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
249 boolean removed = ResourceElementSmall.removeStatement(getTable(), realIndex,
250 pRef, oRef, pCompleteType, ct);
253 int predicateIndex = ResourceElementSmall.getPredicateIndex(getTable(), realIndex);
254 if (0 == predicateIndex) {
255 // if (!ResourceElementSmall.isUsed(getTable(), realIndex))
256 // decResourceCount();
258 } else if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
259 return; // Complete type statements are not kept in statement cache.
260 // We have one more statements in predicate table.
261 // Here we check if statement cache needs fixing.
262 GetStatementsSmall gs = new GetStatementsSmall(ot);
263 pt.foreachPredicate(predicateIndex, gs, null, null, null);
264 ArrayList<Statement> stms = gs.getStatements();
266 final int SIZE = stms.size();
268 for (int i = 0; i < SIZE; ++i) {
269 Statement stm = stms.get(i);
270 PredicateTable.Status ret = pt.removePredicate(predicateIndex,
271 stm.pRef, stm.oIndex, ot);
272 if (ret == Status.NothingRemoved)
273 throw new DatabaseException("Internal error during statement cache fix (2).");
274 assert(stm.pRef < (1<<16));
275 assert(stm.oIndex < 1<<16);
276 int pi = ResourceElementSmall.addStatement(getTable(), realIndex, (short)stm.pRef, (short)stm.oIndex,
277 pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
280 assert(0 == pt.getPredicateSetSize(predicateIndex));
281 ResourceElementSmall.setPredicateIndex(getTable(), realIndex, 0);
283 for (int i = 0; i < SIZE; ++i) {
284 Statement stm = stms.get(i);
285 assert(stm.pRef < (1<<16));
286 assert(stm.oIndex < 1<<16);
287 int pIndex = ResourceElementSmall.addStatement(getTable(), realIndex,
288 (short)stm.pRef, (short)stm.oIndex, pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
290 return; // cache fixed and full, p and o sets in use
292 throw new DatabaseException("Internal error during statement cache fix (3).");
294 // if (!ResourceElementSmall.isUsed(getTable(), realIndex))
295 // decResourceCount();
298 private int checkIndexAndGetRealIndex(final int resourceIndex) {
299 if (ClusterTraitsBase.isIllegalResourceIndex(resourceIndex))
300 throw new RuntimeException("Illegal resource index. index=" + resourceIndex + ".");
301 if(resourceIndex > getTableCount())
302 throw new RuntimeException("Illegal resource index. index=" + resourceIndex + " table count=" + getTableCount());
303 final int SIZE = ResourceElementSmall.getSizeOf();
304 final int REAL_INDEX = resourceIndex * SIZE - (SIZE - ZERO_SHIFT) + offset;
307 void check(ClusterImpl cluster)
308 throws DatabaseException {
309 // throw new Error("Not implemented.//KRAA:");
312 public void toBig(ClusterBase big, final ClusterSupport support, final ClusterBase small)
313 throws DatabaseException {
314 int resourceIndex = 1;
315 long[] table = getTable();
316 int ps = getHeader().getOffset() + ZERO_SHIFT;
317 final int TABLE_SIZE = getTableSize();
318 int pe = ps + TABLE_SIZE;
319 for (int p=ps; p<pe; p+=ResourceElementSmall.getSizeOf(), ++resourceIndex) {
320 big.createResource(support);
321 int subjectKey = ClusterTraits.createResourceKey(small.clusterKey, resourceIndex);
322 if (!ResourceElementSmall.isUsed(table, p))
324 int cr = ResourceElementSmall.getCompleteObjectRef(table, p);
326 ClusterI.CompleteTypeEnum ct = ResourceElementSmall.getCompleteType(table, p);
327 if (ClusterI.CompleteTypeEnum.NotComplete != ct) {
328 int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
329 int oKey = small.getCompleteObjectKey(subjectKey, support);
330 big.addRelation(subjectKey, pKey, oKey, support);
332 final class ForeachObject<Context>
333 implements ClusterI.ObjectProcedure<Context> {
336 public ForeachObject(int sKey, ClusterBase big) {
341 public boolean execute(Context context, int completeRef)
342 throws DatabaseException {
343 ClusterI.CompleteTypeEnum ct = ClusterTraitsSmall.completeRefAndTypeGetType(completeRef);
344 int p = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
345 int o = small.execute(completeRef & 0xFFFF);
346 big.addRelation(sKey, p, o, support);
347 return false; // Continue looping.
350 ForeachObject<Object> op = new ForeachObject<Object>(subjectKey, big);
351 small.getCompleteTable().foreach(cr & 0xFFFF, op, null, support, null);
354 int pi = ResourceElementSmall.getPredicateIndex(table, p);
356 ToBigStatements tbs = new ToBigStatements(small, big, support, subjectKey);
357 small.getPredicateTable().foreach(pi, tbs, null, null, null);
359 int p1 = ResourceElementSmall.getStm1Predicate(table, p);
360 int o1 = ResourceElementSmall.getStm1Object(table, p);
362 int pk1 = small.execute(p1);
363 int ok1 = small.execute(o1);
364 big.addRelation(subjectKey, pk1, ok1, support);
365 int p2 = ResourceElementSmall.getStm2Predicate(table, p);
366 int o2 = ResourceElementSmall.getStm2Object(table, p);
368 int pk2 = small.execute(p2);
369 int ok2 = small.execute(o2);
370 big.addRelation(subjectKey, pk2, ok2, support);
374 int valueIndex = ResourceElementSmall.getValueIndex(table, p);
375 if (ClusterTraitsSmall.VALUE_INDEX_EX == valueIndex)
376 big.setValueEx(subjectKey);
378 byte[] value = ResourceElementSmall.getValue((ValueTableSmall)small.getValueTable(), table, p);
380 big.setValue(subjectKey, value, value.length, support);
386 public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
387 ClusterSupport support, Modifier modifier) throws DatabaseException {
388 throw new UnsupportedOperationException();
392 class CalculateStatementsSmall
393 implements ClusterI.PredicateProcedure<CalculateStatements> {
395 private static final Logger LOGGER = LoggerFactory.getLogger(CalculateStatementsSmall.class);
397 private ObjectTable ot;
398 private final int sRef;
400 CalculateStatementsSmall(int sRef, ObjectTable ot) {
406 public boolean execute(CalculateStatements context
407 , final int pKey, int oIndex) {
408 if (ClusterTraits.statementIndexIsDirect(oIndex))
409 return false; // osize = 1
411 oIndex = ClusterTraits.statementIndexGet(oIndex);
412 } catch (DatabaseException e) {
413 LOGGER.error("Missing object set for s="
414 + sRef + " p=" + pKey, e);
415 return false; // continue looping
417 int osize = ot.getObjectSetSize(oIndex);
418 if (osize == 3 || osize > 9)
419 System.out.println("Resource " + sRef + " predicate " + pKey + " has "
420 + osize + " objects.");
421 return true; // break loop
425 class GetStatementsSmall implements ClusterI.PredicateProcedure<Object>, ClusterI.ObjectProcedure<Integer> {
426 private ObjectTable ot;
427 private final ArrayList<Statement> stms = new ArrayList<Statement>();
428 GetStatementsSmall(ObjectTable ot) {
431 ArrayList<Statement> getStatements() {
435 public boolean execute(Object context, int pRef, int oIndex) {
437 ot.foreachObject(oIndex, this, pRef, null, null);
438 } catch (DatabaseException e) {
440 return false; // continue looping
443 return true; // break loop
444 return false; // continue looping
448 public boolean execute(Integer pRef, int oRef) {
449 stms.add(new Statement(pRef, oRef));
451 return true; // break loop
452 return false; // continue looping
456 class ToBigStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {
457 private ClusterBase small;
458 private ClusterBase big;
459 private ClusterSupport support;
460 private int subjectKey;
461 ToBigStatements(ClusterBase small, ClusterBase big, ClusterSupport support, int subjectKey) {
464 this.support = support;
465 this.subjectKey = subjectKey;
468 public boolean execute(Object context, int pRef, int oIndex) {
470 small.getObjectTable().foreach(oIndex, this, pRef, null, null);
471 } catch (DatabaseException e) {
473 return false; // continue looping
475 return false; // continue looping
479 public boolean execute(Integer pRef, int oRef)
480 throws DatabaseException {
481 int pKey = small.execute(pRef);
482 int oKey = small.execute(oRef);
483 big.addRelation(subjectKey, pKey, oKey, support);
484 return false; // continue looping