boolean gotMutex = impl.tryAcquireMutex();
boolean done = false;
- // TODO: fix this properly pleease
int count = 0;
+ long startTime = 0;
while (!done) {
if (gotMutex || borrowMutex) {
runWithMutex();
done = true;
} else {
- if (count % 100 == 0)
+ if (count % 10 == 0) {
+ // Taking too long, sleep for a while.
LOGGER.warn("Retry mutex acquire");
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ }
+ }
gotMutex = impl.tryAcquireMutex();
- count++;
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - startTime) > 10) {
+ startTime = currentTime;
+ count++;
+ }
}
}
package org.simantics.db.impl.graph;
-import java.io.DataInput;
-import java.io.DataOutput;
+import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import org.eclipse.core.runtime.Platform;
import org.simantics.databoard.Bindings;
import org.simantics.databoard.accessor.Accessor;
-import org.simantics.databoard.accessor.reference.ChildReference;
import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.error.BindingConstructionException;
-import org.simantics.databoard.binding.impl.BindingPrintContext;
-import org.simantics.databoard.serialization.SerializationException;
import org.simantics.databoard.serialization.Serializer;
import org.simantics.databoard.type.Datatype;
-import org.simantics.databoard.util.IdentityPair;
import org.simantics.databoard.util.binary.RandomAccessBinary;
import org.simantics.db.Metadata;
import org.simantics.db.ReadGraph;
import org.simantics.layer0.Layer0;
import org.simantics.utils.datastructures.MapList;
-import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TIntIntHashMap;
import gnu.trove.map.hash.TObjectIntHashMap;
* immediately but with an explicit commit method. All read operations
* return results based on the old graph.
*/
-public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader {
-
- private static final boolean DEBUG = false;
- public static int BUFFER = 65536;
-
- static class Haxx extends Binding {
-
- static final Serializer serializer = new Serializer() {
-
- public byte[] serialize(Object obj) throws SerializationException {
- return (byte[])obj;
- }
-
- @Override
- public void serialize(DataOutput out,
- TObjectIntHashMap<Object> identities, Object obj)
- throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public void serialize(DataOutput out, Object obj)
- throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public Object deserialize(DataInput in, List<Object> identities)
- throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public Object deserialize(DataInput in) throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public void deserializeTo(DataInput in, List<Object> identities,
- Object obj) throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public void deserializeTo(DataInput in, Object obj)
- throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public void skip(DataInput in, List<Object> identities)
- throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public void skip(DataInput in) throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public Integer getConstantSize() {
- throw new Error("Not supported.");
- }
-
- @Override
- public int getSize(Object obj, TObjectIntHashMap<Object> identities)
- throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public int getSize(Object obj) throws IOException {
- throw new Error("Not supported.");
- }
-
- @Override
- public int getMinSize() {
- throw new Error("Not supported.");
- }
-
- };
-
- @Override
- public Serializer serializer() {
- return serializer;
- }
-
- @Override
- public void accept(Visitor1 v, Object obj) {
- throw new Error("Not supported.");
- }
-
- @Override
- public <T> T accept(Visitor<T> v) {
- throw new Error("Not supported.");
- }
-
- @Override
- public boolean isInstance(Object obj) {
- throw new Error("Not supported.");
- }
-
- @Override
- public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
- throws org.simantics.databoard.binding.error.BindingException {
- throw new Error("Not supported.");
- }
-
- @Override
- public int deepHashValue(Object value,
- IdentityHashMap<Object, Object> hashedObjects)
- throws org.simantics.databoard.binding.error.BindingException {
- throw new Error("Not supported.");
- }
-
- @Override
- public int deepCompare(Object o1, Object o2,
- Set<IdentityPair<Object, Object>> compareHistory)
- throws org.simantics.databoard.binding.error.BindingException {
- throw new Error("Not supported.");
- }
-
- @Override
- public void readFrom(Binding srcBinding, Object src, Object dst)
- throws org.simantics.databoard.binding.error.BindingException {
- throw new Error("Not supported.");
- }
-
- @Override
- public Object readFromTry(Binding srcBinding, Object src, Object dst)
- throws org.simantics.databoard.binding.error.BindingException {
- throw new Error("Not supported.");
- }
-
- @Override
- protected void toString(Object value, BindingPrintContext ctx) throws org.simantics.databoard.binding.error.BindingException {
- throw new Error("Not supported.");
- }
-
- @Override
- public int getComponentCount() {
- throw new Error("Not supported.");
- }
+public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader, Closeable {
- @Override
- public Binding getComponentBinding(int index) {
- throw new Error("Not supported.");
- }
+ private static final boolean DEBUG = false;
+ private static final int BUFFER_SIZE = 512*1024;
- @Override
- public Binding getComponentBinding(ChildReference path) {
- throw new Error("Not supported.");
- }
-
- }
-
- private static final Haxx haxx = new Haxx();
+ private static final PassthroughSerializerBinding PASSTHROUGH = new PassthroughSerializerBinding();
private final int TERM = 0;
private final int CLAIM = 1;
private final int DENY = 5;
private final int DENY_VALUE = 6;
private final int COMMIT_AND_CONTINUE = 7;
-
- static class ClusterSet {
- public Resource resource;
- ClusterSet() {
- ids = new TIntArrayList();
- old = false;
- }
- ClusterSet(boolean old, Resource r) {
- ids = new TIntArrayList();
- this.old = old;
- this.resource = r;
- }
- void add(int id) {
- ids.add(id);
- }
- private TIntArrayList ids;
- private final boolean old; // true if
- boolean isNew() {
- return !old;
- }
- }
- public class State {
+
+ private static class State {
public File tempFile;
public FileOutputStream out;
+ public FileInputStream in;
public ArrayList<Resource> idToResource = new ArrayList<Resource>();
public TIntIntHashMap externalToId = new TIntIntHashMap();
public ArrayList<Binding> idToBinding = new ArrayList<Binding>();
public int valueCount = 0;
public int fileCount = 0;
}
-
- public State writeState;
- public TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();
-
- Layer0 b;
- Session session;
+
+ private State writeState;
+ private TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();
+
+ private FileChannel channel;
+ private byte[] bytes = new byte[BUFFER_SIZE];
+ private ByteBuffer bb = ByteBuffer.wrap(bytes);
+ private int byteIndex = 0;
+
+ private Layer0 b;
+ private Session session;
+
public static Resource convertDelayedResource(Resource r) {
- if (r instanceof InternalResource) {
- InternalResource ri = (InternalResource)r;
- return ri.resource;
- }
+ if (r instanceof InternalResource)
+ return ((InternalResource) r).resource;
return r;
}
+
private static class InternalResource implements Resource {
int id;
long clusterId = 0;
Resource resource = null;
Resource clusterSet = null;
-
+
public InternalResource(int id, long clusterId) {
this.id = id;
this.clusterId = clusterId;
this.id = id;
this.clusterSet = clusterSet;
}
-
+
@Override
public long getResourceId() {
throw new UnsupportedOperationException();
public Resource get() {
return this;
}
-
+
@Override
public boolean isPersistent() {
return false;
@Override
public int compareTo(Resource o) {
- if(o instanceof InternalResource) {
- return Integer.compare(id, ((InternalResource)o).id);
- } else {
- return -1;
- }
+ if(o instanceof InternalResource)
+ return Integer.compare(id, ((InternalResource)o).id);
+ return -1;
}
@Override
result = prime * result + id;
return result;
}
-
+
@Override
public int getThreadHash() {
return hashCode();
return false;
return true;
}
-
@Override
public boolean equalsResource(Resource other) {
return equals(other);
}
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder(32);
session = g.getSession();
b = Layer0.getInstance(g);
this.writeState = state;
- }
+ }
public DelayedWriteGraph newSync() {
return new DelayedWriteGraph(this, writeState);
if (ws.hasClusterSet(null, clusterSet))
throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
writeState.clusterSetsForExistingResources.add(clusterSet);
- } else {
+ } else {
if(!writeState.clusterSets.add(clusterSet))
throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
}
}
}
+ private OutputStream valueWriter = new OutputStream() {
+ @Override
+ public void write(int b) throws IOException {
+ writeByte(b);
+ }
+ };
+
@Override
public void claimValue(Resource resource, Object value, Binding binding)
throws ServiceException {
try {
-
+
writeByte(CLAIM_VALUE_B);
writeInt(getId(resource));
Serializer serializer = binding.serializer();
int size = serializer.getSize(value);
writeInt(size);
- serializer.serialize(new OutputStream() {
-
- @Override
- public void write(int b) throws IOException {
- writeByte(b);
- }
-
- }, value);
-
+ serializer.serialize(valueWriter, value);
+
} catch(IOException e) {
Logger.defaultLogError(e);
throw new ServiceException(e);
public void flushCluster(Resource r) throws ServiceException {
throw new ServiceException("Operation flushCluster(" + r + " not implemented.");
}
-
- private FileChannel channel;
- byte[] bytes = new byte[BUFFER];
- byte[] buffer = new byte[BUFFER];
- ByteBuffer bb = ByteBuffer.wrap(bytes);
- int byteIndex = 0;
-
- private void writeReset(int size) {
+ private void writeReset(int size) {
byteIndex = 0;
bb.position(0);
bb.limit(size);
try {
-
- if(writeState.tempFile == null) {
-
+ if (writeState.tempFile == null) {
File workspace = Platform.getLocation().toFile();
File temp = new File(workspace, "tempFiles");
- temp.mkdirs();
-
File base = new File(temp, "delayed");
- base.mkdirs();
+ Files.createDirectories(base.toPath());
writeState.tempFile = new File(base, UUID.randomUUID().toString());
writeState.out = new FileOutputStream(writeState.tempFile);
channel = writeState.out.getChannel();
-
}
for (int got=0;got < size;) {
int n = channel.write(bb);
if (n <= 0) {
- new Exception().printStackTrace();
+ Logger.defaultLogError(new Exception("FileChannel.write returned " + n));
return;
}
got += n;
}
} catch (IOException e) {
- e.printStackTrace();
+ Logger.defaultLogError("Failed to write buffer of " + size + " bytes to temporary file " + writeState.tempFile, e);
}
}
private void reset() {
byteIndex = 0;
- try {
- bb.clear();
- for(int got=0; got < BUFFER;) {
- int n = channel.read(bb);
- if (n <= 0)
- return;
- got += n;
+ bb.clear();
+ if (channel != null) {
+ try {
+ for(int got=0; got < BUFFER_SIZE;) {
+ int n = channel.read(bb);
+ if (n <= 0)
+ return;
+ got += n;
+ }
+ } catch (IOException e) {
+ Logger.defaultLogError("FileChannel.read failed", e);
}
- } catch (IOException e) {
- e.printStackTrace();
}
}
private void writeInt(int i) {
- if(byteIndex < (BUFFER-4)) {
+ if(byteIndex < (BUFFER_SIZE-4)) {
bytes[byteIndex++] = (byte)(i&0xff);
bytes[byteIndex++] = (byte)((i>>>8)&0xff);
bytes[byteIndex++] = (byte)((i>>>16)&0xff);
bytes[byteIndex++] = (byte)((i>>>24)&0xff);
- if (byteIndex == BUFFER)
- writeReset(BUFFER);
+ if (byteIndex == BUFFER_SIZE)
+ writeReset(BUFFER_SIZE);
} else {
- int has = BUFFER-byteIndex;
- if(has == 0) writeReset(BUFFER);
+ int has = BUFFER_SIZE-byteIndex;
+ if(has == 0) writeReset(BUFFER_SIZE);
bytes[byteIndex++] = (byte)(i&0xff);
- if(has == 1) writeReset(BUFFER);
+ if(has == 1) writeReset(BUFFER_SIZE);
bytes[byteIndex++] = (byte)((i>>>8)&0xff);
- if(has == 2) writeReset(BUFFER);
+ if(has == 2) writeReset(BUFFER_SIZE);
bytes[byteIndex++] = (byte)((i>>>16)&0xff);
- if(has == 3) writeReset(BUFFER);
+ if(has == 3) writeReset(BUFFER_SIZE);
bytes[byteIndex++] = (byte)((i>>>24)&0xff);
- if(has == 4) writeReset(BUFFER);
+ if(has == 4) writeReset(BUFFER_SIZE);
}
}
-
+
private int readInt() {
- if(byteIndex < (BUFFER-4)) {
+ if(byteIndex < (BUFFER_SIZE-4)) {
int result = (int)
((bytes[byteIndex++] & 0xff) |
((bytes[byteIndex++] & 0xff)<<8) |
((bytes[byteIndex++] & 0xff)<<24));
return result;
} else {
- int has = BUFFER-byteIndex;
+ int has = BUFFER_SIZE-byteIndex;
int result = 0;
if(has == 0) reset();
result = (int)(bytes[byteIndex++] & 0xff);
return result;
}
}
-
+
private byte readByte() {
byte result = bytes[byteIndex++];
- if(byteIndex == BUFFER) reset();
+ if(byteIndex == BUFFER_SIZE) reset();
return result;
}
private void writeByte(int b) {
bytes[byteIndex++] = (byte)b;
- if(byteIndex == BUFFER) writeReset(BUFFER);
+ if(byteIndex == BUFFER_SIZE) writeReset(BUFFER_SIZE);
}
-
+
private void writeBytes(byte[] data) {
- int has = BUFFER-byteIndex;
+ int has = BUFFER_SIZE-byteIndex;
int amount = data.length;
if(has > amount) {
System.arraycopy(data, 0, bytes, byteIndex, amount);
byteIndex += amount;
} else {
System.arraycopy(data, 0, bytes, byteIndex, has);
- writeReset(BUFFER);
+ writeReset(BUFFER_SIZE);
ByteBuffer bb2 = ByteBuffer.wrap(data);
bb2.position(has);
try {
channel.write(bb2);
} catch (IOException e) {
- e.printStackTrace();
+ Logger.defaultLogError("FileChannel.write failed", e);
}
}
}
-
- public byte[] readBytes(int amount) {
- return readBytes(buffer, amount);
- }
-
+
public byte[] readBytes(byte[] result, int amount) {
if(result == null) result = new byte[amount];
- int has = BUFFER-byteIndex;
+ int has = BUFFER_SIZE-byteIndex;
if(has > amount) {
System.arraycopy(bytes, byteIndex, result, 0, amount);
byteIndex += amount;
try {
got += channel.read(bb2);
if(got == -1) {
- new Exception().printStackTrace();
+ // End-of-stream, why log this?
return result;
}
-
} catch (IOException e) {
- e.printStackTrace();
+ Logger.defaultLogError("FileChannel.read failed", e);
}
reset();
}
return result;
}
-
+
public void commit(final WriteOnlyGraph w, final WriteTraits traits) throws ServiceException {
writeState.bindingToId = null;
writeState.externalToId = null;
- try {
-
- writeByte(TERM);
- if(byteIndex > 0) {
+ writeByte(TERM);
+
+ if (writeState.out != null) {
+ // Flush current buffer to file only if backing file has already
+ // been taken into use.
+ if (byteIndex > 0)
writeReset(byteIndex);
+
+ try (OutputStream out = writeState.out) {
+ channel.force(false);
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ } finally {
+ writeState.out = null;
}
- channel.force(false);
- writeState.out.close();
- FileInputStream fs = new FileInputStream(writeState.tempFile);
- channel = fs.getChannel();
-
- } catch (IOException e) {
- throw new ServiceException(e);
+ try {
+ writeState.in = new FileInputStream(writeState.tempFile);
+ channel = writeState.in.getChannel();
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ }
}
-
+
w.getMetadata().putAll(metadata);
-
+
TransferableGraphSupport tgs = w.getService(TransferableGraphSupport.class);
// First create all resources defined by clusterId
}
reset();
- bb.limit(BUFFER);
+ bb.limit(BUFFER_SIZE);
try {
while(true) {
byte method = readByte();
- switch(method) {
+ switch(method) {
case TERM: {
+ if (DEBUG) {
+ System.out.println("Resources: " + writeState.idToResource.size());
+ System.out.println("Statements: " + writeState.statementCount);
+ System.out.println("Values: " + writeState.valueCount);
+ System.out.println("Files: " + writeState.fileCount);
+ System.out.println("Clusters: " + writeState.clusterCount);
+ }
return;
}
case CLAIM: {
Resource resource = getResource(readInt());
int len = readInt();
tgs.setValue(w, resource, null, this, len);
-// byte[] bytes = readBytes(len);
-// tgs.setValue(resource, null, bytes);
} break;
case COMMIT_AND_CONTINUE: {
XSupport xs = w.getService(XSupport.class);
else
throw new ServiceException(e);
} finally {
- try {
- channel.close();
- channel = null;
- } catch (IOException e) {
- throw new ServiceException(e);
+ channel = null;
+ if (writeState.in != null) {
+ try (InputStream in = writeState.in) {
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ } finally {
+ writeState.in = null;
+ writeState.tempFile.delete();
+ }
}
}
-// System.out.println("Resources: " + state.resourceCount);
-// System.out.println("Statements: " + state.statementCount);
-// System.out.println("Values: " + state.valueCount);
}
-
+
private Resource getType(Object value) {
Class<?> clazz = value.getClass();
Resource dataType =
: clazz == String[].class ? b.StringArray
: clazz == boolean[].class ? b.BooleanArray
: clazz == byte[].class ? b.ByteArray
- : clazz == long[].class ? b.LongArray
+ : clazz == long[].class ? b.LongArray
: null
;
return dataType;
}
-
+
public long newCluster() {
return -1 - (++writeState.clusterCount);
}
public long getDefaultCluster() {
return writeState.defaultCluster;
}
-
+
public void setDefaultCluster(long cluster) {
writeState.defaultCluster = cluster;
}
-
+
@Override
public void syncRequest(final DelayedWrite request) throws DatabaseException {
-
+
try {
final DelayedWriteGraph dwg = new DelayedWriteGraph(this);
});
} catch (DatabaseException e) {
-
+
throw e;
-
+
} catch (Throwable e) {
-
+
throw new DatabaseException(e);
-
+
} finally {
-
}
-
+
}
-
+
@Override
public void syncRequest(WriteOnly request) throws DatabaseException {
-
+
Resource defaultClusterSet = setClusterSet4NewResource(null);
-
+
try {
WriteSupport ws = session.getService(WriteSupport.class);
ws.performWriteRequest(this, request);
} finally {
setClusterSet4NewResource(defaultClusterSet);
}
-
+
}
@SuppressWarnings("unchecked")
@Override
public <T> T getService(Class<T> api) {
-
+
if(ClusteringSupport.class == api) {
final ClusteringSupport support = (ClusteringSupport)super.getService(api);
return (T)new ClusteringSupport() {
-
+
@Override
public Resource getResourceByIndexAndCluster(int resourceIndex, long clusterId)
throws DatabaseException, ResourceNotFoundException {
return support.getResourceByIndexAndCluster(resourceIndex, clusterId);
}
-
+
@Override
public Resource getResourceByKey(int resourceKey) throws ResourceNotFoundException {
return support.getResourceByKey(resourceKey);
}
-
+
@Override
public int getNumberOfResources(long clusterId)
throws DatabaseException {
return support.getNumberOfResources(clusterId);
}
-
+
@Override
public long getCluster(Resource r) {
return support.getCluster(r);
}
-
+
@Override
public long createCluster() {
return newCluster();
}
-
+
@Override
public boolean isClusterSet(Resource r) throws DatabaseException {
return support.isClusterSet(r);
public Resource getClusterSetOfCluster(Resource r) throws DatabaseException {
return support.getClusterSetOfCluster(r);
}
-
+
@Override
public Resource getClusterSetOfCluster(long cluster) throws DatabaseException {
return support.getClusterSetOfCluster(cluster);
}
};
-
+
} else if (TransferableGraphSupport.class == api) {
-
+
final TransferableGraphSupport parentSupport = session.getService(TransferableGraphSupport.class);
-
+
return (T)new TransferableGraphSupport() {
@Override
writeInt(getId(resource));
writeInt(raw.length);
writeBytes(raw);
- writeInt(getBindingId(haxx));
+ writeInt(getBindingId(PASSTHROUGH));
}
-
+
@Override
public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, ByteReader reader, int amount)
throws DatabaseException {
writeInt(getId(resource));
writeInt(amount);
writeBytes(reader.readBytes(null, amount));
- writeInt(getBindingId(haxx));
+ writeInt(getBindingId(PASSTHROUGH));
}
-
+
@Override
public byte[] getValue(ReadGraph graph, Resource resource) {
return parentSupport.getValue(graph, resource);
}
-
+
@Override
public InputStream getValueStream(ReadGraph graph, Resource resource) {
return parentSupport.getValueStream(graph, resource);
}
-
+
};
}
-
+
return super.getService(api);
-
+
}
@Override
}
}
+ public void close() {
+ if (writeState.out != null) {
+ try (OutputStream out = writeState.out) {
+ } catch (IOException e) {
+ Logger.defaultLogError("Failed to close delayed write graph temporary commit output stream", e);
+ } finally {
+ writeState.out = null;
+ }
+ }
+ if (writeState.in != null) {
+ try (InputStream in = writeState.in) {
+ } catch (IOException e) {
+ Logger.defaultLogError("Failed to close delayed write graph temporary commit input stream", e);
+ } finally {
+ writeState.in = null;
+ }
+ }
+ if (writeState.tempFile != null) {
+ writeState.tempFile.delete();
+ writeState.tempFile = null;
+ }
+ }
+
}
--- /dev/null
+package org.simantics.db.impl.graph;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.simantics.databoard.accessor.reference.ChildReference;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.impl.BindingPrintContext;
+import org.simantics.databoard.serialization.SerializationException;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.util.IdentityPair;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+/**
+ * Originally within DelayedWriteGraph, put in separate file in 1.30.0.
+ *
+ * @author Antti Villberg
+ */
+class PassthroughSerializerBinding extends Binding {
+
+ static final Serializer serializer = new Serializer() {
+
+ public byte[] serialize(Object obj) throws SerializationException {
+ return (byte[])obj;
+ }
+
+ @Override
+ public void serialize(DataOutput out,
+ TObjectIntHashMap<Object> identities, Object obj)
+ throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public void serialize(DataOutput out, Object obj)
+ throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public Object deserialize(DataInput in, List<Object> identities)
+ throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public Object deserialize(DataInput in) throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public void deserializeTo(DataInput in, List<Object> identities,
+ Object obj) throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public void deserializeTo(DataInput in, Object obj)
+ throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public void skip(DataInput in, List<Object> identities)
+ throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public void skip(DataInput in) throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public Integer getConstantSize() {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public int getSize(Object obj, TObjectIntHashMap<Object> identities)
+ throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public int getSize(Object obj) throws IOException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public int getMinSize() {
+ throw new Error("Not supported.");
+ }
+
+ };
+
+ @Override
+ public Serializer serializer() {
+ return serializer;
+ }
+
+ @Override
+ public void accept(Visitor1 v, Object obj) {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public <T> T accept(Visitor<T> v) {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public boolean isInstance(Object obj) {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
+ throws org.simantics.databoard.binding.error.BindingException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public int deepHashValue(Object value,
+ IdentityHashMap<Object, Object> hashedObjects)
+ throws org.simantics.databoard.binding.error.BindingException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public int deepCompare(Object o1, Object o2,
+ Set<IdentityPair<Object, Object>> compareHistory)
+ throws org.simantics.databoard.binding.error.BindingException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public void readFrom(Binding srcBinding, Object src, Object dst)
+ throws org.simantics.databoard.binding.error.BindingException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public Object readFromTry(Binding srcBinding, Object src, Object dst)
+ throws org.simantics.databoard.binding.error.BindingException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ protected void toString(Object value, BindingPrintContext ctx) throws org.simantics.databoard.binding.error.BindingException {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public int getComponentCount() {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public Binding getComponentBinding(int index) {
+ throw new Error("Not supported.");
+ }
+
+ @Override
+ public Binding getComponentBinding(ChildReference path) {
+ throw new Error("Not supported.");
+ }
+
+}
\ No newline at end of file
TransferableGraphConfiguration2 conf = new TransferableGraphConfiguration2(graph, resource);
conf.values = false;
- ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf));
final SerialisationSupport ss = graph.getService(SerialisationSupport.class);
- try {
+ try (ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf))) {
source.forResourceStatements(graph, new TransferableGraphSourceProcedure<int[]>() {
@Override
});
- source.closeStreams();
-
} catch (Exception e) {
throw new DatabaseException(e);
}
* @param graph
* @param component
* for which the identifier is added
+ * @param add
+ * <code>true</code> to invoke addLiteral, <code>false</code> to
+ * invoke claimLiteral
* @throws DatabaseException
*/
- public static void addL0Identifier(WriteGraph graph, Resource component) throws DatabaseException {
+ public static void claimNewIdentifier(WriteGraph graph, Resource component, boolean add) throws DatabaseException {
Layer0 L0 = Layer0.getInstance(graph);
- graph.addLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, GUID.random(), GUID.BINDING);
+ GUID guid = GUID.random();
+ if (add)
+ graph.addLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING);
+ else
+ graph.claimLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING);
+ }
+
+ /**
+ * Sets a new random unique identifier for the specified entity if it already
+ * has an identifier. If the entity does not have a previous identifier, nothing
+ * is done.
+ *
+ * @param graph
+ * @param entity
+ * for which the identifier is added
+ * @return <code>true</code> if the identifier was renewed, <code>false</code>
+ * otherwise
+ * @throws DatabaseException
+ * @see {@link #claimNewIdentifier(WriteGraph, Resource, boolean)}
+ */
+ public static boolean renewIdentifier(WriteGraph graph, Resource entity) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ Statement stm = graph.getPossibleStatement(entity, L0.identifier);
+ if (stm != null) {
+ graph.claimValue(stm.getObject(), GUID.random(), GUID.BINDING);
+ return true;
+ }
+ return false;
}
}
package org.simantics.db.layer0.util;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
configuration.exclusionFunction = TGRepresentationUtils.computeExclusionFunction(graph, resources, hints);
}
- ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(configuration));
- return TransferableGraphs.create(graph, source);
-
+ try (ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(configuration))) {
+ return TransferableGraphs.create(graph, source);
+ } catch (IOException e) {
+ throw new DatabaseException(e);
+ }
}
@SuppressWarnings("unchecked")
} catch (Throwable e) {
delayedWriteState.except(e);
total.finish();
+ dwg.close();
return;
} finally {
// newGraph.state.barrier.dec();
}
}
- private static final ConnectionStyle DEFAULT_CONNECTION_STYLE = new ExampleConnectionStyle();
+ private static final ConnectionStyle DEFAULT_CONNECTION_STYLE = new BasicConnectionStyle(Color.BLACK, Color.BLACK, 3, ExampleConnectionStyle.SOLID, ExampleConnectionStyle.SOLID, 8);
/**
* @param graph
import org.simantics.db.common.utils.NameUtils;
import org.simantics.db.common.utils.OrderedSetUtils;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.Layer0Utils;
import org.simantics.db.layer0.util.RemoverUtil;
import org.simantics.db.request.Write;
import org.simantics.diagram.content.ConnectionUtil;
graph.claim(copy, L0.ConsistsOf, L0.PartOf, relationCopy);
graph.claim(copy, MOD.HasReferenceRelation, MOD.HasReferenceRelation_Inverse, relationCopy);
+ // #7348: renew reference relation GUID identifiers properly
+ Layer0Utils.renewIdentifier(graph, relationCopy);
+ for (Resource invRel : graph.getObjects(relationCopy, L0.ConsistsOf))
+ Layer0Utils.renewIdentifier(graph, invRel);
+
return copy;
}
package org.simantics.layer0.utils.writer;
-import gnu.trove.map.hash.TIntIntHashMap;
-import gnu.trove.map.hash.TIntLongHashMap;
-
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import org.simantics.db.WriteOnlyGraph;
import org.simantics.db.exception.DatabaseException;
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.map.hash.TIntLongHashMap;
+
public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
protected File file;
System.out.println("Temp file: " + file.getAbsolutePath());
s = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file), 1024*1024));
// s = new ObjectOutputStream(backup);
-
file.deleteOnExit();
} catch (IOException e) {
throw new RuntimeException("Opening output stream to temporary file failed", e);
assert(value != null);
assert(dataType != null);
try {
- ++internalCount;
+ ++internalCount;
timestamps.add(0);
- s.writeByte(1);
- writeRef(internalCount);
+ s.writeByte(1);
+ writeRef(internalCount);
s.writeUnshared(value);
- writeRef(getId(dataType));
+ writeRef(getId(dataType));
s.writeByte(0);
writeRef(current);
assert(value != null);
assert(dataType != null);
try {
- ++internalCount;
+ ++internalCount;
timestamps.add(0);
- s.writeByte(1);
- writeRef(internalCount);
+ s.writeByte(1);
+ writeRef(internalCount);
s.writeUnshared(value);
- writeRef(getId(dataType));
-
+ writeRef(getId(dataType));
+
current = internalCount;
} catch (IOException e) {
throw new RuntimeException("Writing statement failed.", e);
clusterHints.put(current, clusterHint);
return this;
}
-
+
@Override
public GraphWriter createInverse(int cluster, Resource r) {
assert(r != null);
}
return this;
}
-
+
@Override
public GraphWriter createInverse(Resource r) {
assert(r != null);
throw new RuntimeException("Writing statement failed.", e);
}
return this;
- }
+ }
protected Resource getResource(WriteOnlyGraph wg, Resource[] internals, long[] resourceIds, int id) {
if(id > 0) {
@Override
public void commit(IProgressMonitor monitor, WriteOnlyGraph wg) throws DatabaseException {
-
try {
- if (s != null) {
- s.close();
- s = null;
- }
+ if (s != null) {
+ s.close();
+ s = null;
+ }
externalsInv = null;
-
- monitor.beginTask("", 100);
-
- int lastPercentageDone = 0;
- long fileLength = file.length();
-
-// System.out.println("size of commit file: " + fileLength);
-
- Resource[] internals = new Resource[internalCount];
- resourceIds = new long[internalCount];
-
-
+ monitor.beginTask("Writing database", 100);
FileInputStream fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
- ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(fis, 1024*1024));
- int resourceCounter = 0;
- int statementCounter = 0;
- int valueCounter = 0;
- time = 0;
- loop: while(true) {
- switch(is.read()) {
- case -1:
- break loop;
- case 0: {
- int s = is.readInt();
- int p = is.readInt();
- int o = is.readInt();
- Resource rs = getResource(wg, internals, resourceIds, s);
- Resource rp = getResource(wg, internals, resourceIds, p);
- Resource ro = getResource(wg, internals, resourceIds, o);
- Resource rpInv = inverses.get(p);
- wg.claim(rs, rp, rpInv, ro);
- statementCounter += 2;
- } break;
- case 1: {
- int id = is.readInt();
- Object value = is.readUnshared();
- int type = is.readInt();
-
- Resource r = newResource(wg, internals, id);
- wg.claim(r, l0.InstanceOf, null, getResource(wg, internals, resourceIds, type));
- wg.claimValue(r, value);
- statementCounter ++;
- resourceCounter ++;
- valueCounter ++;
-
- } break;
- case 2: {
- wg.flushCluster();
- } break;
- case 3: {
-
- int s = is.readInt();
- int t = is.readInt();
-
- Resource type = getResource(wg, internals, resourceIds, t);
- wg.claim(newResource(wg, internals, s), l0.InstanceOf, null, type);
- statementCounter ++;
- resourceCounter ++;
-
- } break;
- case 4: {
-
- int s = is.readInt();
- newResource(wg, internals, s);
- resourceCounter ++;
-
- } break;
- case 5: { // InverseOf
-
- int r1 = is.readInt();
- int r2 = is.readInt();
-
- Resource rr1 = getResource(wg, internals, resourceIds, r1);
- Resource rr2 = getResource(wg, internals, resourceIds, r2);
- wg.claim(rr1, l0.InverseOf, l0.InverseOf, rr2);
- statementCounter += 2;
-
- inverses.put(r1, rr2);
- inverses.put(r2, rr1);
-
- } break;
- }
-
-// if((counter % 200000) == 0) {
-// System.out.println("Written " + counter + " statements.");
-// }
-
- double percentageDone = 100.0 * (double) fc.position() / (double) fileLength;
- int newPercentageDone = (int) Math.round(percentageDone);
- if(newPercentageDone > lastPercentageDone) {
- monitor.setTaskName("Writing database (" + newPercentageDone + "%)");
- monitor.worked(newPercentageDone - lastPercentageDone);
- lastPercentageDone = newPercentageDone;
- }
+ try (ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(fis, 1024*1024))) {
+ commit(monitor, wg, is, fc);
}
-
- System.out.println("clusterIds.size() = " + clusterIds.size());
-
- System.out.println("Wrote " + resourceCounter + " resources, " + statementCounter + " statements and " + valueCounter + " values.");
-
} catch (IOException e) {
- throw new RuntimeException("Commiting delayed graph writings failed.", e);
+ throw new DatabaseException("Commiting delayed graph writings failed.", e);
} catch (ClassNotFoundException e) {
- throw new RuntimeException("Commiting delayed graph writings failed.", e);
- } finally {
+ throw new DatabaseException("Commiting delayed graph writings failed.", e);
+ } finally {
file.delete();
monitor.done();
}
}
-
+
+ private void commit(IProgressMonitor monitor, WriteOnlyGraph wg, ObjectInputStream is, FileChannel fc) throws DatabaseException, IOException, ClassNotFoundException {
+ int lastPercentageDone = 0;
+ long fileLength = file.length();
+ //System.out.println("size of commit file: " + fileLength);
+
+ Resource[] internals = new Resource[internalCount];
+ resourceIds = new long[internalCount];
+
+ int resourceCounter = 0;
+ int statementCounter = 0;
+ int valueCounter = 0;
+ time = 0;
+ while(true) {
+ switch(is.read()) {
+ case -1:
+ System.out.println("clusterIds.size() = " + clusterIds.size());
+ System.out.println("Wrote " + resourceCounter + " resources, " + statementCounter + " statements and " + valueCounter + " values.");
+ return;
+
+ case 0: {
+ int s = is.readInt();
+ int p = is.readInt();
+ int o = is.readInt();
+ Resource rs = getResource(wg, internals, resourceIds, s);
+ Resource rp = getResource(wg, internals, resourceIds, p);
+ Resource ro = getResource(wg, internals, resourceIds, o);
+ Resource rpInv = inverses.get(p);
+ wg.claim(rs, rp, rpInv, ro);
+ statementCounter += 2;
+ } break;
+ case 1: {
+ int id = is.readInt();
+ Object value = is.readUnshared();
+ int type = is.readInt();
+
+ Resource r = newResource(wg, internals, id);
+ wg.claim(r, l0.InstanceOf, null, getResource(wg, internals, resourceIds, type));
+ wg.claimValue(r, value);
+ statementCounter ++;
+ resourceCounter ++;
+ valueCounter ++;
+
+ } break;
+ case 2: {
+ wg.flushCluster();
+ } break;
+ case 3: {
+
+ int s = is.readInt();
+ int t = is.readInt();
+
+ Resource type = getResource(wg, internals, resourceIds, t);
+ wg.claim(newResource(wg, internals, s), l0.InstanceOf, null, type);
+ statementCounter ++;
+ resourceCounter ++;
+
+ } break;
+ case 4: {
+
+ int s = is.readInt();
+ newResource(wg, internals, s);
+ resourceCounter ++;
+
+ } break;
+ case 5: { // InverseOf
+
+ int r1 = is.readInt();
+ int r2 = is.readInt();
+
+ Resource rr1 = getResource(wg, internals, resourceIds, r1);
+ Resource rr2 = getResource(wg, internals, resourceIds, r2);
+ wg.claim(rr1, l0.InverseOf, l0.InverseOf, rr2);
+ statementCounter += 2;
+
+ inverses.put(r1, rr2);
+ inverses.put(r2, rr1);
+
+ } break;
+ }
+
+// if((counter % 200000) == 0) {
+// System.out.println("Written " + counter + " statements.");
+// }
+
+ double percentageDone = 100.0 * (double) fc.position() / (double) fileLength;
+ int newPercentageDone = (int) Math.round(percentageDone);
+ if(newPercentageDone > lastPercentageDone) {
+ monitor.setTaskName("Writing database (" + newPercentageDone + "%)");
+ monitor.worked(newPercentageDone - lastPercentageDone);
+ lastPercentageDone = newPercentageDone;
+ }
+ }
+ }
+
private Resource newResource(WriteOnlyGraph wg, Resource[] internals, int s) throws DatabaseException {
int clusterHint = clusterHints.get(s);
resourceIds[s-1] = r.getResourceId();
return r;
}
-
-// public ValueDescriptor createDescriptor(Object obj) {
-//
-// if(obj instanceof String[])
-// return new ValueDescriptor(ValueTrait.StaticValue, (String[])obj);
-// else if(obj instanceof int[])
-// return new ValueDescriptor(ValueTrait.StaticValue, (int[])obj);
-// else if(obj instanceof double[])
-// return new ValueDescriptor(ValueTrait.StaticValue, (double[])obj);
-// else if(obj instanceof float[])
-// return new ValueDescriptor(ValueTrait.StaticValue, (float[])obj);
-// else if(obj instanceof boolean[])
-// return new ValueDescriptor(ValueTrait.StaticValue, (boolean[])obj);
-// else if(obj instanceof long[])
-// return new ValueDescriptor(ValueTrait.StaticValue, (long[])obj);
-// else if(obj instanceof byte[])
-// return new ValueDescriptor(ValueTrait.StaticValue, (byte[])obj);
-//
-// else if(obj instanceof String)
-// return new ValueDescriptor(ValueTrait.StaticValue, new String[] {(String)obj});
-// else if(obj instanceof Double)
-// return new ValueDescriptor(ValueTrait.StaticValue, new double[] {(Double)obj});
-// else if(obj instanceof Float)
-// return new ValueDescriptor(ValueTrait.StaticValue, new float[] {(Float)obj});
-// else if(obj instanceof Integer)
-// return new ValueDescriptor(ValueTrait.StaticValue, new int[] {(Integer)obj});
-// else if(obj instanceof Boolean)
-// return new ValueDescriptor(ValueTrait.StaticValue, new boolean[] {(Boolean)obj});
-// else if(obj instanceof Byte)
-// return new ValueDescriptor(ValueTrait.StaticValue, new byte[] {(Byte)obj});
-// else if(obj instanceof Long)
-// return new ValueDescriptor(ValueTrait.StaticValue, new long[] {(Long)obj});
-//
-// throw new Error("Wrong type!");
-//
-// }
@Override
public GraphWriter create() {
@Override
public GraphWriter create(int clusterHint, Resource type) {
-
- create(type);
+ create(type);
clusterHints.put(current, clusterHint);
return this;
return this;
}
- public GraphWriter flush() {
+ public GraphWriter flush() {
try {
s.writeByte(2);
} catch(IOException e) {
Resource project = SimanticsUI.getProject().get();
- try {
-
- StreamingTransferableGraphFileReader importer = new StreamingTransferableGraphFileReader(new File(fileName));
+ try (StreamingTransferableGraphFileReader importer = new StreamingTransferableGraphFileReader(new File(fileName))) {
TransferableGraphSource tg = importer.readTG();
final DefaultPasteImportAdvisor advisor = new DefaultPasteImportAdvisor(project) {
Layer0 L0 = Layer0.getInstance(graph);
while(!todo.isEmpty()) {
Resource resource = todo.remove(todo.size()-1);
- Layer0Utils.addL0Identifier(graph, resource);
+ Layer0Utils.claimNewIdentifier(graph, resource, false);
if(deep)
todo.addAll(graph.getObjects(resource, L0.ConsistsOf));
}
GUID existing = graph.getPossibleRelatedValue(r, L0.identifier, GUID.BINDING);
if(existing == null) {
- Layer0Utils.addL0Identifier(graph, r);
+ Layer0Utils.claimNewIdentifier(graph, r, true);
madeChanges = true;
}
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Random;
import java.util.Set;
import java.util.UUID;
+import java.util.stream.Collectors;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGeneratorContext;
import org.apache.batik.svggen.SVGGraphics2D;
+import org.simantics.Simantics;
+import org.simantics.datatypes.literal.GUID;
+import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
+import org.simantics.db.common.request.UnaryRead;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
import org.simantics.diagram.elements.DiagramNodeUtil;
import org.simantics.diagram.elements.TextGridNode;
import org.simantics.diagram.elements.TextNode;
+import org.simantics.diagram.stubs.DiagramResource;
import org.simantics.g2d.canvas.ICanvasContext;
import org.simantics.g2d.diagram.DiagramHints;
import org.simantics.g2d.diagram.IDiagram;
import org.simantics.g2d.element.IElement;
import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider;
import org.simantics.g2d.utils.CanvasUtils;
+import org.simantics.layer0.Layer0;
import org.simantics.scenegraph.INode;
import org.simantics.scenegraph.ParentNode;
import org.simantics.scenegraph.g2d.G2DParentNode;
import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;
import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.scl.runtime.function.Function1;
import org.simantics.trend.impl.ItemNode;
import org.simantics.utils.threads.ThreadUtils;
import org.slf4j.Logger;
}
- public static String renderSVG(ICanvasContext ctx) {
+ public static String renderSVG3(ICanvasContext ctx) {
+ return renderSVG0(ctx, p0 -> p0.stream().collect(Collectors.toMap(p1 -> p1, p2 -> p2)));
+ }
+
+ /**
+ * @param graph
+ * @param component
+ * @throws DatabaseException
+ */
+ private static Object[] createURIBasedL0Identifier(ReadGraph graph, Resource component) throws DatabaseException {
+ String uri = graph.getPossibleURI(component);
+ int hashCode = uri.hashCode();
+ Random random = new Random(hashCode);
+ long l1 = random.nextLong();
+ long l2 = random.nextLong();
+ return new Object[] { l1, l2 };
+ }
+
+ /**
+ * Default no-op mapper
+ */
+ private static final Function1<Set<?>, Map<?, ?>> mapper = p0 -> p0.stream().collect(Collectors.toMap(p1 -> p1, p2 -> p2));
+
+ public static String renderSVG(ICanvasContext ctx) {
+ return renderSVG0(ctx, mapper);
+ }
+
+ /**
+ * Renders ICanvasContext into SVG by mapping the SVG id's into URI based
+ * GUID's
+ *
+ * @param ctx
+ * @return
+ */
+ public static String renderSVGMapIdentifiers(ICanvasContext ctx) {
+ return renderSVG0(ctx, new Function1<Set<?>, Map<?, ?>>() {
+
+ @Override
+ public Map<?, ?> apply(Set<?> p0) {
+ try {
+ return Simantics.getSession().syncRequest(new UnaryRead<Set<?>, Map<?, ?>>(p0) {
+
+ @Override
+ public Map<?, ?> perform(ReadGraph graph) throws DatabaseException {
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ DiagramResource DIA = DiagramResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+ return parameter.stream().collect(Collectors.toMap(p -> p, p -> {
+ try {
+ if (p instanceof Resource) {
+ Resource element = (Resource) p;
+ if (graph.isInstanceOf(element, DIA.Element)) {
+ Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
+ if (component != null) {
+ GUID identifier = graph.getPossibleRelatedValue(component, L0.identifier, GUID.BINDING);
+ if (identifier != null) {
+ return Arrays.toString(createURIBasedL0Identifier(graph, component));
+ } else {
+ LOGGER.error("Component {} does not have GUID identifier!", component);
+ }
+ } else if (graph.isInstanceOf(element, DIA.Connection) || graph.isInstanceOf(element, DIA.Terminal)) {
+ // Ok, lets create a hashcode for connections and terminals as they do not have identifiers
+ return graph.getURI(element).hashCode();
+ } else {
+ // Ok, lets create a hashcode or either return empty string in cases where no ID is required
+ if (graph.hasStatement(element, L0.HasName))
+ return graph.getURI(element).hashCode();
+ return "";
+ }
+ }
+ } else {
+ LOGGER.error("Parameter p {} is not resource but it is {}", p, p.getClass());
+ }
+ return p;
+ } catch (DatabaseException e) {
+ throw new RuntimeDatabaseException(e);
+ }
+ }));
+ }
+ });
+ } catch (DatabaseException e) {
+ LOGGER.error("Could not apply mappings", e);
+ throw new RuntimeDatabaseException(e);
+ }
+ }
+ });
+ }
+
+ private static String renderSVG0(ICanvasContext ctx, Function1<Set<?>, Map<?, ?>> mappingFunction) {
// Get a DOMImplementation.
DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
result.append("<svg width=\"100%\" height=\"100%\" stroke=\"black\"><g transform=\"translate(").append(trX).append(' ').append(trY).append(")\">");
- IG2DNodeVisitor visitor = new IG2DNodeVisitor() {
-
- int indent = 0;
-
- HashMap<SingleElementNode,StringBuilder> senBuilders = new HashMap<>();
-
- @Override
- public void enter(IG2DNode node) {
-
- StringBuilder parentBuilder = getParentBuilder(node);
-
- indent++;
- if(node instanceof ConnectionNode) {
-
- for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
- n.setIgnoreSelection(true);
- }
-
- String key = ((ConnectionNode)node).getKey().toString();
-
- parentBuilder.append("\n<g class=\"connection\" id=\"" + key + "\">");
- Element doc = renderSVGNode((IG2DNode)node);
- String svg = printSVGDocument(doc);
- parentBuilder.append(svg);
-
- for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
- n.setIgnoreSelection(false);
- }
-
- parentBuilder.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
- doc = renderSVGNode((IG2DNode)node);
- svg = printSVGDocument(doc);
- parentBuilder.append(svg);
- parentBuilder.append("\n</g>");
-
- BasicStroke bs = new BasicStroke(5f);
-
- for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
- n.setDynamicStroke(bs);
- }
-
- parentBuilder.append("\n<g class=\"selectionMask\" opacity=\"0.001\" id=\"" + key + "\">");
- doc = renderSVGNode((IG2DNode)node);
- svg = printSVGDocument(doc);
- parentBuilder.append(svg);
- parentBuilder.append("\n</g>");
-
- parentBuilder.append("\n</g>");
-
- } else if (node instanceof SelectionNode) {
-
- SelectionNode n = (SelectionNode)node;
- SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
- if(parentSEN != null && parentSEN.getKey() != null) {
-
- StringBuilder parentBuilder2 = getParentBuilder(parentSEN);
-
- String key = parentSEN.getKey().toString();
- Element doc = renderSVGNode((IG2DNode)node);
- String svg = printSVGDocument(doc);
- parentBuilder2.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
- parentBuilder2.append(svg);
- parentBuilder2.append("\n</g>");
- parentBuilder2.append("\n<g class=\"selectionMask\" id=\"" + key + "\">");
- Rectangle2D rect = n.getRect();
- parentBuilder2.append("<rect style=\"fill:#fff\" opacity=\"0.001\"");
- parentBuilder2.append(" x=\"" + rect.getX() + "\" y=\"" + rect.getY() + "\"");
- parentBuilder2.append(" width=\"" + rect.getWidth() + "\" height=\"" + rect.getHeight() + "\"");
- parentBuilder2.append("></rect>");
- parentBuilder2.append("\n</g>");
- }
- } else if (node instanceof SVGNode) {
- SVGNode svg = (SVGNode)node;
- parentBuilder.append(svg.getSVGText());
- } else if (node instanceof G2DParentNode) {
- AffineTransform at = node.getTransform();
- if(node instanceof SingleElementNode) {
- SingleElementNode sen = (SingleElementNode)node;
- if(sen.getKey() != null) {
- String key = sen.getKey().toString();
- parentBuilder.append("\n<g class=\"definedElement\" id=\"" + key + "\">");
- }
- senBuilders.put(sen, new StringBuilder());
- }
- if(!at.isIdentity()) {
- if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) {
- String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")";
- parentBuilder.append("\n<g transform=\"" + m + "\">");
- } else {
- double[] ds = new double[6];
- at.getMatrix(ds);
- String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")";
- parentBuilder.append("\n<g transform=\"" + m + "\">");
- }
- }
- }
-
- //enters.put(node, b.length());
-
- }
-
- private StringBuilder getParentBuilder(IG2DNode node) {
-
- INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
- if(parentSEN instanceof G2DSceneGraph) return result;
-
- StringBuilder parentBuilder = senBuilders.get(parentSEN);
- if(parentBuilder == null) return result;
-
- return parentBuilder;
-
- }
-
- @Override
- public void leave(IG2DNode node) {
-
- if(node instanceof ConnectionNode || node instanceof SVGNode) {
- // We are done
- } else if (node instanceof G2DParentNode) {
-
- StringBuilder parentBuilder = getParentBuilder(node);
-
- if(node instanceof SingleElementNode) {
- SingleElementNode sen = (SingleElementNode)node;
-// if(sen.getKey() != null) {
- StringBuilder b = senBuilders.get(sen);
- String content = b.toString();
- if(content.isEmpty()) {
- if(sen.getKey() != null) {
-
- for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) {
- n.setIgnore(true);
- }
-
- Element doc = renderSVGNode((IG2DNode)node);
- String svg = printSVGDocument(doc);
- parentBuilder.append(svg);
- }
- } else {
- parentBuilder.append(content);
- }
-// }
- }
-
-
- AffineTransform at = node.getTransform();
- if(!at.isIdentity()) {
- parentBuilder.append("</g>");
- }
- if(node instanceof SingleElementNode) {
- SingleElementNode sen = (SingleElementNode)node;
- if(sen.getKey() != null) {
- parentBuilder.append("</g>");
- }
- }
- }
- indent --;
- }
+ KeyVisitor keyVisitor = new KeyVisitor();
+ sg.accept(keyVisitor);
+
+ Set<Object> keys = keyVisitor.getKeys();
+
+ Map<?, ?> mappings = mappingFunction.apply(keys);
- };
+ IG2DNodeVisitor visitor = new PrintingVisitor(result, mappings);
sg.accept(visitor);
} catch (Throwable t) {
//System.err.println(" == FINAL RESULT == ");
//System.err.println(b);
return result.toString();
+ }
+
+
+
+ private static class KeyVisitor implements IG2DNodeVisitor {
+
+ private Set<Object> keys = new HashSet<>();
+ @Override
+ public void enter(IG2DNode node) {
+ if (node instanceof SingleElementNode) {
+ Object key = ((SingleElementNode) node).getKey();
+ if (key != null) {
+ keys.add(key);
+ }
+ }
+ }
+
+ @Override
+ public void leave(IG2DNode node) {
+ // Nothing to do
+ }
+
+ public Set<Object> getKeys() {
+ return keys;
+ }
}
+ private static class PrintingVisitor implements IG2DNodeVisitor {
+
+ int indent = 0;
+
+ HashMap<SingleElementNode,StringBuilder> senBuilders = new HashMap<>();
+
+ private StringBuilder result;
+
+ private Map<?, ?> mappings;
+
+ public PrintingVisitor(StringBuilder result, Map<?, ?> mappings) {
+ this.result = result;
+ this.mappings = mappings;
+ }
+
+ private String getKey(SingleElementNode node) {
+ String key;
+ if (mappings.containsKey(node.getKey()))
+ key = mappings.get(node.getKey()).toString();
+ else
+ key = node.getKey().toString();
+ return key;
+ }
+
+ @Override
+ public void enter(IG2DNode node) {
+
+ StringBuilder parentBuilder = getParentBuilder(node);
+
+ indent++;
+ if(node instanceof ConnectionNode) {
+
+ for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+ n.setIgnoreSelection(true);
+ }
+
+ String key = getKey((ConnectionNode) node);
+ parentBuilder.append("\n<g class=\"connection\" id=\"" + key + "\">");
+ Element doc = renderSVGNode((IG2DNode)node);
+ String svg = printSVGDocument(doc);
+ parentBuilder.append(svg);
+
+ for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+ n.setIgnoreSelection(false);
+ }
+
+ parentBuilder.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
+ doc = renderSVGNode((IG2DNode)node);
+ svg = printSVGDocument(doc);
+ parentBuilder.append(svg);
+ parentBuilder.append("\n</g>");
+
+ BasicStroke bs = new BasicStroke(5f);
+
+ for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+ n.setDynamicStroke(bs);
+ }
+
+ parentBuilder.append("\n<g class=\"selectionMask\" opacity=\"0.001\" id=\"" + key + "\">");
+ doc = renderSVGNode((IG2DNode)node);
+ svg = printSVGDocument(doc);
+ parentBuilder.append(svg);
+ parentBuilder.append("\n</g>");
+
+ parentBuilder.append("\n</g>");
+
+ } else if (node instanceof SelectionNode) {
+
+ SelectionNode n = (SelectionNode)node;
+ SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
+ if(parentSEN != null && parentSEN.getKey() != null) {
+
+ StringBuilder parentBuilder2 = getParentBuilder(parentSEN);
+
+ String key = getKey(parentSEN);
+ Element doc = renderSVGNode((IG2DNode)node);
+ String svg = printSVGDocument(doc);
+ parentBuilder2.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
+ parentBuilder2.append(svg);
+ parentBuilder2.append("\n</g>");
+ parentBuilder2.append("\n<g class=\"selectionMask\" id=\"" + key + "\">");
+ Rectangle2D rect = n.getRect();
+ parentBuilder2.append("<rect style=\"fill:#fff\" opacity=\"0.001\"");
+ parentBuilder2.append(" x=\"" + rect.getX() + "\" y=\"" + rect.getY() + "\"");
+ parentBuilder2.append(" width=\"" + rect.getWidth() + "\" height=\"" + rect.getHeight() + "\"");
+ parentBuilder2.append("></rect>");
+ parentBuilder2.append("\n</g>");
+ }
+ } else if (node instanceof SVGNode) {
+ SVGNode svg = (SVGNode)node;
+ parentBuilder.append(svg.getSVGText());
+ } else if (node instanceof G2DParentNode) {
+ AffineTransform at = node.getTransform();
+ if(node instanceof SingleElementNode) {
+ SingleElementNode sen = (SingleElementNode)node;
+ if(sen.getKey() != null) {
+ String key = getKey(sen);
+ parentBuilder.append("\n<g class=\"definedElement\" id=\"" + key + "\">");
+ }
+ senBuilders.put(sen, new StringBuilder());
+ }
+ if(!at.isIdentity()) {
+ if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) {
+ String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")";
+ parentBuilder.append("\n<g transform=\"" + m + "\">");
+ } else {
+ double[] ds = new double[6];
+ at.getMatrix(ds);
+ String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")";
+ parentBuilder.append("\n<g transform=\"" + m + "\">");
+ }
+ }
+ }
+
+ //enters.put(node, b.length());
+
+ }
+
+ private StringBuilder getParentBuilder(IG2DNode node) {
+
+ INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
+ if(parentSEN instanceof G2DSceneGraph) return result;
+
+ StringBuilder parentBuilder = senBuilders.get(parentSEN);
+ if(parentBuilder == null) return result;
+
+ return parentBuilder;
+
+ }
+ @Override
+ public void leave(IG2DNode node) {
+
+ if(node instanceof ConnectionNode || node instanceof SVGNode) {
+ // We are done
+ } else if (node instanceof G2DParentNode) {
+
+ StringBuilder parentBuilder = getParentBuilder(node);
+
+ if(node instanceof SingleElementNode) {
+ SingleElementNode sen = (SingleElementNode)node;
+// if(sen.getKey() != null) {
+ StringBuilder b = senBuilders.get(sen);
+ String content = b.toString();
+ if(content.isEmpty()) {
+ if(sen.getKey() != null) {
+
+ for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) {
+ n.setIgnore(true);
+ }
+
+ Element doc = renderSVGNode((IG2DNode)node);
+ String svg = printSVGDocument(doc);
+ parentBuilder.append(svg);
+ }
+ } else {
+ parentBuilder.append(content);
+ }
+// }
+ }
+
+
+ AffineTransform at = node.getTransform();
+ if(!at.isIdentity()) {
+ parentBuilder.append("</g>");
+ }
+ if(node instanceof SingleElementNode) {
+ SingleElementNode sen = (SingleElementNode)node;
+ if(sen.getKey() != null) {
+ parentBuilder.append("</g>");
+ }
+ }
+ }
+ indent --;
+ }
+ }
}
\ No newline at end of file
import org.simantics.db.common.request.ObjectsWithType;
import org.simantics.db.common.request.PossibleIndexRoot;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.function.DbConsumer;
import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
import org.simantics.db.layer0.adapter.impl.DefaultCopyHandler;
import org.simantics.db.layer0.util.TransferableGraphConfiguration2;
if(indexRoot == null) throw new DatabaseException("Composite is not part of any index root");
String indexRootUri = graph.getURI(indexRoot);
+ DbConsumer<Resource> identifierExcluder = r -> {
+ if (r != null)
+ exclusions.addAll(graph.getObjects(r, L0.identifier));
+ };
+
for(Resource resource : resources) {
// Process all connection joins.
// This is the only way to access all of them.
for (Resource diagram : graph.getObjects(resource, MOD.CompositeToDiagram)) {
- for (Resource flag : graph.syncRequest(new ObjectsWithType(diagram, L0.ConsistsOf, DIA.Flag))) {
- for (Resource join : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
- // Joins with external references are omitted
- for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) {
- if (!resourceSet.contains(comp))
- exclusions.add(join);
- }
- // This code excludes joins with flags to external
- // diagrams that are not connected (have no
- // configuration for the flag)
- for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) {
- Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf);
- if (diagram2 != null) {
- Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite);
+ identifierExcluder.accept(diagram);
+
+ for (Resource element : graph.getObjects(diagram, L0.ConsistsOf)) {
+ identifierExcluder.accept(element);
+
+ Set<Resource> types = graph.getTypes(element);
+
+ // Check all diagram flag elements for necessary exclusions.
+ if (types.contains(DIA.Flag)) {
+ for (Resource join : graph.getObjects(element, DIA.FlagIsJoinedBy)) {
+ // Joins with external references are omitted
+ for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) {
if (!resourceSet.contains(comp))
- exclusions.add(join);
+ exclusions.add(join);
+ }
+ // This code excludes joins with flags to external
+ // diagrams that are not connected (have no
+ // configuration for the flag)
+ for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) {
+ Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf);
+ if (diagram2 != null) {
+ Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite);
+ if (!resourceSet.contains(comp))
+ exclusions.add(join);
+ }
+ }
+ }
+ }
+
+ // Check all diagram monitor elements.
+ // Any components referenced that are external to the exported diagrams must be excluded from the export.
+ // This will leave the monitors without a monitored component but export and import will work anyway.
+ if (types.contains(DIA.Monitor)) {
+ for (Resource monitoredComponent : graph.getObjects(element, DIA.HasMonitorComponent)) {
+ Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf);
+ if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) {
+ exclusions.add(monitoredComponent);
}
}
}
- }
- // Check all diagram monitor elements.
- // Any components referenced that are external to the exported diagrams must be excluded from the export.
- // This will leave the monitors without a monitored component but export and import will work anyway.
- for (Resource ref : graph.syncRequest(new ObjectsWithType(diagram, L0.ConsistsOf, DIA.Monitor))) {
- for (Resource monitoredComponent : graph.getObjects(ref, DIA.HasMonitorComponent)) {
- Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf);
- if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) {
- exclusions.add(monitoredComponent);
+ // Check all diagram reference elements for necessary exclusions.
+ if (types.contains(MOD.ReferenceElement)) {
+ for (Resource rel : graph.getObjects(element, L0.ConsistsOf)) {
+ identifierExcluder.accept(rel);
+ for (Resource invRel : graph.getObjects(rel, L0.ConsistsOf)) {
+ identifierExcluder.accept(invRel);
+ }
}
}
}
// Include resource as root
CompositeInfo info = CompositeInfo.fromResource(graph, resource);
roots.add(new RootSpec(resource, info.getTGName(), true, typeId(graph, L0, indexRootUri, resource)));
- Resource id = graph.getPossibleObject(resource, L0.identifier);
- if(id != null) exclusions.add(id);
+ identifierExcluder.accept(resource);
// Include components as roots
- for(Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
- DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child);
- id = graph.getPossibleObject(child, L0.identifier);
- if(id != null) exclusions.add(id);
+ for (Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
+ DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child);
+ identifierExcluder.accept(child);
roots.add(new RootSpec(child, cinfo.getTGName(info), true, typeId(graph, L0, indexRootUri, child)));
}
}
import org.simantics.Simantics;
import org.simantics.databoard.Bindings;
-import org.simantics.datatypes.literal.GUID;
import org.simantics.db.Resource;
import org.simantics.db.WriteGraph;
import org.simantics.db.exception.DatabaseException;
if (graph.hasStatement(sourceContainer, L0.ConsistsOf, source))
graph.claim(targetContainer, L0.ConsistsOf, copy);
- Layer0Utils.addL0Identifier(graph, copy);
+ Layer0Utils.claimNewIdentifier(graph, copy, false);
if (context.get(SynchronizationHints.NO_RENAME) == null)
renameComponent(context, graph, source, copy, sourceContainer, targetContainer);
return copy;
import org.simantics.db.exception.CancelTransactionException;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.request.PossibleModel;
+import org.simantics.db.layer0.util.Layer0Utils;
import org.simantics.diagram.stubs.DiagramResource;
import org.simantics.diagram.stubs.G2DResource;
import org.simantics.diagram.synchronization.ISynchronizationContext;
if (graph.hasStatement(sourceContainer, L0.ConsistsOf, source))
graph.claim(targetContainer, L0.ConsistsOf, copy);
+ Layer0Utils.claimNewIdentifier(graph, copy, false);
+
return copy;
}
import gnu.trove.map.hash.TIntIntHashMap;
import gnu.trove.set.hash.TIntHashSet;
-import org.simantics.datatypes.literal.GUID;
import org.simantics.db.Resource;
import org.simantics.db.WriteGraph;
import org.simantics.db.common.utils.CommonDBUtils;
Resource result = GraphUtils.create(g,
b.HasName, proposition
);
- Layer0Utils.addL0Identifier(g, result);
+ Layer0Utils.claimNewIdentifier(g, result, true);
return result;
} catch (NamingException e1) {
throw new DatabaseException(e1);
import java.util.Collection;
-import org.simantics.datatypes.literal.GUID;
import org.simantics.db.Resource;
import org.simantics.db.WriteGraph;
import org.simantics.db.common.CommentMetadata;
for (Resource r : ids) {
if (!graph.hasStatement(r, L0.identifier)) {
CommonDBUtils.selectClusterSet(graph, r);
- Layer0Utils.addL0Identifier(graph, r);
+ Layer0Utils.claimNewIdentifier(graph, r, true);
}
}
if(inlineArity < Integer.MAX_VALUE)
inlinableDefinition = (SSAFunction)definition.copy();
}
+
+ public void cleanup() {
+ if(definition != null)
+ definition.cleanup();
+ if(inlinableDefinition != null)
+ inlinableDefinition.cleanup();
+ }
}
}
public void resolve(TranslationContext context) {
+ if(parameters != null) {
+ for(int i=0;i<parameters.length;++i)
+ parameters[i] = parameters[i].resolve(context);
+ }
if(relation instanceof UnresolvedCHRRelation) {
UnresolvedCHRRelation unresolved = (UnresolvedCHRRelation)relation;
CHRConstraint constraint = context.resolveCHRConstraint(unresolved.name);
if(sclRelation != null)
relation = new ExternalCHRRelation(sclRelation);
else {
+ if(unresolved.name.contains(".")) {
+ context.getErrorLog().log(unresolved.location, "Couldn't resolve relation " + unresolved.name + ".");
+ return;
+ }
if(parameters == null) {
context.getErrorLog().log(location, "Relation must be declared if record syntax is used.");
return;
}
fields = null;
}
- else {
- for(int i=0;i<parameters.length;++i)
- parameters[i] = parameters[i].resolve(context);
- }
}
public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
import org.simantics.scl.compiler.elaboration.equation.EquationVisitor;
import org.simantics.scl.compiler.elaboration.expressions.accessor.ExpressionAccessor;
import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
equation.guard = equation.guard.accept(this);
}
+ @Override
+ public void visit(CHRStatement statement) {
+ for(int i=0;i<statement.body.length;++i)
+ statement.body[i] = statement.body[i].accept(this);
+ for(int i=0;i<statement.head.length;++i)
+ statement.head[i] = statement.head[i].accept(this);
+ }
+
}
import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor;
import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;
import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;
import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;
+import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;
import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifierVisitor;
import org.simantics.scl.compiler.elaboration.expressions.list.ListSeq;
import org.simantics.scl.compiler.elaboration.expressions.list.ListThen;
public void visit(IncludeStatement statement) {
statement.value.accept(this);
}
+
+ @Override
+ public void visit(CHRStatement statement) {
+ for(ListQualifier q : statement.body)
+ q.accept(this);
+ for(ListQualifier q : statement.head)
+ q.accept(this);
+ }
}
@Override
public void accept(StatementVisitor visitor) {
- throw new UnsupportedOperationException();
+ visitor.visit(this);
}
@Override
void visit(LetStatement statement);
void visit(RuleStatement statement);
void visit(IncludeStatement statement);
+ void visit(CHRStatement statement);
}
statement.forValRefs(visitor);
exit.forValRefs(visitor);
}
+
+ public void cleanup() {
+ for(SSAStatement statement = firstStatement;
+ statement != null; statement = statement.next)
+ statement.cleanup();
+ exit.cleanup();
+ }
}
}
public abstract void forValRefs(ValRefVisitor visitor);
+
+ public abstract void cleanup();
}
}
public abstract void forValRefs(ValRefVisitor visitor);
+
+ public abstract void cleanup();
}
\ No newline at end of file
// Add valid variables and continuations
context.validContinuations.add(returnCont);
- for(SSABlock block = firstBlock; block != null; block = block.next) {
+ for(SSABlock block = firstBlock; block != null; block = block.next) {
context.validContinuations.add(block);
for(BoundVar parameter : block.parameters)
context.validBoundVariables.add(parameter);
block.forValRefs(visitor);
}
+ @Override
+ public void cleanup() {
+ for(SSABlock block = firstBlock; block != null; block = block.next)
+ block.cleanup();
+ }
}
for(SCLConstant function : functions.values())
function.saveInlinableDefinition();
}
+
+ public void cleanup() {
+ for(SSAClosure closure : closuresToGenerate)
+ closure.cleanup();
+ for(SCLConstant constant : functions.values())
+ constant.cleanup();
+ }
}
closure.forValRefs(visitor);
}
+ @Override
+ public void cleanup() {
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())
+ closure.cleanup();
+ }
+
}
}
public abstract void forValRefs(ValRefVisitor visitor);
+
+ public abstract void cleanup();
}
public void forValRefs(ValRefVisitor visitor) {
visitor.visit(condition);
}
+
+ @Override
+ public void cleanup() {
+ condition.remove();
+ }
}
for(ValRef parameter : parameters)
visitor.visit(parameter);
}
+
+ @Override
+ public void cleanup() {
+ for(ValRef parameter : parameters)
+ parameter.remove();
+ }
}
public void forValRefs(ValRefVisitor visitor) {
visitor.visit(scrutinee);
}
+
+ @Override
+ public void cleanup() {
+ scrutinee.remove();
+ }
}
@Override
public void forValRefs(ValRefVisitor visitor) {
}
+
+ @Override
+ public void cleanup() {
+ }
}
for(ValRef parameter : parameters)
visitor.visit(parameter);
}
+
+ @Override
+ public void cleanup() {
+ function.remove();
+ for(ValRef parameter : parameters)
+ parameter.remove();
+ }
}
for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())
closure.forValRefs(visitor);
}
+
+ @Override
+ public void cleanup() {
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())
+ closure.cleanup();
+ }
}
throw new SCLExpressionCompilationException(errorLog.getErrors());
}
Map<String, byte[]> classes = moduleBuilder.getClasses();
+ ssaModule.cleanup();
// Load generated code and execute
try {
import java.util.Set;
import org.simantics.databoard.Bindings;
-import org.simantics.datatypes.literal.GUID;
import org.simantics.db.ReadGraph;
import org.simantics.db.RequestProcessor;
import org.simantics.db.Resource;
g.claim(component, L0.HasName, Layer0Utils.literal(g, name));
g.claim(component, L0.HasLabel, Layer0Utils.literal(g, ""));
g.claim(parent, L0.ConsistsOf, component);
- // Add identifier
- Layer0Utils.addL0Identifier(g, component);
+ Layer0Utils.claimNewIdentifier(g, component, true);
// Add comment to change set.
CommentMetadata cm = g.getMetadata(CommentMetadata.class);
g.addMetadata(cm.add("Created component " + component));
ModuleRepository repo = new ModuleRepository(SCLOsgi.SOURCE_REPOSITORY);
CommandSession session = null;
try {
- repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {
-
- @Override
- public ModuleCompilationOptions getOptions(String moduleName) {
- // TODO: default to false
- boolean coverage = true;
- // TODO: add moduleName filters back
- // for (Pattern p : getModuleNameFilterPatterns()) {
- // if (p.matcher(moduleName.toLowerCase()).find()) {
- // coverage = true;
- // break;
- // }
- // }
- return new ModuleCompilationOptions(coverage);
- }
- });
+// repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {
+//
+// @Override
+// public ModuleCompilationOptions getOptions(String moduleName) {
+// // TODO: default to false
+// boolean coverage = true;
+// // TODO: add moduleName filters back
+// // for (Pattern p : getModuleNameFilterPatterns()) {
+// // if (p.matcher(moduleName.toLowerCase()).find()) {
+// // coverage = true;
+// // break;
+// // }
+// // }
+// return new ModuleCompilationOptions(coverage);
+// }
+// });
SCLReportingHandler handler = (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
session = new CommandSession(repo, handler);
}
private static void scheduleEditorClose(IEditorPart editorPart) {
- SWTUtils.asyncExec(editorPart.getSite().getShell(), () -> {
+ if (editorPart == null)
+ return;
+ SWTUtils.asyncExec(editorPart.getSite().getWorkbenchWindow().getShell(), () -> {
// Don't have to check isDisposed since closeEditor
// will ignore already closed editor parts.
WorkbenchUtils.closeEditor(editorPart, false);
--- /dev/null
+package org.simantics.scl.compiler.tests;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
+import org.simantics.scl.compiler.errors.CompilationErrorFormatter;
+import org.simantics.scl.compiler.module.repository.ImportFailure;
+import org.simantics.scl.compiler.module.repository.ImportFailureException;
+import org.simantics.scl.compiler.module.repository.ModuleRepository;
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
+import org.simantics.scl.compiler.top.ExpressionEvaluator;
+import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class MemoryLeakTest {
+ ModuleRepository moduleRepository;
+
+ EnvironmentSpecification environmentSpecification;
+
+ @Before
+ public void initialize() throws Exception {
+ moduleRepository = InitialRepository.getInitialRepository();
+
+ // Environment for compiling expressions
+ environmentSpecification = new EnvironmentSpecification();
+ environmentSpecification.importModule("Builtin", "");
+ environmentSpecification.importModule("Prelude", "");
+ }
+
+ private void testExpression0(String expressionText,
+ Object expectedValue,
+ Type expectedType) throws Exception {
+
+ RuntimeEnvironment runtimeEnvironment;
+ try {
+ runtimeEnvironment = moduleRepository.createRuntimeEnvironment(environmentSpecification,
+ getClass().getClassLoader());
+ } catch(ImportFailureException e) {
+ for(ImportFailure failure : e.failures)
+ System.err.println("Failed to import " + failure.moduleName);
+ throw e;
+ }
+
+ // Compiling and running expression
+ try {
+ Object result = new ExpressionEvaluator(runtimeEnvironment, expressionText)
+ .expectedType(expectedType)
+ .interpretIfPossible(false)
+ .eval();
+ if(expectedValue != null)
+ Assert.assertEquals(expectedValue, result);
+ } catch(SCLExpressionCompilationException e) {
+ System.out.println(CompilationErrorFormatter.toString(expressionText, e.getErrors()));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testIt() throws Exception {
+ for(int i=0;i<1000000;++i) {
+ testExpression0("fst (\"a\", \"b\")", "a", Types.STRING);
+ if(i % 10000 == 0 && i > 0) {
+ System.gc();
+ System.runFinalization();
+ System.gc();
+ Thread.sleep(100L);
+ double used = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
+ System.out.println(i + " " + used*1e-6 + " Mb, " + (used / i) + " b / expression");
+ }
+ }
+ }
+}