ctf/tmf: allow multiple traces to be open with name clashing events
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / ctfadaptor / CtfTmfTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
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:
10 * Matthew Khouzam - Initial API and implementation
11 * Patrick Tasse - Updated for removal of context clone
12 * Geneviève Bastien - Added the createTimestamp function
13 *******************************************************************************/
14
15 package org.eclipse.linuxtools.tmf.core.ctfadaptor;
16
17 import java.nio.BufferOverflowException;
18 import java.nio.ByteBuffer;
19 import java.util.Map;
20
21 import org.eclipse.core.resources.IProject;
22 import org.eclipse.core.resources.IResource;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.Status;
25 import org.eclipse.linuxtools.ctf.core.event.CTFClock;
26 import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
27 import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
28 import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
29 import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
30 import org.eclipse.linuxtools.internal.tmf.core.Activator;
31 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
32 import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
33 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
34 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
35 import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
36 import org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser;
37 import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceProperties;
38 import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
39 import org.eclipse.linuxtools.tmf.core.trace.TraceValidationStatus;
40 import org.eclipse.linuxtools.tmf.core.trace.indexer.ITmfPersistentlyIndexable;
41 import org.eclipse.linuxtools.tmf.core.trace.indexer.ITmfTraceIndexer;
42 import org.eclipse.linuxtools.tmf.core.trace.indexer.TmfBTreeTraceIndexer;
43 import org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint;
44 import org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
45 import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
46
47 /**
48 * The CTf trace handler
49 *
50 * @version 1.0
51 * @author Matthew khouzam
52 */
53 public class CtfTmfTrace extends TmfTrace
54 implements ITmfEventParser, ITmfTraceProperties, ITmfPersistentlyIndexable {
55
56 // -------------------------------------------
57 // Constants
58 // -------------------------------------------
59 /**
60 * Default cache size for CTF traces
61 */
62 protected static final int DEFAULT_CACHE_SIZE = 50000;
63
64 /*
65 * The Ctf clock unique identifier field
66 */
67 private static final String CLOCK_HOST_PROPERTY = "uuid"; //$NON-NLS-1$
68 private static final int CONFIDENCE = 10;
69
70 // -------------------------------------------
71 // Fields
72 // -------------------------------------------
73
74 /* Reference to the CTF Trace */
75 private CTFTrace fTrace;
76
77 // -------------------------------------------
78 // TmfTrace Overrides
79 // -------------------------------------------
80 /**
81 * Method initTrace.
82 *
83 * @param resource
84 * The resource associated with this trace
85 * @param path
86 * The path to the trace file
87 * @param eventType
88 * The type of events that will be read from this trace
89 * @throws TmfTraceException
90 * If something went wrong while reading the trace
91 */
92 @Override
93 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType)
94 throws TmfTraceException {
95 /*
96 * Set the cache size. This has to be done before the call to super()
97 * because the super needs to know the cache size.
98 */
99 setCacheSize();
100
101 super.initTrace(resource, path, eventType);
102
103 try {
104 this.fTrace = new CTFTrace(path);
105 CtfIteratorManager.addTrace(this);
106 CtfTmfContext ctx;
107 /* Set the start and (current) end times for this trace */
108 ctx = (CtfTmfContext) seekEvent(0L);
109 CtfTmfEvent event = getNext(ctx);
110 if ((ctx.getLocation().equals(CtfIterator.NULL_LOCATION)) || (ctx.getCurrentEvent() == null)) {
111 /* Handle the case where the trace is empty */
112 this.setStartTime(TmfTimestamp.BIG_BANG);
113 } else {
114 final ITmfTimestamp curTime = event.getTimestamp();
115 this.setStartTime(curTime);
116 this.setEndTime(curTime);
117 }
118
119 } catch (final CTFReaderException e) {
120 /*
121 * If it failed at the init(), we can assume it's because the file
122 * was not found or was not recognized as a CTF trace. Throw into
123 * the new type of exception expected by the rest of TMF.
124 */
125 throw new TmfTraceException(e.getMessage(), e);
126 }
127 }
128
129 @Override
130 public synchronized void dispose() {
131 CtfIteratorManager.removeTrace(this);
132 if (fTrace != null) {
133 fTrace.dispose();
134 fTrace = null;
135 }
136 super.dispose();
137 }
138
139 /**
140 * {@inheritDoc}
141 * <p>
142 * The default implementation sets the confidence to 10 if the trace is a
143 * valid CTF trace.
144 */
145 @Override
146 public IStatus validate(final IProject project, final String path) {
147 IStatus validTrace = new TraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID);
148 try {
149 final CTFTrace temp = new CTFTrace(path);
150 if (!temp.majorIsSet()) {
151 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_MajorNotSet);
152 } else {
153 CTFTraceReader ctfTraceReader = new CTFTraceReader(temp);
154 if (!ctfTraceReader.hasMoreEvents()) {
155 // TODO: This will need an additional check when we support live traces
156 // because having no event is valid for a live trace
157 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_NoEvent);
158 }
159 ctfTraceReader.dispose();
160 }
161 temp.dispose();
162 } catch (final CTFReaderException e) {
163 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError +": " + e.toString()); //$NON-NLS-1$
164 } catch (final BufferOverflowException e){
165 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError +": " + Messages.CtfTmfTrace_BufferOverflowErrorMessage); //$NON-NLS-1$
166 }
167
168 return validTrace;
169 }
170
171 /**
172 * Method getCurrentLocation. This is not applicable in CTF
173 *
174 * @return null, since the trace has no knowledge of the current location
175 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getCurrentLocation()
176 * @since 3.0
177 */
178 @Override
179 public ITmfLocation getCurrentLocation() {
180 return null;
181 }
182
183 /**
184 * @since 3.0
185 */
186 @Override
187 public double getLocationRatio(ITmfLocation location) {
188 final CtfLocation curLocation = (CtfLocation) location;
189 final CtfTmfContext context = new CtfTmfContext(this);
190 context.setLocation(curLocation);
191 context.seek(curLocation.getLocationInfo());
192 final CtfLocationInfo currentTime = ((CtfLocationInfo) context.getLocation().getLocationInfo());
193 final long startTime = getIterator(this, context).getStartTime();
194 final long endTime = getIterator(this, context).getEndTime();
195 return ((double) currentTime.getTimestamp() - startTime)
196 / (endTime - startTime);
197 }
198
199 /**
200 * Method seekEvent.
201 *
202 * @param location
203 * ITmfLocation<?>
204 * @return ITmfContext
205 * @since 3.0
206 */
207 @Override
208 public synchronized ITmfContext seekEvent(final ITmfLocation location) {
209 CtfLocation currentLocation = (CtfLocation) location;
210 CtfTmfContext context = new CtfTmfContext(this);
211 if (fTrace == null) {
212 context.setLocation(null);
213 context.setRank(ITmfContext.UNKNOWN_RANK);
214 return context;
215 }
216 /*
217 * The rank is set to 0 if the iterator seeks the beginning. If not, it
218 * will be set to UNKNOWN_RANK, since CTF traces don't support seeking
219 * by rank for now.
220 */
221 if (currentLocation == null) {
222 currentLocation = new CtfLocation(new CtfLocationInfo(0L, 0L));
223 context.setRank(0);
224 }
225 if (currentLocation.getLocationInfo() == CtfLocation.INVALID_LOCATION) {
226 currentLocation = new CtfLocation(getEndTime().getValue() + 1, 0L);
227 }
228 context.setLocation(currentLocation);
229 if (location == null) {
230 CtfTmfEvent event = getIterator(this, context).getCurrentEvent();
231 if (event != null) {
232 currentLocation = new CtfLocation(event.getTimestamp().getValue(), 0);
233 }
234 }
235 if (context.getRank() != 0) {
236 context.setRank(ITmfContext.UNKNOWN_RANK);
237 }
238 return context;
239 }
240
241 @Override
242 public synchronized ITmfContext seekEvent(double ratio) {
243 CtfTmfContext context = new CtfTmfContext(this);
244 if (fTrace == null) {
245 context.setLocation(null);
246 context.setRank(ITmfContext.UNKNOWN_RANK);
247 return context;
248 }
249 final long end = this.getEndTime().getValue();
250 final long start = this.getStartTime().getValue();
251 final long diff = end - start;
252 final long ratioTs = Math.round(diff * ratio) + start;
253 context.seek(ratioTs);
254 context.setRank(ITmfContext.UNKNOWN_RANK);
255 return context;
256 }
257
258 /**
259 * Method readNextEvent.
260 *
261 * @param context
262 * ITmfContext
263 * @return CtfTmfEvent
264 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getNext(ITmfContext)
265 */
266 @Override
267 public synchronized CtfTmfEvent getNext(final ITmfContext context) {
268 if (fTrace == null) {
269 return null;
270 }
271 CtfTmfEvent event = null;
272 if (context instanceof CtfTmfContext) {
273 if (context.getLocation() == null || CtfLocation.INVALID_LOCATION.equals(context.getLocation().getLocationInfo())) {
274 return null;
275 }
276 CtfTmfContext ctfContext = (CtfTmfContext) context;
277 event = ctfContext.getCurrentEvent();
278
279 if (event != null) {
280 updateAttributes(context, event.getTimestamp());
281 ctfContext.advance();
282 ctfContext.increaseRank();
283 }
284 }
285
286 return event;
287 }
288
289 /**
290 * gets the CTFtrace that this is wrapping
291 *
292 * @return the CTF trace
293 */
294 public CTFTrace getCTFTrace() {
295 return fTrace;
296 }
297
298 /**
299 * Ctf traces have a clock with a unique uuid that will be used to identify
300 * the host. Traces with the same clock uuid will be known to have been made
301 * on the same machine.
302 *
303 * Note: uuid is an optional field, it may not be there for a clock.
304 */
305 @Override
306 public String getHostId() {
307 CTFClock clock = getCTFTrace().getClock();
308 if (clock != null) {
309 String clockHost = (String) clock.getProperty(CLOCK_HOST_PROPERTY);
310 if (clockHost != null) {
311 return clockHost;
312 }
313 }
314 return super.getHostId();
315 }
316
317 // -------------------------------------------
318 // ITmfTraceProperties
319 // -------------------------------------------
320
321 /**
322 * @since 2.0
323 */
324 @Override
325 public Map<String, String> getTraceProperties() {
326 return fTrace.getEnvironment();
327 }
328
329 // -------------------------------------------
330 // Clocks
331 // -------------------------------------------
332
333 /**
334 * gets the clock offset
335 *
336 * @return the clock offset in ns
337 */
338 public long getOffset() {
339 if (fTrace != null) {
340 return fTrace.getOffset();
341 }
342 return 0;
343 }
344
345 /**
346 * Returns whether or not an event is in the metadata of the trace,
347 * therefore if it can possibly be in the trace. It does not verify whether
348 * or not the event is actually in the trace
349 *
350 * @param eventName
351 * The name of the event to check
352 * @return Whether the event is in the metadata or not
353 * @since 2.1
354 */
355 public boolean hasEvent(final String eventName) {
356 Map<Long, IEventDeclaration> events = fTrace.getEvents(0L);
357 if (events != null) {
358 for (IEventDeclaration decl : events.values()) {
359 if (decl.getName().equals(eventName)) {
360 return true;
361 }
362 }
363 }
364 return false;
365 }
366
367 /**
368 * Return whether all requested events are in the metadata
369 *
370 * @param names
371 * The array of events to check for
372 * @return Whether all events are in the metadata
373 * @since 2.1
374 */
375 public boolean hasAllEvents(String[] names) {
376 for (String name : names) {
377 if (!hasEvent(name)) {
378 return false;
379 }
380 }
381 return true;
382 }
383
384 /**
385 * Returns whether the metadata contains at least one of the requested
386 * events
387 *
388 * @param names
389 * The array of event names of check for
390 * @return Whether one of the event is present in trace metadata
391 * @since 2.1
392 */
393 public boolean hasAtLeastOneOfEvents(String[] names) {
394 for (String name : names) {
395 if (hasEvent(name)) {
396 return true;
397 }
398 }
399 return false;
400 }
401
402 // -------------------------------------------
403 // Parser
404 // -------------------------------------------
405
406 @Override
407 public CtfTmfEvent parseEvent(ITmfContext context) {
408 CtfTmfEvent event = null;
409 if (context instanceof CtfTmfContext) {
410 final ITmfContext tmpContext = seekEvent(context.getLocation());
411 event = getNext(tmpContext);
412 }
413 return event;
414 }
415
416 /**
417 * Sets the cache size for a CtfTmfTrace.
418 */
419 protected void setCacheSize() {
420 setCacheSize(DEFAULT_CACHE_SIZE);
421 }
422
423 // -------------------------------------------
424 // Helpers
425 // -------------------------------------------
426
427 private static CtfIterator getIterator(CtfTmfTrace trace, CtfTmfContext context) {
428 return CtfIteratorManager.getIterator(trace, context);
429 }
430
431 /**
432 * Get an iterator to the trace
433 *
434 * @return an iterator to the trace
435 * @since 2.0
436 */
437 public CtfIterator createIterator() {
438 try {
439 return new CtfIterator(this);
440 } catch (CTFReaderException e) {
441 Activator.logError(e.getMessage(), e);
442 }
443 return null;
444 }
445
446 // ------------------------------------------------------------------------
447 // Timestamp transformation functions
448 // ------------------------------------------------------------------------
449
450 /**
451 * @since 3.0
452 */
453 @Override
454 public CtfTmfTimestamp createTimestamp(long ts) {
455 return new CtfTmfTimestamp(getTimestampTransform().transform(ts));
456 }
457
458 private static int fCheckpointSize = -1;
459
460 /**
461 * @since 3.0
462 */
463 @Override
464 public synchronized int getCheckpointSize() {
465 if (fCheckpointSize == -1) {
466 TmfCheckpoint c = new TmfCheckpoint(new CtfTmfTimestamp(0), new CtfLocation(0, 0), 0);
467 ByteBuffer b = ByteBuffer.allocate(ITmfCheckpoint.MAX_SERIALIZE_SIZE);
468 b.clear();
469 c.serialize(b);
470 fCheckpointSize = b.position();
471 }
472
473 return fCheckpointSize;
474 }
475
476 @Override
477 protected ITmfTraceIndexer createIndexer(int interval) {
478 return new TmfBTreeTraceIndexer(this, interval);
479 }
480
481 /**
482 * @since 3.0
483 */
484 @Override
485 public ITmfLocation restoreLocation(ByteBuffer bufferIn) {
486 return new CtfLocation(bufferIn);
487 }
488 }
This page took 0.04387 seconds and 5 git commands to generate.