package fi.vtt.simantics.procore.internal; import org.simantics.db.Resource; import org.simantics.db.WriteOnlyGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.RuntimeDatabaseException; import org.simantics.db.impl.ClusterSupport; import org.simantics.db.impl.ClusterTraitsBase; import org.simantics.db.impl.ResourceImpl; import org.simantics.db.impl.graph.WriteGraphImpl; import org.simantics.db.procore.cluster.ClusterImpl; import org.simantics.db.service.ClusterBuilder2; import org.simantics.db.service.SerialisationSupport; import fi.vtt.simantics.procore.internal.SessionImplSocket.WriteOnlySupport; public class ClusterBuilderImpl2 implements ClusterBuilder2 { final private ClusterSupport cs; final private SerialisationSupport ss; final private ClusterStream stream; final private WriteOnlySupport support; final private ClusterImpl[] clusterArray; private boolean allowImmutables; ClusterBuilderImpl2(SessionImplSocket session, boolean allowImmutables) { WriteState state = session.writeState; if(state != null) { WriteGraphImpl graph = state.getGraph(); support = (WriteOnlySupport)graph.writeSupport; stream = support.stream; } else { support = null; stream = null; } this.ss = session.getService(SerialisationSupport.class); this.clusterArray = session.clusterTable.getClusterArray(); this.cs = session.getService(ClusterSupport.class); this.allowImmutables = allowImmutables; } ClusterBuilderImpl2(SessionImplSocket session) { this(session, false); } @Override public void newCluster() throws DatabaseException { support.flushCluster(); } @Override public void selectCluster(long cluster) throws DatabaseException { support.selectCluster(cluster); } @Override public void newCluster(int setHandle) throws DatabaseException { support.setDefaultClusterSet(resource(setHandle)); support.flushCluster(); } @Override public void createClusterSet(int resource) throws DatabaseException { support.createClusterSet(null, resource(resource)); } @Override public int newResource() throws DatabaseException { Resource result = support.createResource(null); return handle(result); } @Override public int newResource(int set) throws DatabaseException { Resource result = support.createResource(null, resource(set)); return ss.getTransientId(result); } @Override public int resource(Resource res) throws DatabaseException { ResourceImpl r = (ResourceImpl)res; int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(r.id); ClusterImpl cluster = clusterArray[clusterKey]; if(cluster.cc == null) cluster.cc = new ClusterChange(stream, cluster); return r.id; } @Override public void addStatement(WriteOnlyGraph graph, int subject, int predicate, int object) throws DatabaseException { int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(subject); ClusterImpl cluster = clusterArray[clusterKey]; if(!cluster.isLoaded()) cluster = (ClusterImpl)cs.getClusterByResourceKey(subject); if(cluster.isWriteOnly()) addStatement(cluster, subject, predicate, object); else { WriteGraphImpl impl = (WriteGraphImpl)graph; if(!cluster.getImmutable() || allowImmutables) impl.writeSupport.claim(graph.getProvider(), subject, predicate, object); } } private void addStatement(ClusterImpl cluster, int resourceKey, int predicate, int object) { if(cluster.getImmutable()) return; Change change = cluster.change; change.addStatementIndex0(resourceKey, ClusterChange.ADD_OPERATION); applyPredicate(cluster, predicate); applyObject(cluster, object); cluster.cc.addChange(change); } public void applyPredicate(ClusterImpl impl, int predicate) { int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(predicate); ClusterImpl cluster = clusterArray[clusterKey]; impl.change.addStatementIndex1(predicate, cluster.clusterUID, (byte)0, impl.foreignLookup); } public void applyObject(ClusterImpl impl, int object) { int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(object); ClusterImpl cluster = clusterArray[clusterKey]; impl.change.addStatementIndex2(object, cluster.clusterUID, (byte)0, impl.foreignLookup); } @Override public Resource resource(int key) { try { return ss.getResource(key); } catch (DatabaseException e) { throw new RuntimeDatabaseException(e); } } @Override public int handle(Resource r) { return ((ResourceImpl)r).id; } byte[] buffer = new byte[65536]; int bufferOffset = 0; int valueSubject = 0; int valueOffset = 0; @Override public void beginValue(int subject) { valueSubject = subject; bufferOffset = 0; valueOffset = 0; } @Override public void appendValue(int byteValue) throws DatabaseException { buffer[bufferOffset++] = (byte)byteValue; if(bufferOffset == 65536) { int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(valueSubject); ClusterImpl cluster = clusterArray[clusterKey]; cluster.modiValueEx(valueSubject, valueOffset, 65536, buffer, 0, cs); bufferOffset = 0; valueOffset += 65536; } } @Override public void endValue() throws DatabaseException { if(bufferOffset > 0) { int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(valueSubject); ClusterImpl cluster = clusterArray[clusterKey]; if(valueOffset == 0) { if(cluster.isWriteOnly()) cluster.cc.setValue((short)(valueSubject & 0xFFF), buffer, bufferOffset); else { support.claimValue(null, valueSubject, buffer, bufferOffset); } } else { cluster.modiValueEx(valueSubject, valueOffset, bufferOffset, buffer, 0, cs); } } } }