tmf.ctf: Move each CtfIteratorManager into its own trace object
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ctf.core / src / org / eclipse / tracecompass / tmf / ctf / core / CtfTmfTrace.java
CommitLineData
b1baa808 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
b1baa808
MK
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 *
ea271da6
PT
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Patrick Tasse - Updated for removal of context clone
e73a4ba5 12 * Geneviève Bastien - Added the createTimestamp function
b1baa808
MK
13 *******************************************************************************/
14
2bdf0193 15package org.eclipse.tracecompass.tmf.ctf.core;
a3fc8213 16
96c0f2af 17import java.nio.BufferOverflowException;
032ecd45 18import java.nio.ByteBuffer;
409bea20 19import java.util.ArrayList;
e600c338 20import java.util.Collections;
2db2b43a 21import java.util.HashMap;
409bea20 22import java.util.List;
299e494e 23import java.util.Map;
409bea20 24import java.util.Set;
299e494e 25
a3fc8213
AM
26import org.eclipse.core.resources.IProject;
27import org.eclipse.core.resources.IResource;
6fd3c6e9 28import org.eclipse.core.runtime.CoreException;
a94410d9
MK
29import org.eclipse.core.runtime.IStatus;
30import org.eclipse.core.runtime.Status;
f357bcd4
AM
31import org.eclipse.tracecompass.ctf.core.event.CTFClock;
32import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
33import org.eclipse.tracecompass.ctf.core.trace.CTFReaderException;
34import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
35import org.eclipse.tracecompass.ctf.core.trace.CTFTraceReader;
2bdf0193
AM
36import org.eclipse.tracecompass.internal.tmf.ctf.core.Activator;
37import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
38import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
2bdf0193 39import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
2bdf0193
AM
40import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
41import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
42import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
43import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
44import org.eclipse.tracecompass.tmf.core.trace.ITmfEventParser;
45import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceProperties;
46import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents;
47import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
48import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus;
49import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfPersistentlyIndexable;
50import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfTraceIndexer;
51import org.eclipse.tracecompass.tmf.core.trace.indexer.TmfBTreeTraceIndexer;
52import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint;
53import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
54import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
a3fc8213 55
409bea20
GB
56import com.google.common.collect.ImmutableSet;
57
9ac2eb62 58/**
d09f973b
FC
59 * The CTf trace handler
60 *
61 * @version 1.0
62 * @author Matthew khouzam
9ac2eb62 63 */
22307af3 64public class CtfTmfTrace extends TmfTrace
090c006e 65 implements ITmfEventParser, ITmfTraceProperties, ITmfPersistentlyIndexable,
409bea20 66 ITmfTraceWithPreDefinedEvents, AutoCloseable {
a3fc8213 67
a94410d9
MK
68 // -------------------------------------------
69 // Constants
70 // -------------------------------------------
324a6a4a
BH
71 /**
72 * Default cache size for CTF traces
73 */
74 protected static final int DEFAULT_CACHE_SIZE = 50000;
64c2cb4c 75
bb52f9bc
GB
76 /*
77 * The Ctf clock unique identifier field
78 */
79 private static final String CLOCK_HOST_PROPERTY = "uuid"; //$NON-NLS-1$
cd43d683 80 private static final int CONFIDENCE = 10;
bb52f9bc 81
a94410d9
MK
82 // -------------------------------------------
83 // Fields
84 // -------------------------------------------
a3fc8213 85
e600c338
AM
86 private final Map<String, CtfTmfEventType> fContainedEventTypes =
87 Collections.synchronizedMap(new HashMap<String, CtfTmfEventType>());
88
6a0ec7bc
AM
89 private final CtfIteratorManager fIteratorManager =
90 new CtfIteratorManager(this);
91
4b7c469f
MK
92 /* Reference to the CTF Trace */
93 private CTFTrace fTrace;
a3fc8213 94
a94410d9
MK
95 // -------------------------------------------
96 // TmfTrace Overrides
97 // -------------------------------------------
b1baa808
MK
98 /**
99 * Method initTrace.
063f0d27
AM
100 *
101 * @param resource
102 * The resource associated with this trace
103 * @param path
104 * The path to the trace file
105 * @param eventType
106 * The type of events that will be read from this trace
b1baa808 107 * @throws TmfTraceException
07804639 108 * If something went wrong while reading the trace
b1baa808 109 */
a3fc8213 110 @Override
6256d8ad 111 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType)
b4f71e4a 112 throws TmfTraceException {
4a110860
AM
113 /*
114 * Set the cache size. This has to be done before the call to super()
115 * because the super needs to know the cache size.
116 */
117 setCacheSize();
324a6a4a 118
32c16b50
GB
119 super.initTrace(resource, path, eventType);
120
a3fc8213
AM
121 try {
122 this.fTrace = new CTFTrace(path);
81a2d02e 123 CtfTmfContext ctx;
99b483fe 124 /* Set the start and (current) end times for this trace */
81a2d02e 125 ctx = (CtfTmfContext) seekEvent(0L);
132a02b0 126 CtfTmfEvent event = getNext(ctx);
a94410d9 127 if ((ctx.getLocation().equals(CtfIterator.NULL_LOCATION)) || (ctx.getCurrentEvent() == null)) {
99b483fe
AM
128 /* Handle the case where the trace is empty */
129 this.setStartTime(TmfTimestamp.BIG_BANG);
130 } else {
132a02b0 131 final ITmfTimestamp curTime = event.getTimestamp();
21fb02fa
MK
132 this.setStartTime(curTime);
133 this.setEndTime(curTime);
99b483fe 134 }
409bea20
GB
135 /*
136 * Register every event type. When you call getType, it will
137 * register a trace to that type in the TmfEventTypeManager
138 */
6a0ec7bc 139 try (CtfIterator iter = fIteratorManager.getIterator(ctx)) {
409bea20 140 for (IEventDeclaration ied : iter.getEventDeclarations()) {
e600c338 141 CtfTmfEventType ctfTmfEventType = fContainedEventTypes.get(ied.getName());
409bea20
GB
142 if (ctfTmfEventType == null) {
143 List<ITmfEventField> content = new ArrayList<>();
144 /* Should only return null the first time */
145 for (String fieldName : ied.getFields().getFieldsList()) {
146 content.add(new TmfEventField(fieldName, null, null));
147 }
148 ITmfEventField contentTree = new TmfEventField(
149 ITmfEventField.ROOT_FIELD_ID,
150 null,
151 content.toArray(new ITmfEventField[content.size()])
152 );
153
e600c338
AM
154 ctfTmfEventType = new CtfTmfEventType(ied.getName(), contentTree);
155 fContainedEventTypes.put(ctfTmfEventType.getName(), ctfTmfEventType);
409bea20
GB
156 }
157 }
158 }
25e48683 159 } catch (final CTFReaderException e) {
a3fc8213
AM
160 /*
161 * If it failed at the init(), we can assume it's because the file
162 * was not found or was not recognized as a CTF trace. Throw into
163 * the new type of exception expected by the rest of TMF.
164 */
9fa32496 165 throw new TmfTraceException(e.getMessage(), e);
a3fc8213 166 }
a3fc8213
AM
167 }
168
6a0ec7bc
AM
169 /**
170 * Return the iterator manager of this trace
171 *
172 * @return The iterator manager
173 */
174 public CtfIteratorManager getIteratorManager() {
175 return fIteratorManager;
176 }
177
090c006e
AM
178 @Override
179 public void close() {
180 dispose();
181 }
182
53b235e1
MK
183 @Override
184 public synchronized void dispose() {
6a0ec7bc 185 fIteratorManager.dispose();
5d1c6919 186 if (fTrace != null) {
dd9752d5 187 fTrace.close();
5d1c6919
PT
188 fTrace = null;
189 }
53b235e1
MK
190 super.dispose();
191 }
192
b1baa808 193 /**
cd43d683
PT
194 * {@inheritDoc}
195 * <p>
196 * The default implementation sets the confidence to 10 if the trace is a
197 * valid CTF trace.
b1baa808 198 */
a3fc8213 199 @Override
a94410d9 200 public IStatus validate(final IProject project, final String path) {
dd9752d5
AM
201 IStatus status = new TraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID);
202 try (final CTFTrace temp = new CTFTrace(path);) {
07804639 203 if (!temp.majorIsSet()) {
dd9752d5 204 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_MajorNotSet);
b5354daa 205 } else {
dd9752d5
AM
206 try (CTFTraceReader ctfTraceReader = new CTFTraceReader(temp);) {
207 if (!ctfTraceReader.hasMoreEvents()) {
208 // TODO: This will need an additional check when we
209 // support live traces
210 // because having no event is valid for a live trace
211 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_NoEvent);
212 }
b5354daa 213 }
a94410d9 214 }
25e48683 215 } catch (final CTFReaderException e) {
dd9752d5
AM
216 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError + ": " + e.toString()); //$NON-NLS-1$
217 } catch (final BufferOverflowException e) {
218 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError + ": " + Messages.CtfTmfTrace_BufferOverflowErrorMessage); //$NON-NLS-1$
a3fc8213 219 }
96c0f2af 220
dd9752d5 221 return status;
a3fc8213
AM
222 }
223
b1baa808 224 /**
f474d36b 225 * Method getCurrentLocation. This is not applicable in CTF
a94410d9 226 *
f474d36b 227 * @return null, since the trace has no knowledge of the current location
2bdf0193 228 * @see org.eclipse.tracecompass.tmf.core.trace.ITmfTrace#getCurrentLocation()
a3db8436 229 * @since 3.0
b1baa808 230 */
a3fc8213 231 @Override
1e1bef82 232 public ITmfLocation getCurrentLocation() {
f474d36b 233 return null;
a3fc8213
AM
234 }
235
a3db8436
AM
236 /**
237 * @since 3.0
238 */
a3fc8213 239 @Override
1e1bef82 240 public double getLocationRatio(ITmfLocation location) {
4b7c469f 241 final CtfLocation curLocation = (CtfLocation) location;
81a2d02e 242 final CtfTmfContext context = new CtfTmfContext(this);
53b235e1 243 context.setLocation(curLocation);
5976d44a 244 context.seek(curLocation.getLocationInfo());
a94410d9 245 final CtfLocationInfo currentTime = ((CtfLocationInfo) context.getLocation().getLocationInfo());
6a0ec7bc
AM
246 final long startTime = fIteratorManager.getIterator(context).getStartTime();
247 final long endTime = fIteratorManager.getIterator(context).getEndTime();
132a02b0 248 return ((double) currentTime.getTimestamp() - startTime)
53b235e1 249 / (endTime - startTime);
a3fc8213
AM
250 }
251
b1baa808
MK
252 /**
253 * Method seekEvent.
a94410d9
MK
254 *
255 * @param location
256 * ITmfLocation<?>
b1baa808 257 * @return ITmfContext
a3db8436 258 * @since 3.0
b1baa808 259 */
a3fc8213 260 @Override
76643eb7 261 public synchronized ITmfContext seekEvent(final ITmfLocation location) {
ce2388e0 262 CtfLocation currentLocation = (CtfLocation) location;
81a2d02e 263 CtfTmfContext context = new CtfTmfContext(this);
76643eb7
BH
264 if (fTrace == null) {
265 context.setLocation(null);
266 context.setRank(ITmfContext.UNKNOWN_RANK);
267 return context;
268 }
4a110860
AM
269 /*
270 * The rank is set to 0 if the iterator seeks the beginning. If not, it
271 * will be set to UNKNOWN_RANK, since CTF traces don't support seeking
272 * by rank for now.
273 */
11d6f468 274 if (currentLocation == null) {
f5df94f8 275 currentLocation = new CtfLocation(new CtfLocationInfo(0L, 0L));
4a110860 276 context.setRank(0);
11d6f468 277 }
5976d44a 278 if (currentLocation.getLocationInfo() == CtfLocation.INVALID_LOCATION) {
962fb72f 279 currentLocation = new CtfLocation(getCTFTrace().getCurrentEndTime() + 1, 0L);
1191a574 280 }
f474d36b 281 context.setLocation(currentLocation);
7f0bab07 282 if (location == null) {
6a0ec7bc 283 long timestamp = fIteratorManager.getIterator(context).getCurrentTimestamp();
962fb72f 284 currentLocation = new CtfLocation(timestamp, 0);
7f0bab07 285 }
a94410d9 286 if (context.getRank() != 0) {
3bd44ac8 287 context.setRank(ITmfContext.UNKNOWN_RANK);
64c2cb4c 288 }
f474d36b 289 return context;
a3fc8213
AM
290 }
291
a3fc8213 292 @Override
76643eb7 293 public synchronized ITmfContext seekEvent(double ratio) {
81a2d02e 294 CtfTmfContext context = new CtfTmfContext(this);
76643eb7
BH
295 if (fTrace == null) {
296 context.setLocation(null);
297 context.setRank(ITmfContext.UNKNOWN_RANK);
298 return context;
299 }
962fb72f
PT
300 final long end = getCTFTrace().getCurrentEndTime();
301 final long start = getCTFTrace().getCurrentStartTime();
b2dc9e02 302 final long diff = end - start;
15e89960 303 final long ratioTs = Math.round(diff * ratio) + start;
b2dc9e02 304 context.seek(ratioTs);
f474d36b
PT
305 context.setRank(ITmfContext.UNKNOWN_RANK);
306 return context;
a3fc8213
AM
307 }
308
b1baa808
MK
309 /**
310 * Method readNextEvent.
a94410d9
MK
311 *
312 * @param context
313 * ITmfContext
b1baa808 314 * @return CtfTmfEvent
2bdf0193 315 * @see org.eclipse.tracecompass.tmf.core.trace.ITmfTrace#getNext(ITmfContext)
b1baa808 316 */
a3fc8213 317 @Override
4b7c469f 318 public synchronized CtfTmfEvent getNext(final ITmfContext context) {
faa38350
PT
319 if (fTrace == null) {
320 return null;
321 }
f474d36b 322 CtfTmfEvent event = null;
81a2d02e 323 if (context instanceof CtfTmfContext) {
575beffc 324 if (context.getLocation() == null || CtfLocation.INVALID_LOCATION.equals(context.getLocation().getLocationInfo())) {
ae09313d
PT
325 return null;
326 }
81a2d02e 327 CtfTmfContext ctfContext = (CtfTmfContext) context;
788ddcbc 328 event = ctfContext.getCurrentEvent();
4a110860 329
324a6a4a
BH
330 if (event != null) {
331 updateAttributes(context, event.getTimestamp());
788ddcbc
MK
332 ctfContext.advance();
333 ctfContext.increaseRank();
324a6a4a 334 }
f474d36b 335 }
4a110860 336
aa572e22 337 return event;
a3fc8213
AM
338 }
339
4b7c469f
MK
340 /**
341 * gets the CTFtrace that this is wrapping
a94410d9 342 *
4b7c469f
MK
343 * @return the CTF trace
344 */
345 public CTFTrace getCTFTrace() {
a3fc8213
AM
346 return fTrace;
347 }
a1a24d68 348
bb52f9bc
GB
349 /**
350 * Ctf traces have a clock with a unique uuid that will be used to identify
351 * the host. Traces with the same clock uuid will be known to have been made
352 * on the same machine.
353 *
354 * Note: uuid is an optional field, it may not be there for a clock.
355 */
356 @Override
357 public String getHostId() {
358 CTFClock clock = getCTFTrace().getClock();
359 if (clock != null) {
360 String clockHost = (String) clock.getProperty(CLOCK_HOST_PROPERTY);
361 if (clockHost != null) {
362 return clockHost;
363 }
364 }
365 return super.getHostId();
366 }
367
a94410d9 368 // -------------------------------------------
22307af3 369 // ITmfTraceProperties
a94410d9 370 // -------------------------------------------
4b7c469f
MK
371
372 /**
299e494e 373 * @since 2.0
4b7c469f 374 */
22307af3
AM
375 @Override
376 public Map<String, String> getTraceProperties() {
2db2b43a
GB
377 Map<String, String> properties = new HashMap<>();
378 properties.putAll(fTrace.getEnvironment());
379 properties.put(Messages.CtfTmfTrace_HostID, getHostId());
380 return properties;
4b7c469f
MK
381 }
382
a94410d9
MK
383 // -------------------------------------------
384 // Clocks
385 // -------------------------------------------
bfe038ff 386
9ac2eb62
MK
387 /**
388 * gets the clock offset
a94410d9 389 *
9ac2eb62
MK
390 * @return the clock offset in ns
391 */
a94410d9
MK
392 public long getOffset() {
393 if (fTrace != null) {
bfe038ff
MK
394 return fTrace.getOffset();
395 }
396 return 0;
397 }
398
3480bf12 399 /**
409bea20 400 * Gets the list of declared events
3480bf12 401 *
409bea20 402 * @since 3.0
3480bf12 403 */
409bea20 404 @Override
e600c338
AM
405 public Set<CtfTmfEventType> getContainedEventTypes() {
406 return ImmutableSet.copyOf(fContainedEventTypes.values());
407 }
408
409 /**
410 * Register an event type to this trace.
411 *
412 * Package-visible so that {@link CtfTmfEvent#getType} can call it.
413 *
414 * FIXME This could probably be made cleaner?
415 */
416 void registerEventType(CtfTmfEventType eventType) {
417 fContainedEventTypes.put(eventType.getName(), eventType);
3480bf12
GB
418 }
419
a94410d9
MK
420 // -------------------------------------------
421 // Parser
422 // -------------------------------------------
4b7c469f
MK
423
424 @Override
bfe038ff 425 public CtfTmfEvent parseEvent(ITmfContext context) {
4b7c469f 426 CtfTmfEvent event = null;
ea271da6
PT
427 if (context instanceof CtfTmfContext) {
428 final ITmfContext tmpContext = seekEvent(context.getLocation());
429 event = getNext(tmpContext);
4b7c469f
MK
430 }
431 return event;
11d6f468 432 }
64c2cb4c 433
324a6a4a 434 /**
64c2cb4c 435 * Sets the cache size for a CtfTmfTrace.
324a6a4a
BH
436 */
437 protected void setCacheSize() {
438 setCacheSize(DEFAULT_CACHE_SIZE);
439 }
ce2388e0 440
a94410d9
MK
441 // -------------------------------------------
442 // Helpers
443 // -------------------------------------------
53b235e1 444
36dd544c
MK
445 /**
446 * Get an iterator to the trace
447 *
448 * @return an iterator to the trace
ed59ab27 449 * @since 2.0
36dd544c 450 */
a94410d9 451 public CtfIterator createIterator() {
db8e8f7d
AM
452 try {
453 return new CtfIterator(this);
454 } catch (CTFReaderException e) {
91e7f946 455 Activator.getDefault().logError(e.getMessage(), e);
db8e8f7d
AM
456 }
457 return null;
36dd544c 458 }
e73a4ba5
GB
459
460 // ------------------------------------------------------------------------
461 // Timestamp transformation functions
462 // ------------------------------------------------------------------------
463
464 /**
465 * @since 3.0
466 */
467 @Override
468 public CtfTmfTimestamp createTimestamp(long ts) {
469 return new CtfTmfTimestamp(getTimestampTransform().transform(ts));
470 }
032ecd45
MAL
471
472 private static int fCheckpointSize = -1;
473
c4767854
AM
474 /**
475 * @since 3.0
476 */
032ecd45
MAL
477 @Override
478 public synchronized int getCheckpointSize() {
479 if (fCheckpointSize == -1) {
480 TmfCheckpoint c = new TmfCheckpoint(new CtfTmfTimestamp(0), new CtfLocation(0, 0), 0);
481 ByteBuffer b = ByteBuffer.allocate(ITmfCheckpoint.MAX_SERIALIZE_SIZE);
482 b.clear();
483 c.serialize(b);
484 fCheckpointSize = b.position();
485 }
486
487 return fCheckpointSize;
488 }
489
490 @Override
491 protected ITmfTraceIndexer createIndexer(int interval) {
492 return new TmfBTreeTraceIndexer(this, interval);
493 }
494
c4767854
AM
495 /**
496 * @since 3.0
497 */
032ecd45
MAL
498 @Override
499 public ITmfLocation restoreLocation(ByteBuffer bufferIn) {
500 return new CtfLocation(bufferIn);
501 }
6fd3c6e9
MAL
502
503 @Override
504 public boolean isComplete() {
505 if (getResource() == null) {
506 return true;
507 }
508
509 String host = null;
510 String port = null;
511 String sessionName = null;
512 try {
513 host = getResource().getPersistentProperty(CtfConstants.LIVE_HOST);
514 port = getResource().getPersistentProperty(CtfConstants.LIVE_PORT);
515 sessionName = getResource().getPersistentProperty(CtfConstants.LIVE_SESSION_NAME);
516 } catch (CoreException e) {
517 Activator.getDefault().logError(e.getMessage(), e);
518 // Something happened to the resource, assume we won't get any more data from it
519 return true;
520 }
521 return host == null || port == null || sessionName == null;
522 }
523
524 @Override
525 public void setComplete(final boolean isComplete) {
526 super.setComplete(isComplete);
527 try {
528 if (isComplete) {
529 getResource().setPersistentProperty(CtfConstants.LIVE_HOST, null);
530 getResource().setPersistentProperty(CtfConstants.LIVE_PORT, null);
531 getResource().setPersistentProperty(CtfConstants.LIVE_SESSION_NAME, null);
532 }
533 } catch (CoreException e) {
534 Activator.getDefault().logError(e.getMessage(), e);
535 }
536 }
a3fc8213 537}
This page took 0.101234 seconds and 5 git commands to generate.