1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.procore.cluster;
\r
14 import java.util.ArrayList;
\r
16 import org.simantics.db.Resource;
\r
17 import org.simantics.db.common.utils.Logger;
\r
18 import org.simantics.db.exception.DatabaseException;
\r
19 import org.simantics.db.impl.ClusterBase;
\r
20 import org.simantics.db.impl.ClusterI;
\r
21 import org.simantics.db.impl.ClusterI.ObjectProcedure;
\r
22 import org.simantics.db.impl.ClusterI.PredicateProcedure;
\r
23 import org.simantics.db.impl.ClusterI.Procedure;
\r
24 import org.simantics.db.impl.ClusterSupport;
\r
25 import org.simantics.db.impl.ClusterTraitsBase;
\r
26 import org.simantics.db.impl.Modifier;
\r
27 import org.simantics.db.impl.Table;
\r
28 import org.simantics.db.impl.TableFactory;
\r
29 import org.simantics.db.impl.TableSizeListener;
\r
30 import org.simantics.db.impl.graph.ReadGraphImpl;
\r
31 import org.simantics.db.procedure.AsyncContextMultiProcedure;
\r
32 import org.simantics.db.procedure.AsyncMultiProcedure;
\r
33 import org.simantics.db.procore.cluster.PredicateTable.Status;
\r
37 public final class ResourceTableSmall extends Table<long[]> {
\r
38 public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {
\r
39 super(TableFactory.getLongFactory(), sizeListener, header, headerBase);
\r
42 public ResourceTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, long[] longs) {
\r
43 super(TableFactory.getLongFactory(), sizeListener, header, headerBase, longs);
\r
46 public int getUsedSize() {
\r
47 return getTableCount();
\r
50 public short createResource() {
\r
51 final int INDEX = getTableCount();
\r
52 final int SIZE = ResourceElementSmall.getSizeOf();
\r
53 int resourceIndex = createNewElement(SIZE);
\r
54 assert (0 != resourceIndex);
\r
55 final int REAL_INDEX = checkIndexAndGetRealIndex(resourceIndex, SIZE);
\r
56 ResourceElementSmall.construct(getTable(), REAL_INDEX);
\r
58 return (short)(INDEX + ZERO_SHIFT);
\r
61 void createResource(int resourceIndex) {
\r
62 final int tableCount = getTableCount();
\r
63 if (resourceIndex <= tableCount) { // old index
\r
64 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
65 if (ResourceElementSmall.isEmpty(getTable(), realIndex))
\r
67 } if (resourceIndex == tableCount+1) {
\r
71 throw new InternalError("Trying to create resource with illegal index=" + resourceIndex);
\r
74 public short getCompleteObjectRef(int resourceIndex) {
\r
75 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
76 return ResourceElementSmall.getCompleteObjectRef(getTable(), realIndex);
\r
79 public ClusterI.CompleteTypeEnum getCompleteType(int resourceIndex) {
\r
80 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
81 return ResourceElementSmall.getCompleteType(getTable(), realIndex);
\r
84 public int getPredicateIndex(int resourceIndex) {
\r
85 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
86 return ResourceElementSmall.getPredicateIndex(table, realIndex);
\r
89 public void setPredicateIndex(int resourceIndex, int predicateIndex) {
\r
90 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
91 ResourceElementSmall.setPredicateIndex(getTable(), realIndex, predicateIndex);
\r
94 public byte[] getValue(ValueTableSmall valueTable, int resourceIndex)
\r
95 throws DatabaseException {
\r
96 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
97 return ResourceElementSmall.getValue(valueTable, getTable(), realIndex);
\r
100 // char[] getString(ValueTableSmall valueTable, int resourceIndex) {
\r
101 // int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
102 // return ResourceElementSmall.getString(valueTable, getTable(), realIndex);
\r
105 public boolean hasValue(int resourceIndex) {
\r
106 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
107 return ResourceElementSmall.hasValue(getTable(), realIndex);
\r
110 // boolean hasValue(ValueTable valueTable, int resourceIndex, byte[] value) {
\r
111 // int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
112 // return ResourceElementSmall.hasValue(valueTable, getTable(), realIndex, value);
\r
115 public boolean removeValue(ValueTableSmall valueTable, int resourceIndex) {
\r
116 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
117 boolean ret = ResourceElementSmall.removeValue(valueTable, getTable(), realIndex);
\r
118 // if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
\r
119 // decResourceCount();
\r
123 public void setValue(ValueTableSmall valueTable, int resourceIndex, byte[] value, int length)
\r
124 throws OutOfSpaceException {
\r
125 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
126 ResourceElementSmall.setValue(valueTable, getTable(), realIndex, value, length);
\r
129 public boolean isValueEx(ValueTableSmall valueTable, int resourceIndex) {
\r
130 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
131 return ResourceElementSmall.isValueEx(valueTable, getTable(), realIndex);
\r
134 public void setValueEx(ValueTableSmall valueTable, int resourceIndex) {
\r
135 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
136 ResourceElementSmall.setValueEx(valueTable, getTable(), realIndex);
\r
139 static final int RESOURCE_COUNT_INDEX = 0;
\r
140 static final int FOREIGN_COUNT_INDEX = 1; // Reserved by server.
\r
141 static final int CLUSTER_STATUS_INDEX = 2;
\r
143 int incResourceCount() {
\r
144 int count = getExtra(RESOURCE_COUNT_INDEX) + 1;
\r
145 setExtra(RESOURCE_COUNT_INDEX, count);
\r
149 // int decResourceCount() {
\r
150 // int count = getExtra(RESOURCE_COUNT_INDEX) - 1;
\r
151 // setExtra(RESOURCE_COUNT_INDEX, count);
\r
155 public int getResourceCount() {
\r
156 return getExtra(RESOURCE_COUNT_INDEX);
\r
158 public int getClusterStatus() {
\r
159 return getExtra(CLUSTER_STATUS_INDEX);
\r
161 public void setClusterStatus(int value) {
\r
162 setExtra(CLUSTER_STATUS_INDEX, value);
\r
165 <Context> boolean foreachResource(ClusterI.ObjectProcedure<Context> procedure, Context context,
\r
166 ClusterSupport support, Modifier modifier) throws DatabaseException {
\r
167 final int tsize = getTableSize();
\r
168 // final int rsize = getResourceCount();
\r
169 final int esize = ResourceElementSmall.getSizeOf();
\r
171 int key = ZERO_SHIFT;
\r
172 for (int i = getTableBase(); i < getTableBase() + tsize; i += esize, ++key) {
\r
173 if (ResourceElementSmall.isUsed(getTable(), i)) {
\r
175 if (null == modifier)
\r
178 ref = modifier.execute(key);
\r
179 if (procedure.execute(context, ref))
\r
180 return true; // loop was broken by procedure
\r
181 // if (rsize == ++count)
\r
182 // return false; // loop finished
\r
185 //assert(rsize == count);
\r
186 return false; // loop finished
\r
189 public <Context> boolean foreachPredicate(int resourceIndex
\r
190 , ClusterI.PredicateProcedure<Context> procedure, Context context
\r
191 , ClusterSupport support, Modifier modifier, CompleteTable ct)
\r
192 throws DatabaseException {
\r
193 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
194 return ResourceElementSmall.foreachPredicate(getTable(), realIndex
\r
195 , procedure, context, support, modifier, ct);
\r
198 public int getSingleObject(int resourceIndex, ClusterSupport support, short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
\r
199 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
200 return ResourceElementSmall.getSingleObject(table, realIndex, support, pRef, completeType, ct, modifier);
\r
203 public void foreachObject(int resourceIndex, ReadGraphImpl graph,
\r
204 AsyncMultiProcedure<Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
\r
205 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
206 ResourceElementSmall.foreachObject(table, realIndex, graph, procedure, support,
\r
207 pRef, completeType, ct, modifier);
\r
210 public <C> void foreachObject(int resourceIndex, ReadGraphImpl graph, C context,
\r
211 AsyncContextMultiProcedure<C, Resource> procedure, ClusterSupport support, int pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct, Modifier modifier) throws DatabaseException {
\r
212 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
213 ResourceElementSmall.foreachObject(table, realIndex, graph, context, procedure, support,
\r
214 pRef, completeType, ct, modifier);
\r
217 public <Context> boolean foreachObject(int resourceIndex
\r
218 , ClusterI.ObjectProcedure<Context> procedure, Context context
\r
219 , ClusterSupport support, Modifier modifier,
\r
220 short pRef, ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
\r
221 throws DatabaseException {
\r
222 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
223 return ResourceElementSmall.foreachObject(table, realIndex
\r
224 , procedure, context, support, modifier
\r
225 , pRef, completeType, ct);
\r
227 public int addStatement(int resourceIndex, short pRef, short oRef, PredicateTable pt, ObjectTable ot
\r
228 , ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
\r
229 throws DatabaseException {
\r
230 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
231 return ResourceElementSmall.addStatement(getTable(), realIndex, pRef, oRef, pt, ot, completeType, ct);
\r
234 public boolean removeStatementFromCache(int resourceIndex, short pRef, short oRef,
\r
235 ClusterI.CompleteTypeEnum completeType, CompleteTable ct)
\r
236 throws DatabaseException {
\r
237 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
238 boolean ret = ResourceElementSmall.removeStatement(getTable(), realIndex, pRef, oRef, completeType, ct);
\r
239 // if (ret && !ResourceElementSmall.isUsed(getTable(), realIndex))
\r
240 // decResourceCount();
\r
244 public void removeStatement(int resourceIndex, short pRef, short oRef, ClusterI.CompleteTypeEnum pCompleteType, CompleteTable ct,
\r
245 PredicateTable pt, ObjectTable ot, ClusterSupport support)
\r
246 throws DatabaseException {
\r
247 int realIndex = checkIndexAndGetRealIndex(resourceIndex);
\r
248 boolean removed = ResourceElementSmall.removeStatement(getTable(), realIndex,
\r
249 pRef, oRef, pCompleteType, ct);
\r
252 int predicateIndex = ResourceElementSmall.getPredicateIndex(getTable(), realIndex);
\r
253 if (0 == predicateIndex) {
\r
254 // if (!ResourceElementSmall.isUsed(getTable(), realIndex))
\r
255 // decResourceCount();
\r
257 } else if (ClusterI.CompleteTypeEnum.NotComplete != pCompleteType)
\r
258 return; // Complete type statements are not kept in statement cache.
\r
259 // We have one more statements in predicate table.
\r
260 // Here we check if statement cache needs fixing.
\r
261 GetStatementsSmall gs = new GetStatementsSmall(ot);
\r
262 pt.foreachPredicate(predicateIndex, gs, null, null, null);
\r
263 ArrayList<Statement> stms = gs.getStatements();
\r
265 final int SIZE = stms.size();
\r
267 for (int i = 0; i < SIZE; ++i) {
\r
268 Statement stm = stms.get(i);
\r
269 PredicateTable.Status ret = pt.removePredicate(predicateIndex,
\r
270 stm.pRef, stm.oIndex, ot);
\r
271 if (ret == Status.NothingRemoved)
\r
272 throw new DatabaseException("Internal error during statement cache fix (2).");
\r
273 assert(stm.pRef < (1<<16));
\r
274 assert(stm.oIndex < 1<<16);
\r
275 int pi = ResourceElementSmall.addStatement(getTable(), realIndex, (short)stm.pRef, (short)stm.oIndex,
\r
276 pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
\r
279 assert(0 == pt.getPredicateSetSize(predicateIndex));
\r
280 ResourceElementSmall.setPredicateIndex(getTable(), realIndex, 0);
\r
282 for (int i = 0; i < SIZE; ++i) {
\r
283 Statement stm = stms.get(i);
\r
284 assert(stm.pRef < (1<<16));
\r
285 assert(stm.oIndex < 1<<16);
\r
286 int pIndex = ResourceElementSmall.addStatement(getTable(), realIndex,
\r
287 (short)stm.pRef, (short)stm.oIndex, pt, ot, ClusterI.CompleteTypeEnum.NotComplete, ct);
\r
289 return; // cache fixed and full, p and o sets in use
\r
291 throw new DatabaseException("Internal error during statement cache fix (3).");
\r
293 // if (!ResourceElementSmall.isUsed(getTable(), realIndex))
\r
294 // decResourceCount();
\r
297 private int checkIndexAndGetRealIndex(final int resourceIndex) {
\r
298 if (ClusterTraitsBase.isIllegalResourceIndex(resourceIndex))
\r
299 throw new RuntimeException("Illegal resource index. index=" + resourceIndex + ".");
\r
300 if(resourceIndex > getTableCount())
\r
301 throw new RuntimeException("Illegal resource index. index=" + resourceIndex + " table count=" + getTableCount());
\r
302 final int SIZE = ResourceElementSmall.getSizeOf();
\r
303 final int REAL_INDEX = resourceIndex * SIZE - (SIZE - ZERO_SHIFT) + offset;
\r
306 void check(ClusterImpl cluster)
\r
307 throws DatabaseException {
\r
308 // throw new Error("Not implemented.//KRAA:");
\r
311 public void toBig(ClusterBase big, final ClusterSupport support, final ClusterBase small)
\r
312 throws DatabaseException {
\r
313 int resourceIndex = 1;
\r
314 long[] table = getTable();
\r
315 int ps = getHeader().getOffset() + ZERO_SHIFT;
\r
316 final int TABLE_SIZE = getTableSize();
\r
317 int pe = ps + TABLE_SIZE;
\r
318 for (int p=ps; p<pe; p+=ResourceElementSmall.getSizeOf(), ++resourceIndex) {
\r
319 big.createResource(support);
\r
320 int subjectKey = ClusterTraits.createResourceKey(small.clusterKey, resourceIndex);
\r
321 if (!ResourceElementSmall.isUsed(table, p))
\r
323 int cr = ResourceElementSmall.getCompleteObjectRef(table, p);
\r
325 ClusterI.CompleteTypeEnum ct = ResourceElementSmall.getCompleteType(table, p);
\r
326 if (ClusterI.CompleteTypeEnum.NotComplete != ct) {
\r
327 int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
\r
328 int oKey = small.getCompleteObjectKey(subjectKey, support);
\r
329 big.addRelation(subjectKey, pKey, oKey, support);
\r
331 final class ForeachObject<Context>
\r
332 implements ClusterI.ObjectProcedure<Context> {
\r
335 public ForeachObject(int sKey, ClusterBase big) {
\r
340 public boolean execute(Context context, int completeRef)
\r
341 throws DatabaseException {
\r
342 ClusterI.CompleteTypeEnum ct = ClusterTraitsSmall.completeRefAndTypeGetType(completeRef);
\r
343 int p = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(ct);
\r
344 int o = small.execute(completeRef & 0xFFFF);
\r
345 big.addRelation(sKey, p, o, support);
\r
346 return false; // Continue looping.
\r
349 ForeachObject<Object> op = new ForeachObject<Object>(subjectKey, big);
\r
350 small.getCompleteTable().foreach(cr & 0xFFFF, op, null, support, null);
\r
353 int pi = ResourceElementSmall.getPredicateIndex(table, p);
\r
355 ToBigStatements tbs = new ToBigStatements(small, big, support, subjectKey);
\r
356 small.getPredicateTable().foreach(pi, tbs, null, null, null);
\r
358 int p1 = ResourceElementSmall.getStm1Predicate(table, p);
\r
359 int o1 = ResourceElementSmall.getStm1Object(table, p);
\r
361 int pk1 = small.execute(p1);
\r
362 int ok1 = small.execute(o1);
\r
363 big.addRelation(subjectKey, pk1, ok1, support);
\r
364 int p2 = ResourceElementSmall.getStm2Predicate(table, p);
\r
365 int o2 = ResourceElementSmall.getStm2Object(table, p);
\r
367 int pk2 = small.execute(p2);
\r
368 int ok2 = small.execute(o2);
\r
369 big.addRelation(subjectKey, pk2, ok2, support);
\r
373 int valueIndex = ResourceElementSmall.getValueIndex(table, p);
\r
374 if (ClusterTraitsSmall.VALUE_INDEX_EX == valueIndex)
\r
375 big.setValueEx(subjectKey);
\r
377 byte[] value = ResourceElementSmall.getValue((ValueTableSmall)small.getValueTable(), table, p);
\r
379 big.setValue(subjectKey, value, value.length, support);
\r
385 public <Context> boolean foreach(int setIndex, Procedure procedure, Context context,
\r
386 ClusterSupport support, Modifier modifier) throws DatabaseException {
\r
387 throw new UnsupportedOperationException();
\r
391 class CalculateStatementsSmall
\r
392 implements ClusterI.PredicateProcedure<CalculateStatements> {
\r
393 private ObjectTable ot;
\r
394 private final int sRef;
\r
396 CalculateStatementsSmall(int sRef, ObjectTable ot) {
\r
402 public boolean execute(CalculateStatements context
\r
403 , final int pKey, int oIndex) {
\r
404 if (ClusterTraits.statementIndexIsDirect(oIndex))
\r
405 return false; // osize = 1
\r
407 oIndex = ClusterTraits.statementIndexGet(oIndex);
\r
408 } catch (DatabaseException e) {
\r
409 Logger.getDefault().logError("Missing object set for s="
\r
410 + sRef + " p=" + pKey, null);
\r
411 return false; // continue looping
\r
413 int osize = ot.getObjectSetSize(oIndex);
\r
414 if (osize == 3 || osize > 9)
\r
415 System.out.println("Resource " + sRef + " predicate " + pKey + " has "
\r
416 + osize + " objects.");
\r
417 return true; // break loop
\r
421 class GetStatementsSmall implements ClusterI.PredicateProcedure<Object>, ClusterI.ObjectProcedure<Integer> {
\r
422 private ObjectTable ot;
\r
423 private final ArrayList<Statement> stms = new ArrayList<Statement>();
\r
424 GetStatementsSmall(ObjectTable ot) {
\r
427 ArrayList<Statement> getStatements() {
\r
431 public boolean execute(Object context, int pRef, int oIndex) {
\r
433 ot.foreachObject(oIndex, this, pRef, null, null);
\r
434 } catch (DatabaseException e) {
\r
435 e.printStackTrace();
\r
436 return false; // continue looping
\r
438 if (stms.size() > 2)
\r
439 return true; // break loop
\r
440 return false; // continue looping
\r
444 public boolean execute(Integer pRef, int oRef) {
\r
445 stms.add(new Statement(pRef, oRef));
\r
446 if (stms.size() > 2)
\r
447 return true; // break loop
\r
448 return false; // continue looping
\r
452 class ToBigStatements implements PredicateProcedure<Object>, ObjectProcedure<Integer> {
\r
453 private ClusterBase small;
\r
454 private ClusterBase big;
\r
455 private ClusterSupport support;
\r
456 private int subjectKey;
\r
457 ToBigStatements(ClusterBase small, ClusterBase big, ClusterSupport support, int subjectKey) {
\r
458 this.small = small;
\r
460 this.support = support;
\r
461 this.subjectKey = subjectKey;
\r
464 public boolean execute(Object context, int pRef, int oIndex) {
\r
466 small.getObjectTable().foreach(oIndex, this, pRef, null, null);
\r
467 } catch (DatabaseException e) {
\r
468 e.printStackTrace();
\r
469 return false; // continue looping
\r
471 return false; // continue looping
\r
475 public boolean execute(Integer pRef, int oRef)
\r
476 throws DatabaseException {
\r
477 int pKey = small.execute(pRef);
\r
478 int oKey = small.execute(oRef);
\r
479 big.addRelation(subjectKey, pKey, oKey, support);
\r
480 return false; // continue looping
\r