Extensions extensions;
int resourceCount;
- private int identities;
- private int stmLength;
- private int valueLength;
+ private int identities = -1;
+ private int stmLength = -1;
+ private int valueLength = -1;
public FileTransferableGraphSource() throws Exception {
init();
@Override
public int getIdentityCount() throws Exception {
- identities = safeInt();
+ if(identities == -1) {
+ identities = safeInt();
+ }
return identities;
}
@Override
public int getStatementCount() throws Exception {
- stmLength = safeInt();
+ if(stmLength == -1) {
+ stmLength = safeInt();
+ }
return stmLength;
}
@Override
public int getValueCount() throws Exception {
- valueLength = safeInt();
+ if(valueLength == -1) {
+ valueLength = safeInt();
+ }
return valueLength;
}
@Override
public void forStatements(ReadGraph graph, TransferableGraphSourceProcedure<int[]> procedure) throws Exception {
-
+
int[] value = new int[4];
+ int stmLength = getStatementCount();
+
for(int stmIndex=0;stmIndex<stmLength;) {
-
+
value[stmIndex & 3] = safeInt();
stmIndex++;
if((stmIndex & 3) == 0) procedure.execute(value);
-
+
// Cached bytes
int avail = (SIZE-byteIndex) >> 2;
int allowed = Math.min(stmLength-stmIndex, avail);
// statements[stmIndex++] = ((bytes[index++]&0xff)<<24) | ((bytes[index++]&0xff)<<16) | ((bytes[index++]&0xff)<<8) | ((bytes[index++]&0xff));
}
byteIndex += allowed<<2;
-
+
}
-
+
}
@Override
public void forIdentities(ReadGraph graph, TransferableGraphSourceProcedure<Identity> procedure) throws Exception {
-
+
+ int identities = getIdentityCount();
+
for(int i=0;i<identities;i++) {
-
+
int rid = safeInt();
byte type = bytes[byteIndex++];
// External
if(type == 1) {
-
+
int parent = safeInt();
- int nameLen = bytes[byteIndex++]&0xff;
-
+ int nameLen = getDynamicUInt32();
if(byteIndex+nameLen < SIZE) {
procedure.execute(new Identity(rid, new External(parent, utf(bytes, byteIndex, byteIndex + nameLen))));
byteIndex += nameLen;
} else {
procedure.execute(new Identity(rid, new External(parent, utf(safeBytes(nameLen), 0, nameLen))));
}
-
}
// Internal
else if(type == 3) {
-
+
int parent = safeInt();
- int nameLen = bytes[byteIndex++]&0xff;
+ int nameLen = getDynamicUInt32();
if(byteIndex+nameLen < SIZE) {
procedure.execute(new Identity(rid, new Internal(parent, utf(bytes, byteIndex, byteIndex + nameLen))));
byteIndex += nameLen;
} else {
procedure.execute(new Identity(rid, new Internal(parent, utf(safeBytes(nameLen), 0, nameLen))));
}
-
+
}
// Root
else if(type == 0) {
-
- int nameLen = bytes[byteIndex++]&0xff;
+
+ int nameLen = getDynamicUInt32();
String name = utf(safeBytes(nameLen), 0, nameLen);
- int nameLen2 = bytes[byteIndex++]&0xff;
+ int nameLen2 = getDynamicUInt32();
String rType = utf(safeBytes(nameLen2), 0, nameLen2);
procedure.execute(new Identity(rid, new Root(name, rType)));
- } else if(type == 2) {
- throw new UnsupportedOperationException();
+ }
+ // Optional
+ else if(type == 2) {
+ throw new UnsupportedOperationException("Optional identities not supported");
+ } else {
+ throw new IllegalStateException("Unsupported identity type " + type);
}
}
-
+
}
@Override
public void forValues(ReadGraph graph, TransferableGraphSourceProcedure<Value> procedure) throws Exception {
-
+
+ int valueLength = getValueCount();
+
Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);
-
+
List<Object> idcontext = new ArrayList<>();
-
+
for(int i=0;i<valueLength;i++) {
int resource = safeInt();
+ idcontext.clear();
Variant value = (Variant)variantSerializer
- .deserialize((DataInput)dis, idcontext);
+ .deserialize((DataInput)dis, idcontext);
procedure.execute(new Value(resource, value));
}
-
-
+
}
-
+
@Override
public void forValues2(ReadGraph graph, TransferableGraphSourceValueProcedure procedure) throws Exception {
Binding datatypeBinding = Bindings.getBinding(Datatype.class);
Serializer datatypeSerializer = Bindings.getSerializerUnchecked(datatypeBinding);
-
+
List<Object> idContext = new ArrayList<>();
-
+
for(int i=0;i<valueLength;i++) {
int resource = safeInt();
idContext.clear();
Datatype type = (Datatype)datatypeSerializer.deserialize((DataInput)dis, idContext);
procedure.execute(resource, type, dis);
}
-
+
}
@Override
public TransferableGraphSource readTG() throws Exception {
if(getSize() == 0) return null;
-
+
return new FileTransferableGraphSource();
}
public static TransferableGraph1 create(ReadGraph graph, TransferableGraphSource source) throws DatabaseException {
- final TIntArrayList statements = new TIntArrayList();
- final ArrayList<Value> values = new ArrayList<>();
- final ArrayList<Identity> identities = new ArrayList<>();
-
try {
+ ArrayList<Identity> identities = new ArrayList<>(source.getIdentityCount());
+ source.forIdentities(graph, i -> identities.add(i));
+ TIntArrayList statements = new TIntArrayList(source.getStatementCount());
source.forStatements(graph, r -> statements.addAll(r));
+ ArrayList<Value> values = new ArrayList<>(source.getValueCount());
source.forValues(graph, v -> values.add(v));
- source.forIdentities(graph, i -> identities.add(i));
return new TransferableGraph1(source.getResourceCount(),
identities.toArray(new Identity[identities.size()]),
}
final protected byte[] safeBytes(int amount) throws IOException {
-
byte[] result = new byte[amount];
-
int has = size-byteIndex;
if(amount >= has) {
ReadableByteChannel c = channel;
int got = c.read(bb2);
if(got == -1) throw new IOException("Unexpected end-of-file");
has += got;
+ // For some unknown reason this is needed!
+ // Spec indicates that read would increment position but it does not.
+ bb2.position(has);
}
size = c.read(bb);
bb.position(0);
int result;
if(has == 0) {
ReadableByteChannel c = channel;
- ByteBuffer bb = byteBuffer;
+ ByteBuffer bb = byteBuffer;
size = c.read(bb);
if(size == -1) {
throw new EOFException("Unexpected end-of-file");
if(size == 0)
return -1;
}
- result = bytes[byteIndex];
- if(result < 0)
- result += 256;
- ++byteIndex;
+ result = bytes[byteIndex++] & 0xff;
return result;
}
public int getDynamicUInt32() throws IOException {
- int length = getByte()&0xff;
+ int length = getByte();
if(length >= 0x80) {
if(length >= 0xc0) {
if(length >= 0xe0) {
if(length >= 0xf0) {
length &= 0x0f;
- length += ((getByte()&0xff)<<3);
- length += ((getByte()&0xff)<<11);
- length += ((getByte()&0xff)<<19);
+ length += (getByte()<<3);
+ length += (getByte()<<11);
+ length += (getByte()<<19);
length += 0x10204080;
}
else {
length &= 0x1f;
- length += ((getByte()&0xff)<<4);
- length += ((getByte()&0xff)<<12);
- length += ((getByte()&0xff)<<20);
+ length += (getByte()<<4);
+ length += (getByte()<<12);
+ length += (getByte()<<20);
length += 0x204080;
}
}
else {
length &= 0x3f;
- length += ((getByte()&0xff)<<5);
- length += ((getByte()&0xff)<<13);
+ length += (getByte()<<5);
+ length += (getByte()<<13);
length += 0x4080;
}
}
else {
length &= 0x7f;
- length += ((getByte()&0xff)<<6);
+ length += (getByte()<<6);
length += 0x80;
}
}
final protected int safeInt() throws IOException {
+ byte[] bytes = this.bytes;
+
if(byteIndex >= (size-5)) {
int result = 0;
ReadableByteChannel c = channel;
- ByteBuffer bb = byteBuffer;
+ ByteBuffer bb = byteBuffer;
if(byteIndex == size) {
size = c.read(bb);
if(size == -1) throw new EOFException("Unexpected end-of-file");
bb.position(0);
byteIndex = 0;
}
- result |= ((int)(bytes[byteIndex++]&0xff)<<0);
+ result |= ((int)(bytes[byteIndex++]&0xff));
if(byteIndex == size) {
size = c.read(bb);
bb.position(0);
} else {
return ((bytes[byteIndex++]&0xff)<<24) | ((bytes[byteIndex++]&0xff)<<16) | ((bytes[byteIndex++]&0xff)<<8) | ((bytes[byteIndex++]&0xff));
}
-
+
}
-
+
final protected int getSize() {
return size;
}
int resourceCount = safeInt();
- List<Object> idcontext = new ArrayList<Object>();
+ List<Object> idcontext = new ArrayList<>();
dis = new DataInputStream(in);
Extensions extensions = (Extensions)Bindings.getSerializerUnchecked(Extensions.class).deserialize((DataInput)dis, idcontext);
// long duration = System.nanoTime() - start;
// LOGGER.warn("start in " + 1e-9*duration + "s.");
// start = System.nanoTime();
-
+
for(int i=0;i<identities;i++) {
int rid = safeInt();
byte type = bytes[byteIndex++];
// External
if(type == 1) {
-
+
int parent = safeInt();
int nameLen = getDynamicUInt32();
-
+
if(byteIndex+nameLen < SIZE) {
ids[i] = new Identity(rid, new External(parent, utf(bytes, byteIndex, byteIndex + nameLen)));
byteIndex += nameLen;
} else {
ids[i] = new Identity(rid, new External(parent, utf(safeBytes(nameLen), 0, nameLen)));
}
-
+
}
// Internal
else if(type == 3) {
-
+
int parent = safeInt();
int nameLen = getDynamicUInt32();
if(byteIndex+nameLen < SIZE) {
} else if(type == 2) {
throw new UnsupportedOperationException();
+ } else {
+ throw new IllegalStateException();
}
}
Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);
- idcontext = new ArrayList<Object>();
dis = new DataInputStream(in);
for(int i=0;i<valueLength;i++) {
int resource = safeInt();
+ idcontext.clear();
Variant value = (Variant)variantSerializer
.deserialize((DataInput)dis, idcontext);
values[i] = new Value(resource, value);
private static GraphBundleEx tryGetOnDemandGraph(Bundle bundle, URL url) throws IOException {
try {
Integer cachedHash = readCachedHash(url);
- if (cachedHash == null)
+ if (cachedHash == null) {
+ LOGGER.info("No cached hash for " + bundle);
return null;
+ }
Supplier<TransferableGraph1> graphSource = () -> {
try {
// For an unknown reason this is totally broken when running the TestSCLOsgi
// in the SDK Tycho build. It returns incomplete results because the
// ReadableByteChannel used by ByteFileReader starts returning 0 unexpectedly.
-// try (TransferableGraphFileReader reader = new TransferableGraphFileReader(is)) {
+// try (TransferableGraphFileReader reader = new TransferableGraphFileReader(is)) {
// return reader.readTG();
// }
return DataContainers.readFile(new DataInputStream(is), handlers);
private static Path getInstanceLocation() throws CoreException, IOException {
Location l = Platform.getInstanceLocation();
- if (l == null)
- throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
- "Workspace not defined. Use -data <path> argument to define where to place the baselining workspace."));
-
- Location instanceLoc = Platform.getInstanceLocation();
- if (instanceLoc == null || instanceLoc.isReadOnly())
+ if (l == null || l.isReadOnly())
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
"Workspace not defined. Use -data <path> argument to define where to place the baselining workspace."));
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;
resetDatabase(monitor);
}
- public boolean handleBaselineDatabase() throws PlatformException {
+ private static Path tryGetInstallLocation() {
+ Location l = Platform.getInstallLocation();
+ return l == null ? null : new File(l.getURL().getPath()).toPath();
+ }
+
+ private Path resolveBaselineFile() throws PlatformException {
+ String dbBaselineArchive = System.getProperty("org.simantics.db.baseline", null);
+ if (dbBaselineArchive == null)
+ return null;
+
+ Path baseline = Paths.get(dbBaselineArchive);
+ if (baseline.isAbsolute()) {
+ if (!Files.isRegularFile(baseline))
+ throw new PlatformException("Specified database baseline archive " + baseline
+ + " does not exist. Cannot initialize workspace database from baseline.");
+ return baseline;
+ }
+
+ // Relative path resolution order:
+ // 1. from the platform "install location"
+ // 2. from working directory
+ Path installLocation = tryGetInstallLocation();
+ if (installLocation != null) {
+ Path installedBaseline = installLocation.resolve(dbBaselineArchive);
+ if (Files.isRegularFile(installedBaseline))
+ return installedBaseline;
+ }
+ if (!Files.isRegularFile(baseline))
+ throw new PlatformException("Specified database baseline archive " + baseline
+ + " does not exist in either the install location (" + installLocation
+ + ") or the working directory (" + Paths.get(".").toAbsolutePath()
+ + "). Cannot initialize workspace database.");
+ return null;
+ }
+
+ private boolean handleBaselineDatabase() throws PlatformException {
Path workspaceLocation = Platform.getLocation().toFile().toPath();
Path baselineIndicatorFile = workspaceLocation.resolve(".baselined");
if (Files.isRegularFile(baselineIndicatorFile)) {
return true;
}
- String dbBaselineArchive = System.getProperty("org.simantics.db.baseline", null);
- if (dbBaselineArchive == null)
+ Path baseline = resolveBaselineFile();
+ if (baseline == null)
return false;
- Path baseline = Paths.get(dbBaselineArchive);
- if (!Files.isRegularFile(baseline))
- throw new PlatformException("Specified database baseline archive " + baseline + " does not exist. Cannot initialize workspace database.");
-
DatabaseBaselines.validateBaselineFile(baseline);
DatabaseBaselines.validateWorkspaceForBaselineInitialization(workspaceLocation);
DatabaseBaselines.initializeWorkspaceWithBaseline(baseline, workspaceLocation, baselineIndicatorFile);