1 package org.simantics.graph.representation;
3 import java.io.DataInput;
4 import java.io.DataInputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.nio.ByteBuffer;
9 import java.nio.channels.ReadableByteChannel;
10 import java.util.ArrayList;
11 import java.util.List;
13 import org.simantics.databoard.Bindings;
14 import org.simantics.databoard.Datatypes;
15 import org.simantics.databoard.binding.error.RuntimeDatatypeConstructionException;
16 import org.simantics.databoard.binding.mutable.Variant;
17 import org.simantics.databoard.container.DataContainers;
18 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
19 import org.simantics.databoard.serialization.Serializer;
20 import org.simantics.databoard.type.Datatype;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 final public class TransferableGraphFileReader extends ByteFileReader {
27 private static final Logger LOGGER = LoggerFactory.getLogger(TransferableGraphFileReader.class);
29 InputStream in = new InputStream() {
32 public int read() throws IOException {
37 public int read(byte[] b) throws IOException {
38 // FIXME not correctly implemented
39 System.arraycopy(safeBytes(b.length), 0, b, 0, b.length);
44 public int read(byte[] b, int off, int len) throws IOException {
45 // FIXME not correctly implemented
46 System.arraycopy(safeBytes(len), 0, b, off, len);
53 final static class InputChannel implements ReadableByteChannel {
55 final private InputStream stream;
57 public InputChannel(InputStream stream) {
62 public boolean isOpen() {
67 public void close() throws IOException {
71 public int read(ByteBuffer dst) throws IOException {
72 int pos = dst.position();
73 int limit = dst.limit();
74 int i=stream.read(dst.array(), pos, limit-pos);
75 //LOGGER.warn("Read " + i + " (expected " + dst.array().length + ")");
81 private static boolean init = true;
83 final private static int SIZE = 1<<18;
84 final private static int HEADER = headerSize();
85 final private int header;
87 public TransferableGraphFileReader(File file) throws IOException {
91 TransferableGraphFileReader r = new TransferableGraphFileReader(file, 0);
92 for(int i=0;i<40000;i++) r.readTG();
97 public TransferableGraphFileReader(InputStream stream) throws IOException {
98 super(null, new InputChannel(stream), SIZE);
101 TransferableGraphFileReader r = new TransferableGraphFileReader(stream, 0);
102 for(int i=0;i<40000;i++) r.readTG();
107 public TransferableGraphFileReader(ReadableByteChannel channel) throws IOException {
108 super(null, channel, SIZE);
111 TransferableGraphFileReader r = new TransferableGraphFileReader(channel, 0);
112 for(int i=0;i<40000;i++) r.readTG();
117 public TransferableGraphFileReader(ReadableByteChannel channel, int size) throws IOException {
118 super(null, channel, SIZE);
122 public TransferableGraphFileReader(InputStream stream, int size) throws IOException {
123 super(null, new InputChannel(stream), size);
127 public TransferableGraphFileReader(File file, int size) throws IOException {
129 this.header = HEADER;
132 private static int headerSize() {
134 return Bindings.getSerializerUnchecked(Datatype.class).serialize(Datatypes.getDatatypeUnchecked(TransferableGraph1.class)).length;
135 } catch (RuntimeSerializerConstructionException e) {
136 throw new Error("Failed to determine TransferableGraph1 header size. ", e);
137 } catch (RuntimeDatatypeConstructionException e) {
138 throw new Error("Failed to determine TransferableGraph1 header size. ", e);
139 } catch (IOException e) {
140 throw new Error("Failed to determine TransferableGraph1 header size. ", e);
144 public TransferableGraph1 readTG() throws IOException {
146 if(getSize() == 0) return null;
148 // long start = System.nanoTime();
150 final byte[] bytes = getBytes();
152 // byteIndex = header;
154 DataInputStream dis = new DataInputStream(in);
157 DataContainers.readHeader(dis);
159 // Content variant data type
160 Bindings.getSerializerUnchecked(Datatype.class).deserialize((DataInput)dis);
162 int resourceCount = safeInt();
164 List<Object> idcontext = new ArrayList<>();
165 dis = new DataInputStream(in);
166 Extensions extensions = (Extensions)Bindings.getSerializerUnchecked(Extensions.class).deserialize((DataInput)dis, idcontext);
168 int identities = safeInt();
169 Identity[] ids = new Identity[identities];
171 // LOGGER.warn("rc: " + resourceCount);
172 // LOGGER.warn("ids: " + identities);
174 // long duration = System.nanoTime() - start;
175 // LOGGER.warn("start in " + 1e-9*duration + "s.");
176 // start = System.nanoTime();
178 for(int i=0;i<identities;i++) {
180 byte type = bytes[byteIndex++];
184 int parent = safeInt();
185 int nameLen = getDynamicUInt32();
187 if(byteIndex+nameLen < SIZE) {
188 ids[i] = new Identity(rid, new External(parent, utf(bytes, byteIndex, byteIndex + nameLen)));
189 byteIndex += nameLen;
191 ids[i] = new Identity(rid, new External(parent, utf(safeBytes(nameLen), 0, nameLen)));
198 int parent = safeInt();
199 int nameLen = getDynamicUInt32();
200 if(byteIndex+nameLen < SIZE) {
201 ids[i] = new Identity(rid, new Internal(parent, utf(bytes, byteIndex, byteIndex + nameLen)));
202 byteIndex += nameLen;
204 ids[i] = new Identity(rid, new Internal(parent, utf(safeBytes(nameLen), 0, nameLen)));
210 int nameLen = getDynamicUInt32();
211 String name = utf(safeBytes(nameLen), 0, nameLen);
212 int nameLen2 = getDynamicUInt32();
213 String rType = utf(safeBytes(nameLen2), 0, nameLen2);
214 ids[i] = new Identity(rid, new Root(name, rType));
216 } else if(type == 2) {
217 throw new UnsupportedOperationException();
219 throw new IllegalStateException();
224 // for(Identity id : ids) LOGGER.warn("id: " + id);
227 // duration = System.nanoTime() - start;
228 // LOGGER.warn("ids in " + 1e-9*duration + "s.");
229 // start = System.nanoTime();
231 int stmLength = safeInt();
232 // LOGGER.warn("statements: " + stmLength + " (" + byteIndex + ")");
234 int[] statements = new int[stmLength];
236 for(int stmIndex=0;stmIndex<stmLength;) {
238 statements[stmIndex++] = safeInt();
241 int avail = (SIZE-byteIndex) >> 2;
242 int allowed = Math.min(stmLength-stmIndex, avail);
243 for(int index = byteIndex, i=0;i<allowed;i++) {
244 statements[stmIndex++] = ((bytes[index++]&0xff)<<24) | ((bytes[index++]&0xff)<<16) | ((bytes[index++]&0xff)<<8) | ((bytes[index++]&0xff));
246 byteIndex += allowed<<2;
250 // duration = System.nanoTime() - start;
251 // LOGGER.warn("stms in " + 1e-9*duration + "s.");
253 // start = System.nanoTime();
255 int valueLength = safeInt();
256 // LOGGER.warn("values: " + valueLength + " (" + byteIndex + ")");
258 Value[] values = new Value[valueLength];
260 Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);
262 dis = new DataInputStream(in);
264 for(int i=0;i<valueLength;i++) {
265 int resource = safeInt();
267 Variant value = (Variant)variantSerializer
268 .deserialize((DataInput)dis, idcontext);
269 values[i] = new Value(resource, value);
271 //LOGGER.warn("read variant[" + resource + "]: " + value.toString().substring(0, Math.min(100, value.toString().length())));
276 // duration = System.nanoTime() - start;
277 // LOGGER.warn("values in " + 1e-9*duration + "s.");
279 return new TransferableGraph1(resourceCount, ids, statements, values, extensions.map);
283 public static void main(String[] args) {
287 File file = new File("c:/users/antti villberg/desktop/test.apros");
288 TransferableGraphFileReader reader = new TransferableGraphFileReader(file, SIZE);
289 reader = new TransferableGraphFileReader(file);
290 long s = System.nanoTime();
292 long d = System.nanoTime() - s;
293 LOGGER.warn("Duration=" + 1e-9*d + "s.");
296 } catch (Throwable t) {