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