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