--- /dev/null
+package org.simantics.graph.representation;\r
+\r
+import java.io.DataInput;\r
+import java.io.DataInputStream;\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.nio.ByteBuffer;\r
+import java.nio.channels.ReadableByteChannel;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Datatypes;\r
+import org.simantics.databoard.binding.error.RuntimeDatatypeConstructionException;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.container.DataContainers;\r
+import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;\r
+import org.simantics.databoard.serialization.Serializer;\r
+import org.simantics.databoard.type.Datatype;\r
+\r
+\r
+final public class TransferableGraphFileReader extends ByteFileReader {\r
+\r
+ InputStream in = new InputStream() {\r
+\r
+ @Override\r
+ public int read() throws IOException {\r
+ return getByte();\r
+ }\r
+ \r
+ @Override\r
+ public int read(byte[] b) throws IOException {\r
+ // FIXME not correctly implemented \r
+ System.arraycopy(safeBytes(b.length), 0, b, 0, b.length);\r
+ return b.length;\r
+ }\r
+ \r
+ @Override\r
+ public int read(byte[] b, int off, int len) throws IOException {\r
+ // FIXME not correctly implemented\r
+ System.arraycopy(safeBytes(len), 0, b, off, len);\r
+ return len;\r
+ }\r
+ \r
+ };\r
+ \r
+ \r
+ final static class InputChannel implements ReadableByteChannel {\r
+\r
+ final private InputStream stream;\r
+ \r
+ public InputChannel(InputStream stream) {\r
+ this.stream = stream;\r
+ }\r
+ \r
+ @Override\r
+ public boolean isOpen() {\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public void close() throws IOException {\r
+ }\r
+\r
+ @Override\r
+ public int read(ByteBuffer dst) throws IOException {\r
+ int pos = dst.position();\r
+ int limit = dst.limit();\r
+ int i=stream.read(dst.array(), pos, limit-pos);\r
+ //System.err.println("Read " + i + " (expected " + dst.array().length + ")");\r
+ return i;\r
+ }\r
+ \r
+ }\r
+ \r
+ private static boolean init = true;\r
+ \r
+ final private static int SIZE = 1<<18;\r
+ final private static int HEADER = headerSize();\r
+ final private int header;\r
+ \r
+ public TransferableGraphFileReader(File file) throws IOException {\r
+ super(file, SIZE);\r
+ if(init) {\r
+ init=false;\r
+ TransferableGraphFileReader r = new TransferableGraphFileReader(file, 0);\r
+ for(int i=0;i<40000;i++) r.readTG();\r
+ }\r
+ this.header = HEADER;\r
+ }\r
+ \r
+ public TransferableGraphFileReader(InputStream stream) throws IOException {\r
+ super(null, new InputChannel(stream), SIZE);\r
+ if(init) {\r
+ init=false;\r
+ TransferableGraphFileReader r = new TransferableGraphFileReader(stream, 0);\r
+ for(int i=0;i<40000;i++) r.readTG();\r
+ }\r
+ this.header = 0;\r
+ }\r
+\r
+ public TransferableGraphFileReader(ReadableByteChannel channel) throws IOException {\r
+ super(null, channel, SIZE);\r
+ if(init) {\r
+ init=false;\r
+ TransferableGraphFileReader r = new TransferableGraphFileReader(channel, 0);\r
+ for(int i=0;i<40000;i++) r.readTG();\r
+ }\r
+ this.header = 0;\r
+ }\r
+\r
+ public TransferableGraphFileReader(ReadableByteChannel channel, int size) throws IOException {\r
+ super(null, channel, SIZE);\r
+ this.header = 0;\r
+ }\r
+\r
+ public TransferableGraphFileReader(InputStream stream, int size) throws IOException {\r
+ super(null, new InputChannel(stream), size);\r
+ this.header = 0;\r
+ }\r
+\r
+ public TransferableGraphFileReader(File file, int size) throws IOException {\r
+ super(file, size);\r
+ this.header = HEADER;\r
+ }\r
+\r
+ private static int headerSize() {\r
+ try {\r
+ return Bindings.getSerializerUnchecked(Datatype.class).serialize(Datatypes.getDatatypeUnchecked(TransferableGraph1.class)).length;\r
+ } catch (RuntimeSerializerConstructionException e) {\r
+ throw new Error("Failed to determine TransferableGraph1 header size. ", e);\r
+ } catch (RuntimeDatatypeConstructionException e) {\r
+ throw new Error("Failed to determine TransferableGraph1 header size. ", e);\r
+ } catch (IOException e) {\r
+ throw new Error("Failed to determine TransferableGraph1 header size. ", e);\r
+ } \r
+ }\r
+ \r
+ public TransferableGraph1 readTG() throws IOException {\r
+\r
+ if(getSize() == 0) return null;\r
+ \r
+// long start = System.nanoTime();\r
+\r
+ final byte[] bytes = getBytes();\r
+ \r
+// byteIndex = header;\r
+\r
+ DataInputStream dis = new DataInputStream(in);\r
+\r
+ // Header\r
+ DataContainers.readHeader(dis);\r
+ \r
+ // Content variant data type\r
+ Bindings.getSerializerUnchecked(Datatype.class).deserialize((DataInput)dis);\r
+\r
+ int resourceCount = safeInt();\r
+ \r
+ List<Object> idcontext = new ArrayList<Object>(); \r
+ dis = new DataInputStream(in);\r
+ Extensions extensions = (Extensions)Bindings.getSerializerUnchecked(Extensions.class).deserialize((DataInput)dis, idcontext);\r
+ \r
+ int identities = safeInt();\r
+ Identity[] ids = new Identity[identities];\r
+\r
+// System.err.println("rc: " + resourceCount);\r
+// System.err.println("ids: " + identities);\r
+ \r
+// long duration = System.nanoTime() - start;\r
+// System.err.println("start in " + 1e-9*duration + "s.");\r
+// start = System.nanoTime();\r
+ \r
+ for(int i=0;i<identities;i++) {\r
+ int rid = safeInt();\r
+ byte type = bytes[byteIndex++];\r
+ // External\r
+ if(type == 1) {\r
+ \r
+ int parent = safeInt();\r
+ int nameLen = getDynamicUInt32();\r
+ \r
+ if(byteIndex+nameLen < SIZE) {\r
+ ids[i] = new Identity(rid, new External(parent, utf(bytes, byteIndex, byteIndex + nameLen)));\r
+ byteIndex += nameLen;\r
+ } else {\r
+ ids[i] = new Identity(rid, new External(parent, utf(safeBytes(nameLen), 0, nameLen)));\r
+ }\r
+ \r
+ } \r
+ // Internal\r
+ else if(type == 3) {\r
+ \r
+ int parent = safeInt();\r
+ int nameLen = getDynamicUInt32();\r
+ if(byteIndex+nameLen < SIZE) {\r
+ ids[i] = new Identity(rid, new Internal(parent, utf(bytes, byteIndex, byteIndex + nameLen)));\r
+ byteIndex += nameLen;\r
+ } else {\r
+ ids[i] = new Identity(rid, new Internal(parent, utf(safeBytes(nameLen), 0, nameLen)));\r
+ }\r
+ \r
+ }\r
+ // Root\r
+ else if(type == 0) {\r
+ int nameLen = getDynamicUInt32();\r
+ String name = utf(safeBytes(nameLen), 0, nameLen);\r
+ int nameLen2 = getDynamicUInt32();\r
+ String rType = utf(safeBytes(nameLen2), 0, nameLen2);\r
+ ids[i] = new Identity(rid, new Root(name, rType));\r
+\r
+ } else if(type == 2) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ }\r
+\r
+// for(Identity id : ids) System.err.println("id: " + id);\r
+\r
+ \r
+// duration = System.nanoTime() - start;\r
+// System.err.println("ids in " + 1e-9*duration + "s.");\r
+// start = System.nanoTime();\r
+\r
+ int stmLength = safeInt();\r
+// System.err.println("statements: " + stmLength + " (" + byteIndex + ")");\r
+ \r
+ int[] statements = new int[stmLength];\r
+\r
+ for(int stmIndex=0;stmIndex<stmLength;) {\r
+\r
+ statements[stmIndex++] = safeInt();\r
+ \r
+ // Cached bytes \r
+ int avail = (SIZE-byteIndex) >> 2;\r
+ int allowed = Math.min(stmLength-stmIndex, avail);\r
+ for(int index = byteIndex, i=0;i<allowed;i++) {\r
+ statements[stmIndex++] = ((bytes[index++]&0xff)<<24) | ((bytes[index++]&0xff)<<16) | ((bytes[index++]&0xff)<<8) | ((bytes[index++]&0xff)); \r
+ }\r
+ byteIndex += allowed<<2;\r
+ \r
+ }\r
+\r
+// duration = System.nanoTime() - start;\r
+// System.err.println("stms in " + 1e-9*duration + "s.");\r
+// \r
+// start = System.nanoTime();\r
+\r
+ int valueLength = safeInt();\r
+// System.err.println("values: " + valueLength + " (" + byteIndex + ")");\r
+\r
+ Value[] values = new Value[valueLength]; \r
+\r
+ Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);\r
+ \r
+ idcontext = new ArrayList<Object>(); \r
+ dis = new DataInputStream(in);\r
+ \r
+ for(int i=0;i<valueLength;i++) {\r
+ int resource = safeInt();\r
+ Variant value = (Variant)variantSerializer\r
+ .deserialize((DataInput)dis, idcontext);\r
+ values[i] = new Value(resource, value);\r
+ \r
+ //System.err.println("read variant[" + resource + "]: " + value.toString().substring(0, Math.min(100, value.toString().length())));\r
+ \r
+ }\r
+\r
+ \r
+// duration = System.nanoTime() - start;\r
+// System.err.println("values in " + 1e-9*duration + "s.");\r
+ \r
+ return new TransferableGraph1(resourceCount, ids, statements, values, extensions.map);\r
+\r
+ }\r
+ \r
+ public static void main(String[] args) {\r
+\r
+ try {\r
+ \r
+ File file = new File("c:/users/antti villberg/desktop/test.apros");\r
+ TransferableGraphFileReader reader = new TransferableGraphFileReader(file, SIZE);\r
+ reader = new TransferableGraphFileReader(file);\r
+ long s = System.nanoTime();\r
+ reader.readTG();\r
+ long d = System.nanoTime() - s;\r
+ System.err.println("Duration=" + 1e-9*d + "s.");\r
+ \r
+ \r
+ } catch (Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+ \r
+ }\r
+\r
+}\r