[Tmf][Ctf] Add descriptive fail to import messages.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / Metadata.java
CommitLineData
866e5b51
FC
1/*******************************************************************************
2 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.ctf.core.trace;
14
15import java.io.File;
16import java.io.FileInputStream;
17import java.io.FileNotFoundException;
18import java.io.FileReader;
19import java.io.IOException;
20import java.io.Reader;
21import java.io.StringReader;
22import java.nio.ByteBuffer;
23import java.nio.ByteOrder;
24import java.nio.channels.FileChannel;
25import java.util.Arrays;
26import java.util.UUID;
27
28import org.antlr.runtime.ANTLRReaderStream;
29import org.antlr.runtime.CommonTokenStream;
a94410d9 30import org.antlr.runtime.MismatchedTokenException;
866e5b51
FC
31import org.antlr.runtime.RecognitionException;
32import org.antlr.runtime.tree.CommonTree;
866e5b51
FC
33import org.eclipse.linuxtools.ctf.parser.CTFLexer;
34import org.eclipse.linuxtools.ctf.parser.CTFParser;
35import org.eclipse.linuxtools.ctf.parser.CTFParser.parse_return;
ce2388e0
FC
36import org.eclipse.linuxtools.internal.ctf.core.event.metadata.IOStructGen;
37import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException;
866e5b51
FC
38
39/**
d37aaa7f 40 * The CTF trace metadata file
791072b0 41 *
d37aaa7f
FC
42 * @version 1.0
43 * @author Matthew Khouzam
44 * @author Simon Marchi
866e5b51
FC
45 */
46public class Metadata {
47
48 // ------------------------------------------------------------------------
49 // Constants
50 // ------------------------------------------------------------------------
51
52 /**
53 * Name of the metadata file in the trace directory
54 */
07002e0a 55 final static String METADATA_FILENAME = "metadata"; //$NON-NLS-1$
866e5b51
FC
56
57 /**
58 * Size of the metadata packet header, in bytes, computed by hand.
59 */
07002e0a 60 final static int METADATA_PACKET_HEADER_SIZE = 37;
866e5b51
FC
61
62 // ------------------------------------------------------------------------
63 // Attributes
64 // ------------------------------------------------------------------------
65
66 /**
67 * Reference to the metadata file
68 */
69 private File metadataFile = null;
70
71 /**
72 * Byte order as detected when reading the TSDL magic number.
73 */
74 private ByteOrder detectedByteOrder = null;
75
76 /**
77 * The trace file to which belongs this metadata file.
78 */
79 private CTFTrace trace = null;
80
81 // ------------------------------------------------------------------------
82 // Constructors
83 // ------------------------------------------------------------------------
84
85 /**
86 * Constructs a Metadata object.
aa572e22 87 *
866e5b51
FC
88 * @param trace
89 * The trace to which belongs this metadata file.
90 */
91 public Metadata(CTFTrace trace) {
92 this.trace = trace;
93
94 /* Path of metadata file = trace directory path + metadata filename */
95 String metadataPath = trace.getTraceDirectory().getPath()
96 + Utils.SEPARATOR + METADATA_FILENAME;
97
98 /* Create a file reference to the metadata file */
99 metadataFile = new File(metadataPath);
100 }
101
102 // ------------------------------------------------------------------------
103 // Getters/Setters/Predicates
104 // ------------------------------------------------------------------------
105
106 /**
107 * Returns the ByteOrder that was detected while parsing the metadata.
aa572e22 108 *
866e5b51
FC
109 * @return The byte order.
110 */
111 public ByteOrder getDetectedByteOrder() {
112 return detectedByteOrder;
113 }
114
115 // ------------------------------------------------------------------------
116 // Operations
117 // ------------------------------------------------------------------------
118
119 /**
120 * Parse the metadata file.
aa572e22 121 *
866e5b51 122 * @throws CTFReaderException
be6df2d8 123 * If there was a problem parsing the metadata
866e5b51
FC
124 */
125 public void parse() throws CTFReaderException {
68c9980d
AM
126 CTFReaderException tempException = null;
127
128 FileInputStream fis = null;
129 FileChannel metadataFileChannel = null;
866e5b51
FC
130
131 /*
132 * Reader. It will contain a StringReader if we are using packet-based
133 * metadata and it will contain a FileReader if we have text-based
134 * metadata.
135 */
136 Reader metadataTextInput = null;
137
68c9980d
AM
138 try {
139 fis = new FileInputStream(metadataFile);
140 metadataFileChannel = fis.getChannel();
866e5b51 141
68c9980d
AM
142 /* Check if metadata is packet-based */
143 if (isPacketBased(metadataFileChannel)) {
144 /* Create StringBuffer to receive metadata text */
145 StringBuffer metadataText = new StringBuffer();
866e5b51 146
866e5b51 147 /*
68c9980d
AM
148 * Read metadata packet one by one, appending the text to the
149 * StringBuffer
866e5b51 150 */
68c9980d
AM
151 MetadataPacketHeader packetHeader = readMetadataPacket(
152 metadataFileChannel, metadataText);
153 while (packetHeader != null) {
154 packetHeader = readMetadataPacket(metadataFileChannel,
155 metadataText);
156 }
157
158 /* Wrap the metadata string with a StringReader */
159 metadataTextInput = new StringReader(metadataText.toString());
160 } else {
161 /* Wrap the metadata file with a FileReader */
162 metadataTextInput = new FileReader(metadataFile);
866e5b51 163 }
866e5b51 164
791072b0 165 CommonTree tree = createAST(metadataTextInput);
68c9980d
AM
166
167 /* Generate IO structures (declarations) */
168 IOStructGen gen = new IOStructGen(tree, trace);
169 gen.generate();
170
171 } catch (FileNotFoundException e) {
172 tempException = new CTFReaderException("Cannot find metadata file!"); //$NON-NLS-1$
173 } catch (IOException e) {
174 /* This would indicate a problem with the ANTLR library... */
175 tempException = new CTFReaderException(e);
176 } catch (ParseException e) {
177 tempException = new CTFReaderException(e);
a94410d9
MK
178 } catch (MismatchedTokenException e) {
179 tempException = new CTFReaderException(e);
866e5b51 180 } catch (RecognitionException e) {
68c9980d 181 tempException = new CTFReaderException(e);
866e5b51 182 }
866e5b51 183
68c9980d
AM
184 /* Ghetto resource management. Java 7 will deliver us from this... */
185 if (metadataTextInput != null) {
186 try {
187 metadataTextInput.close();
188 } catch (IOException e) {
aa572e22 189 // Do nothing
68c9980d
AM
190 }
191 }
192 if (metadataFileChannel != null) {
193 try {
194 metadataFileChannel.close();
195 } catch (IOException e) {
aa572e22 196 // Do nothing
68c9980d
AM
197 }
198 }
199 if (fis != null) {
200 try {
201 fis.close();
202 } catch (IOException e) {
aa572e22 203 // Do nothing
68c9980d
AM
204 }
205 }
206
207 if (tempException != null) {
208 throw tempException;
866e5b51
FC
209 }
210 }
211
791072b0
MK
212 private static CommonTree createAST(Reader metadataTextInput) throws IOException,
213 RecognitionException {
214 /* Create an ANTLR reader */
215 ANTLRReaderStream antlrStream;
216 antlrStream = new ANTLRReaderStream(metadataTextInput);
217
218 /* Parse the metadata text and get the AST */
219 CTFLexer ctfLexer = new CTFLexer(antlrStream);
220 CommonTokenStream tokens = new CommonTokenStream(ctfLexer);
221 CTFParser ctfParser = new CTFParser(tokens, false);
222 parse_return ret;
223
224 ret = ctfParser.parse();
225
226 CommonTree tree = (CommonTree) ret.getTree();
227 return tree;
228 }
229
866e5b51
FC
230 /**
231 * Determines whether the metadata file is packet-based by looking at the
232 * TSDL magic number. If it is packet-based, it also gives information about
233 * the endianness of the trace using the detectedByteOrder attribute.
aa572e22 234 *
866e5b51
FC
235 * @param metadataFileChannel
236 * FileChannel of the metadata file.
237 * @return True if the metadata is packet-based.
238 * @throws CTFReaderException
239 */
240 private boolean isPacketBased(FileChannel metadataFileChannel)
241 throws CTFReaderException {
242 /*
243 * Create a ByteBuffer to read the TSDL magic number (default is big
244 * endian)
245 */
246 ByteBuffer magicByteBuffer = ByteBuffer.allocate(Utils.TSDL_MAGIC_LEN);
247
248 /* Read without changing file position */
249 try {
250 metadataFileChannel.read(magicByteBuffer, 0);
251 } catch (IOException e) {
a94410d9 252 throw new CTFReaderException("Unable to read metadata file channel."); //$NON-NLS-1$
866e5b51
FC
253 }
254
255 /* Get the first int from the file */
256 int magic = magicByteBuffer.getInt(0);
257
258 /* Check if it matches */
259 if (Utils.TSDL_MAGIC == magic) {
260 detectedByteOrder = ByteOrder.BIG_ENDIAN;
261 return true;
262 }
263
264 /* Try the same thing, but with little endian */
265 magicByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
266 magic = magicByteBuffer.getInt(0);
267
268 if (Utils.TSDL_MAGIC == magic) {
269 detectedByteOrder = ByteOrder.LITTLE_ENDIAN;
270 return true;
271 }
272
273 return false;
274 }
275
276 /**
277 * Reads a metadata packet from the given metadata FileChannel, do some
278 * basic validation and append the text to the StringBuffer.
aa572e22 279 *
866e5b51
FC
280 * @param metadataFileChannel
281 * Metadata FileChannel
282 * @param metadataText
283 * StringBuffer to which the metadata text will be appended.
284 * @return A structure describing the header of the metadata packet, or null
285 * if the end of the file is reached.
286 * @throws CTFReaderException
287 */
288 private MetadataPacketHeader readMetadataPacket(
289 FileChannel metadataFileChannel, StringBuffer metadataText)
290 throws CTFReaderException {
291 /* Allocate a ByteBuffer for the header */
292 ByteBuffer headerByteBuffer = ByteBuffer.allocate(METADATA_PACKET_HEADER_SIZE);
293
294 /* Read the header */
295 int nbBytesRead;
296 try {
297 nbBytesRead = metadataFileChannel.read(headerByteBuffer);
298 } catch (IOException e) {
299 throw new CTFReaderException("Error reading the metadata header."); //$NON-NLS-1$
300 }
301
302 /* Return null if EOF */
303 if (nbBytesRead < 0) {
304 return null;
305 }
306
307 /* Set ByteBuffer's position to 0 */
308 headerByteBuffer.position(0);
309
310 /* Use byte order that was detected with the magic number */
311 headerByteBuffer.order(detectedByteOrder);
312
313 assert (nbBytesRead == METADATA_PACKET_HEADER_SIZE);
314
315 MetadataPacketHeader header = new MetadataPacketHeader();
316
317 /* Read from the ByteBuffer */
318 header.magic = headerByteBuffer.getInt();
319 headerByteBuffer.get(header.uuid);
320 header.checksum = headerByteBuffer.getInt();
321 header.contentSize = headerByteBuffer.getInt();
322 header.packetSize = headerByteBuffer.getInt();
323 header.compressionScheme = headerByteBuffer.get();
324 header.encryptionScheme = headerByteBuffer.get();
325 header.checksumScheme = headerByteBuffer.get();
326 header.ctfMajorVersion = headerByteBuffer.get();
327 header.ctfMinorVersion = headerByteBuffer.get();
328
329 /* Check TSDL magic number */
330 if (header.magic != Utils.TSDL_MAGIC) {
331 throw new CTFReaderException("TSDL magic number does not match"); //$NON-NLS-1$
332 }
333
334 /* Check UUID */
335 UUID uuid = Utils.makeUUID(header.uuid);
336 if (!trace.UUIDIsSet()) {
337 trace.setUUID(uuid);
338 } else {
339 if (!trace.getUUID().equals(uuid)) {
340 throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
341 }
342 }
343
344 /* Extract the text from the packet */
345 int payloadSize = ((header.contentSize / 8) - METADATA_PACKET_HEADER_SIZE);
346 int skipSize = (header.packetSize - header.contentSize) / 8;
347
348 /* Read the payload + the padding in a ByteBuffer */
349 ByteBuffer payloadByteBuffer = ByteBuffer.allocateDirect(payloadSize
350 + skipSize);
351 try {
352 metadataFileChannel.read(payloadByteBuffer);
353 } catch (IOException e) {
a94410d9 354 throw new CTFReaderException("Error reading metadata packet payload."); //$NON-NLS-1$
866e5b51
FC
355 }
356 payloadByteBuffer.rewind();
357
358 /* Read only the payload from the ByteBuffer into a byte array */
359 byte payloadByteArray[] = new byte[payloadByteBuffer.remaining()];
360 payloadByteBuffer.get(payloadByteArray, 0, payloadSize);
361
362 /* Convert the byte array to a String */
363 String str = new String(payloadByteArray, 0, payloadSize);
364
365 /* Append it to the existing metadata */
366 metadataText.append(str);
367
368 return header;
369 }
370
371 static class MetadataPacketHeader {
372
373 public int magic;
374 public byte uuid[] = new byte[16];
375 public int checksum;
376 public int contentSize;
377 public int packetSize;
378 public byte compressionScheme;
379 public byte encryptionScheme;
380 public byte checksumScheme;
381 public byte ctfMajorVersion;
382 public byte ctfMinorVersion;
383
384 @Override
385 public String toString() {
386 /* Only for debugging, shouldn't be externalized */
e291b8c8 387 /* Therefore it cannot be covered by test cases */
866e5b51
FC
388 return "MetadataPacketHeader [magic=0x" //$NON-NLS-1$
389 + Integer.toHexString(magic) + ", uuid=" //$NON-NLS-1$
390 + Arrays.toString(uuid) + ", checksum=" + checksum //$NON-NLS-1$
391 + ", contentSize=" + contentSize + ", packetSize=" //$NON-NLS-1$ //$NON-NLS-2$
392 + packetSize + ", compressionScheme=" + compressionScheme //$NON-NLS-1$
393 + ", encryptionScheme=" + encryptionScheme //$NON-NLS-1$
394 + ", checksumScheme=" + checksumScheme //$NON-NLS-1$
395 + ", ctfMajorVersion=" + ctfMajorVersion //$NON-NLS-1$
396 + ", ctfMinorVersion=" + ctfMinorVersion + ']'; //$NON-NLS-1$
397 }
398
399 }
400}
This page took 0.046257 seconds and 5 git commands to generate.