]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphFileReader.java
Fixed various bugs in TG readers
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / representation / TransferableGraphFileReader.java
1 package org.simantics.graph.representation;
2
3 import java.io.DataInput;
4 import java.io.DataInputStream;
5 import java.io.File;
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;
12
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;
23
24
25 final public class TransferableGraphFileReader extends ByteFileReader {
26
27     private static final Logger LOGGER = LoggerFactory.getLogger(TransferableGraphFileReader.class);
28
29         InputStream in = new InputStream() {
30
31         @Override
32         public int read() throws IOException {
33             return getByte();
34         }
35         
36         @Override
37         public int read(byte[] b) throws IOException {
38             // FIXME not correctly implemented                
39             System.arraycopy(safeBytes(b.length), 0, b, 0, b.length);
40             return b.length;
41         }
42         
43         @Override
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);
47             return len;
48         }
49             
50         };
51         
52         
53         final static class InputChannel implements ReadableByteChannel {
54
55                 final private InputStream stream;
56                 
57                 public InputChannel(InputStream stream) {
58                         this.stream = stream;
59                 }
60                 
61                 @Override
62                 public boolean isOpen() {
63                         return true;
64                 }
65
66                 @Override
67                 public void close() throws IOException {
68                 }
69
70                 @Override
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 + ")");
76                         return i;
77                 }
78                 
79         }
80         
81         private static boolean init = true;
82         
83         final private static int SIZE = 1<<18;
84         final private static int HEADER = headerSize();
85         final private int header;
86         
87         public TransferableGraphFileReader(File file) throws IOException {
88                 super(file, SIZE);
89                 if(init) {
90                         init=false;
91                         TransferableGraphFileReader r = new TransferableGraphFileReader(file, 0);
92                         for(int i=0;i<40000;i++) r.readTG();
93                 }
94                 this.header = HEADER;
95         }
96         
97         public TransferableGraphFileReader(InputStream stream) throws IOException {
98                 super(null, new InputChannel(stream), SIZE);
99                 if(init) {
100                         init=false;
101                         TransferableGraphFileReader r = new TransferableGraphFileReader(stream, 0);
102                         for(int i=0;i<40000;i++) r.readTG();
103                 }
104                 this.header = 0;
105         }
106
107         public TransferableGraphFileReader(ReadableByteChannel channel) throws IOException {
108                 super(null, channel, SIZE);
109                 if(init) {
110                         init=false;
111                         TransferableGraphFileReader r = new TransferableGraphFileReader(channel, 0);
112                         for(int i=0;i<40000;i++) r.readTG();
113                 }
114                 this.header = 0;
115         }
116
117         public TransferableGraphFileReader(ReadableByteChannel channel, int size) throws IOException {
118                 super(null, channel, SIZE);
119                 this.header = 0;
120         }
121
122         public TransferableGraphFileReader(InputStream stream, int size) throws IOException {
123                 super(null, new InputChannel(stream), size);
124                 this.header = 0;
125         }
126
127         public TransferableGraphFileReader(File file, int size) throws IOException {
128                 super(file, size);
129                 this.header = HEADER;
130         }
131
132         private static int headerSize() {
133                 try {
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);
141                 }               
142         }
143         
144         public TransferableGraph1 readTG() throws IOException {
145
146                 if(getSize() == 0) return null;
147                 
148 //              long start = System.nanoTime();
149
150                 final byte[] bytes = getBytes();
151                 
152 //              byteIndex = header;
153
154                 DataInputStream dis = new DataInputStream(in);
155
156                 // Header
157                 DataContainers.readHeader(dis);
158                 
159                 // Content variant data type
160                 Bindings.getSerializerUnchecked(Datatype.class).deserialize((DataInput)dis);
161
162                 int resourceCount = safeInt();
163                 
164                 List<Object> idcontext = new ArrayList<>(); 
165                 dis = new DataInputStream(in);
166                 Extensions extensions = (Extensions)Bindings.getSerializerUnchecked(Extensions.class).deserialize((DataInput)dis, idcontext);
167                 
168                 int identities = safeInt();
169                 Identity[] ids = new Identity[identities];
170
171 //              LOGGER.warn("rc: " + resourceCount);
172 //              LOGGER.warn("ids: " + identities);
173                 
174 //              long duration = System.nanoTime() - start;
175 //              LOGGER.warn("start in " + 1e-9*duration + "s.");
176 //              start = System.nanoTime();
177
178                 for(int i=0;i<identities;i++) {
179                         int rid = safeInt();
180                         byte type = bytes[byteIndex++];
181                         // External
182                         if(type == 1) {
183
184                                 int parent = safeInt();
185                                 int nameLen = getDynamicUInt32();
186
187                                 if(byteIndex+nameLen < SIZE) {
188                                         ids[i] = new Identity(rid, new External(parent, utf(bytes, byteIndex, byteIndex + nameLen)));
189                                         byteIndex += nameLen;
190                                 } else {
191                                         ids[i] = new Identity(rid, new External(parent, utf(safeBytes(nameLen), 0, nameLen)));
192                                 }
193
194                         } 
195                         // Internal
196                         else if(type == 3) {
197
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;
203                                 } else {
204                                         ids[i] = new Identity(rid, new Internal(parent, utf(safeBytes(nameLen), 0, nameLen)));
205                                 }
206                                 
207                         }
208                         // Root
209                         else if(type == 0) {
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));
215
216                         } else if(type == 2) {
217                                 throw new UnsupportedOperationException();
218                         } else {
219                                 throw new IllegalStateException();
220                         }
221
222                 }
223
224 //              for(Identity id : ids) LOGGER.warn("id: " + id);
225
226                 
227 //              duration = System.nanoTime() - start;
228 //              LOGGER.warn("ids in " + 1e-9*duration + "s.");
229 //              start = System.nanoTime();
230
231                 int stmLength = safeInt();
232 //              LOGGER.warn("statements: " + stmLength + " (" + byteIndex + ")");
233                 
234                 int[] statements = new int[stmLength];
235
236                 for(int stmIndex=0;stmIndex<stmLength;) {
237
238                         statements[stmIndex++] = safeInt();
239                         
240                         // Cached bytes 
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));                              
245                         }
246                         byteIndex += allowed<<2;
247                         
248                 }
249
250 //              duration = System.nanoTime() - start;
251 //              LOGGER.warn("stms in " + 1e-9*duration + "s.");
252 //              
253 //              start = System.nanoTime();
254
255                 int valueLength = safeInt();
256 //              LOGGER.warn("values: " + valueLength + " (" + byteIndex + ")");
257
258                 Value[] values = new Value[valueLength]; 
259
260                 Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);
261                 
262                 dis = new DataInputStream(in);
263                 
264                 for(int i=0;i<valueLength;i++) {
265                         int resource = safeInt();
266                         idcontext.clear();
267                         Variant value = (Variant)variantSerializer
268                                 .deserialize((DataInput)dis, idcontext);
269                         values[i] = new Value(resource, value);
270                         
271                         //LOGGER.warn("read variant[" + resource + "]: " + value.toString().substring(0, Math.min(100, value.toString().length())));
272                         
273                 }
274
275                 
276 //              duration = System.nanoTime() - start;
277 //              LOGGER.warn("values in " + 1e-9*duration + "s.");
278                 
279                 return new TransferableGraph1(resourceCount, ids, statements, values, extensions.map);
280
281         }
282         
283         public static void main(String[] args) {
284
285                 try {
286                         
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();
291                         reader.readTG();
292                         long d = System.nanoTime() - s;
293                         LOGGER.warn("Duration=" + 1e-9*d + "s.");
294                         
295                         
296                 } catch (Throwable t) {
297                         t.printStackTrace();
298                 }
299                 
300         }
301
302 }