]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphFileReader.java
ae1ec711ce676e9d3932cbbbc10485601cbb2f1d
[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<Object>(); 
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                         }
219
220                 }
221
222 //              for(Identity id : ids) LOGGER.warn("id: " + id);
223
224                 
225 //              duration = System.nanoTime() - start;
226 //              LOGGER.warn("ids in " + 1e-9*duration + "s.");
227 //              start = System.nanoTime();
228
229                 int stmLength = safeInt();
230 //              LOGGER.warn("statements: " + stmLength + " (" + byteIndex + ")");
231                 
232                 int[] statements = new int[stmLength];
233
234                 for(int stmIndex=0;stmIndex<stmLength;) {
235
236                         statements[stmIndex++] = safeInt();
237                         
238                         // Cached bytes 
239                         int avail = (SIZE-byteIndex) >> 2;
240                         int allowed = Math.min(stmLength-stmIndex, avail);
241                         for(int index = byteIndex, i=0;i<allowed;i++) {
242                                 statements[stmIndex++] = ((bytes[index++]&0xff)<<24) | ((bytes[index++]&0xff)<<16) | ((bytes[index++]&0xff)<<8) | ((bytes[index++]&0xff));                              
243                         }
244                         byteIndex += allowed<<2;
245                         
246                 }
247
248 //              duration = System.nanoTime() - start;
249 //              LOGGER.warn("stms in " + 1e-9*duration + "s.");
250 //              
251 //              start = System.nanoTime();
252
253                 int valueLength = safeInt();
254 //              LOGGER.warn("values: " + valueLength + " (" + byteIndex + ")");
255
256                 Value[] values = new Value[valueLength]; 
257
258                 Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);
259                 
260                 idcontext = new ArrayList<Object>(); 
261                 dis = new DataInputStream(in);
262                 
263                 for(int i=0;i<valueLength;i++) {
264                         int resource = safeInt();
265                         Variant value = (Variant)variantSerializer
266                                 .deserialize((DataInput)dis, idcontext);
267                         values[i] = new Value(resource, value);
268                         
269                         //LOGGER.warn("read variant[" + resource + "]: " + value.toString().substring(0, Math.min(100, value.toString().length())));
270                         
271                 }
272
273                 
274 //              duration = System.nanoTime() - start;
275 //              LOGGER.warn("values in " + 1e-9*duration + "s.");
276                 
277                 return new TransferableGraph1(resourceCount, ids, statements, values, extensions.map);
278
279         }
280         
281         public static void main(String[] args) {
282
283                 try {
284                         
285                         File file = new File("c:/users/antti villberg/desktop/test.apros");
286                         TransferableGraphFileReader reader = new TransferableGraphFileReader(file, SIZE);
287                         reader = new TransferableGraphFileReader(file);
288                         long s = System.nanoTime();
289                         reader.readTG();
290                         long d = System.nanoTime() - s;
291                         LOGGER.warn("Duration=" + 1e-9*d + "s.");
292                         
293                         
294                 } catch (Throwable t) {
295                         t.printStackTrace();
296                 }
297                 
298         }
299
300 }