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