Commit | Line | Data |
---|---|---|
8c8bf09f | 1 | /******************************************************************************* |
61759503 | 2 | * Copyright (c) 2009, 2013 Ericsson |
0bfb7d06 | 3 | * |
8c8bf09f ASL |
4 | * All rights reserved. This program and the accompanying materials are |
5 | * made 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 | |
0bfb7d06 | 8 | * |
8c8bf09f | 9 | * Contributors: |
20658947 FC |
10 | * Francois Chouinard - Initial API and implementation |
11 | * Francois Chouinard - Updated as per TMF Trace Model 1.0 | |
ea271da6 | 12 | * Patrick Tasse - Updated for removal of context clone |
8c8bf09f ASL |
13 | *******************************************************************************/ |
14 | ||
6c13869b | 15 | package org.eclipse.linuxtools.tmf.core.trace; |
8c8bf09f | 16 | |
6f4a1d2b | 17 | import java.io.File; |
35c160d9 AM |
18 | import java.util.Collections; |
19 | import java.util.LinkedHashMap; | |
a51b2b9f | 20 | import java.util.Map; |
8c8bf09f | 21 | |
828e5592 | 22 | import org.eclipse.core.resources.IResource; |
faa38350 | 23 | import org.eclipse.core.runtime.CoreException; |
9b749023 | 24 | import org.eclipse.core.runtime.IPath; |
6c13869b | 25 | import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider; |
72f1e62a | 26 | import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; |
b4f71e4a | 27 | import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException; |
5419a136 AM |
28 | import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; |
29 | import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest; | |
faa38350 PT |
30 | import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; |
31 | import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal; | |
32 | import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal; | |
7898bb21 | 33 | import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; |
200789b3 | 34 | import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics; |
1c0de632 | 35 | import org.eclipse.linuxtools.tmf.core.statistics.TmfStateStatistics; |
3bd46eef AM |
36 | import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp; |
37 | import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; | |
38 | import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp; | |
8c8bf09f ASL |
39 | |
40 | /** | |
09e86496 FC |
41 | * Abstract implementation of ITmfTrace. |
42 | * <p> | |
13cb5f43 FC |
43 | * Since the concept of 'location' is trace specific, the concrete classes have |
44 | * to provide the related methods, namely: | |
45 | * <ul> | |
46 | * <li> public ITmfLocation<?> getCurrentLocation() | |
47 | * <li> public double getLocationRatio(ITmfLocation<?> location) | |
48 | * <li> public ITmfContext seekEvent(ITmfLocation<?> location) | |
49 | * <li> public ITmfContext seekEvent(double ratio) | |
2848c377 | 50 | * <li> public boolean validate(IProject project, String path) |
13cb5f43 FC |
51 | * </ul> |
52 | * A concrete trace must provide its corresponding parser. A common way to | |
53 | * accomplish this is by making the concrete class extend TmfTrace and | |
54 | * implement ITmfEventParser. | |
55 | * <p> | |
56 | * The concrete class can either specify its own indexer or use the provided | |
57 | * TmfCheckpointIndexer (default). In this case, the trace cache size will be | |
58 | * used as checkpoint interval. | |
0bfb7d06 | 59 | * |
f7703ed6 FC |
60 | * @version 1.0 |
61 | * @author Francois Chouinard | |
62 | * | |
f7703ed6 FC |
63 | * @see ITmfEvent |
64 | * @see ITmfTraceIndexer | |
65 | * @see ITmfEventParser | |
8c8bf09f | 66 | */ |
6256d8ad | 67 | public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace { |
62d1696a | 68 | |
e31e01e8 | 69 | // ------------------------------------------------------------------------ |
8c8bf09f | 70 | // Attributes |
e31e01e8 | 71 | // ------------------------------------------------------------------------ |
8c8bf09f | 72 | |
09e86496 FC |
73 | // The resource used for persistent properties for this trace |
74 | private IResource fResource; | |
75 | ||
b0a282fb | 76 | // The trace path |
12c155f5 | 77 | private String fPath; |
b0a282fb | 78 | |
0316808c FC |
79 | // The trace cache page size |
80 | private int fCacheSize = ITmfTrace.DEFAULT_TRACE_CACHE_SIZE; | |
62d1696a | 81 | |
0316808c FC |
82 | // The number of events collected (so far) |
83 | private long fNbEvents = 0; | |
62d1696a FC |
84 | |
85 | // The time span of the event stream | |
9cbe7899 | 86 | private ITmfTimestamp fStartTime = TmfTimestamp.BIG_BANG; |
a4115405 | 87 | private ITmfTimestamp fEndTime = TmfTimestamp.BIG_BANG; |
62d1696a | 88 | |
0316808c FC |
89 | // The trace streaming interval (0 = no streaming) |
90 | private long fStreamingInterval = 0; | |
085d898f | 91 | |
0316808c | 92 | // The trace indexer |
6256d8ad | 93 | private ITmfTraceIndexer fIndexer; |
20658947 | 94 | |
0316808c | 95 | // The trace parser |
6256d8ad | 96 | private ITmfEventParser fParser; |
7e6347b0 | 97 | |
200789b3 AM |
98 | // The trace's statistics |
99 | private ITmfStatistics fStatistics; | |
100 | ||
a51b2b9f AM |
101 | /** |
102 | * The collection of state systems that are registered with this trace. Each | |
103 | * sub-class can decide to add its (one or many) state system to this map | |
104 | * during their {@link #buildStateSystem()}. | |
105 | * | |
106 | * @since 2.0 | |
107 | */ | |
108 | protected final Map<String, ITmfStateSystem> fStateSystems = | |
35c160d9 | 109 | new LinkedHashMap<String, ITmfStateSystem>(); |
a51b2b9f | 110 | |
e31e01e8 | 111 | // ------------------------------------------------------------------------ |
3791b5df | 112 | // Construction |
e31e01e8 | 113 | // ------------------------------------------------------------------------ |
8c8bf09f | 114 | |
62d1696a | 115 | /** |
3791b5df | 116 | * The default, parameterless, constructor |
62d1696a | 117 | */ |
3791b5df FC |
118 | public TmfTrace() { |
119 | super(); | |
05bd3318 FC |
120 | } |
121 | ||
122 | /** | |
8cf330ae | 123 | * Full constructor. |
0bfb7d06 | 124 | * |
8cf330ae AM |
125 | * @param resource |
126 | * The resource associated to the trace | |
127 | * @param type | |
128 | * The type of events that will be read from this trace | |
129 | * @param path | |
130 | * The path to the trace on the filesystem | |
131 | * @param cacheSize | |
132 | * The trace cache size. Pass '-1' to use the default specified | |
133 | * in {@link ITmfTrace#DEFAULT_TRACE_CACHE_SIZE} | |
134 | * @param interval | |
135 | * The trace streaming interval. You can use '0' for post-mortem | |
136 | * traces. | |
137 | * @param indexer | |
138 | * The trace indexer. You can pass 'null' to use a default | |
139 | * checkpoint indexer. | |
140 | * @param parser | |
141 | * The trace event parser. Use 'null' if (and only if) the trace | |
142 | * object itself is also the ITmfEventParser to be used. | |
143 | * @throws TmfTraceException | |
144 | * If something failed during the opening | |
20658947 | 145 | */ |
8cf330ae AM |
146 | protected TmfTrace(final IResource resource, |
147 | final Class<? extends ITmfEvent> type, | |
148 | final String path, | |
149 | final int cacheSize, | |
150 | final long interval, | |
151 | final ITmfTraceIndexer indexer, | |
152 | final ITmfEventParser parser) | |
153 | throws TmfTraceException { | |
00641a97 | 154 | super(); |
0316808c | 155 | fCacheSize = (cacheSize > 0) ? cacheSize : ITmfTrace.DEFAULT_TRACE_CACHE_SIZE; |
3791b5df | 156 | fStreamingInterval = interval; |
7e6347b0 | 157 | fIndexer = (indexer != null) ? indexer : new TmfCheckpointIndexer(this, fCacheSize); |
13cb5f43 | 158 | fParser = parser; |
09e86496 | 159 | initialize(resource, path, type); |
8c8bf09f ASL |
160 | } |
161 | ||
3791b5df FC |
162 | /** |
163 | * Copy constructor | |
0bfb7d06 | 164 | * |
3791b5df | 165 | * @param trace the original trace |
063f0d27 | 166 | * @throws TmfTraceException Should not happen usually |
3791b5df | 167 | */ |
6256d8ad | 168 | public TmfTrace(final TmfTrace trace) throws TmfTraceException { |
3791b5df | 169 | super(); |
0316808c | 170 | if (trace == null) { |
3791b5df | 171 | throw new IllegalArgumentException(); |
0316808c | 172 | } |
20658947 FC |
173 | fCacheSize = trace.getCacheSize(); |
174 | fStreamingInterval = trace.getStreamingInterval(); | |
7e6347b0 | 175 | fIndexer = new TmfCheckpointIndexer(this); |
13cb5f43 FC |
176 | fParser = trace.fParser; |
177 | initialize(trace.getResource(), trace.getPath(), trace.getEventType()); | |
3791b5df FC |
178 | } |
179 | ||
7e6347b0 FC |
180 | // ------------------------------------------------------------------------ |
181 | // ITmfTrace - Initializers | |
182 | // ------------------------------------------------------------------------ | |
183 | ||
7e6347b0 | 184 | @Override |
6256d8ad | 185 | public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> type) throws TmfTraceException { |
9dc3dee2 | 186 | fIndexer = new TmfCheckpointIndexer(this, fCacheSize); |
7e6347b0 | 187 | initialize(resource, path, type); |
7e6347b0 FC |
188 | } |
189 | ||
09e86496 | 190 | /** |
1703b536 | 191 | * Initialize the trace common attributes and the base component. |
0bfb7d06 MK |
192 | * |
193 | * @param resource the Eclipse resource (trace) | |
1703b536 FC |
194 | * @param path the trace path |
195 | * @param type the trace event type | |
0bfb7d06 | 196 | * |
6f4e8ec0 | 197 | * @throws TmfTraceException If something failed during the initialization |
3791b5df | 198 | */ |
248af329 AM |
199 | protected void initialize(final IResource resource, |
200 | final String path, | |
201 | final Class<? extends ITmfEvent> type) | |
202 | throws TmfTraceException { | |
0316808c | 203 | if (path == null) { |
b4f71e4a | 204 | throw new TmfTraceException("Invalid trace path"); //$NON-NLS-1$ |
0316808c | 205 | } |
3791b5df | 206 | fPath = path; |
1703b536 | 207 | fResource = resource; |
25e48683 | 208 | String traceName = (resource != null) ? resource.getName() : null; |
1703b536 FC |
209 | // If no resource was provided, extract the display name the trace path |
210 | if (traceName == null) { | |
9b749023 | 211 | final int sep = path.lastIndexOf(IPath.SEPARATOR); |
1703b536 FC |
212 | traceName = (sep >= 0) ? path.substring(sep + 1) : path; |
213 | } | |
2352aed9 FC |
214 | if (fParser == null) { |
215 | if (this instanceof ITmfEventParser) { | |
6256d8ad | 216 | fParser = (ITmfEventParser) this; |
2352aed9 FC |
217 | } else { |
218 | throw new TmfTraceException("Invalid trace parser"); //$NON-NLS-1$ | |
219 | } | |
220 | } | |
3791b5df FC |
221 | super.init(traceName, type); |
222 | } | |
223 | ||
2352aed9 FC |
224 | /** |
225 | * Indicates if the path points to an existing file/directory | |
0bfb7d06 | 226 | * |
2352aed9 FC |
227 | * @param path the path to test |
228 | * @return true if the file/directory exists | |
3791b5df | 229 | */ |
2352aed9 | 230 | protected boolean fileExists(final String path) { |
085d898f | 231 | final File file = new File(path); |
3791b5df FC |
232 | return file.exists(); |
233 | } | |
234 | ||
c7e1020d | 235 | /** |
51e75066 | 236 | * @since 2.0 |
c7e1020d | 237 | */ |
51e75066 AM |
238 | @Override |
239 | public void indexTrace(boolean waitForCompletion) { | |
9e0640dc | 240 | getIndexer().buildIndex(0, TmfTimeRange.ETERNITY, waitForCompletion); |
c7e1020d FC |
241 | } |
242 | ||
200789b3 | 243 | /** |
6f4e8ec0 | 244 | * The default implementation of TmfTrace uses a TmfStatistics back-end. |
200789b3 AM |
245 | * Override this if you want to specify another type (or none at all). |
246 | * | |
6f4e8ec0 AM |
247 | * @throws TmfTraceException |
248 | * If there was a problem setting up the statistics | |
200789b3 AM |
249 | * @since 2.0 |
250 | */ | |
251 | protected void buildStatistics() throws TmfTraceException { | |
252 | /* | |
253 | * Initialize the statistics provider, but only if a Resource has been | |
254 | * set (so we don't build it for experiments, for unit tests, etc.) | |
255 | */ | |
1c0de632 | 256 | fStatistics = (fResource == null ? null : new TmfStateStatistics(this) ); |
200789b3 AM |
257 | } |
258 | ||
faa38350 PT |
259 | /** |
260 | * Build the state system(s) associated with this trace type. | |
261 | * | |
262 | * Suppressing the warning, because the 'throws' will usually happen in | |
263 | * sub-classes. | |
264 | * | |
265 | * @throws TmfTraceException | |
266 | * If there is a problem during the build | |
267 | * @since 2.0 | |
268 | */ | |
269 | @SuppressWarnings("unused") | |
270 | protected void buildStateSystem() throws TmfTraceException { | |
271 | /* | |
272 | * Nothing is done in the base implementation, please specify | |
a51b2b9f | 273 | * how/if to register a new state system in derived classes. |
faa38350 PT |
274 | */ |
275 | return; | |
276 | } | |
277 | ||
b5ee6881 FC |
278 | /** |
279 | * Clears the trace | |
280 | */ | |
281 | @Override | |
282 | public synchronized void dispose() { | |
1a4205d9 | 283 | /* Clean up the index if applicable */ |
77551cc2 FC |
284 | if (getIndexer() != null) { |
285 | getIndexer().dispose(); | |
286 | } | |
1a4205d9 AM |
287 | |
288 | /* Clean up the statistics */ | |
289 | if (fStatistics != null) { | |
290 | fStatistics.dispose(); | |
291 | } | |
a51b2b9f AM |
292 | |
293 | /* Clean up the state systems */ | |
294 | for (ITmfStateSystem ss : fStateSystems.values()) { | |
295 | ss.dispose(); | |
296 | } | |
297 | ||
b5ee6881 FC |
298 | super.dispose(); |
299 | } | |
300 | ||
3791b5df | 301 | // ------------------------------------------------------------------------ |
09e86496 | 302 | // ITmfTrace - Basic getters |
e31e01e8 | 303 | // ------------------------------------------------------------------------ |
8c8bf09f | 304 | |
25e48683 | 305 | @Override |
6256d8ad AM |
306 | public Class<ITmfEvent> getEventType() { |
307 | return (Class<ITmfEvent>) super.getType(); | |
25e48683 FC |
308 | } |
309 | ||
d4011df2 | 310 | @Override |
09e86496 FC |
311 | public IResource getResource() { |
312 | return fResource; | |
8c8bf09f ASL |
313 | } |
314 | ||
d4011df2 | 315 | @Override |
09e86496 FC |
316 | public String getPath() { |
317 | return fPath; | |
8c8bf09f ASL |
318 | } |
319 | ||
20658947 FC |
320 | @Override |
321 | public int getCacheSize() { | |
322 | return fCacheSize; | |
323 | } | |
324 | ||
20658947 FC |
325 | @Override |
326 | public long getStreamingInterval() { | |
327 | return fStreamingInterval; | |
328 | } | |
329 | ||
0316808c FC |
330 | /** |
331 | * @return the trace indexer | |
332 | */ | |
6256d8ad | 333 | protected ITmfTraceIndexer getIndexer() { |
0316808c FC |
334 | return fIndexer; |
335 | } | |
336 | ||
337 | /** | |
338 | * @return the trace parser | |
339 | */ | |
6256d8ad | 340 | protected ITmfEventParser getParser() { |
0316808c FC |
341 | return fParser; |
342 | } | |
343 | ||
200789b3 AM |
344 | /** |
345 | * @since 2.0 | |
346 | */ | |
347 | @Override | |
348 | public ITmfStatistics getStatistics() { | |
349 | return fStatistics; | |
350 | } | |
351 | ||
7898bb21 AM |
352 | /** |
353 | * @since 2.0 | |
354 | */ | |
355 | @Override | |
35c160d9 AM |
356 | public final Map<String, ITmfStateSystem> getStateSystems() { |
357 | return Collections.unmodifiableMap(fStateSystems); | |
7898bb21 AM |
358 | } |
359 | ||
6c5e0863 AM |
360 | /** |
361 | * @since 2.0 | |
362 | */ | |
363 | @Override | |
364 | public final void registerStateSystem(String id, ITmfStateSystem ss) { | |
365 | fStateSystems.put(id, ss); | |
366 | } | |
367 | ||
09e86496 FC |
368 | // ------------------------------------------------------------------------ |
369 | // ITmfTrace - Trace characteristics getters | |
370 | // ------------------------------------------------------------------------ | |
371 | ||
d4011df2 | 372 | @Override |
5419a136 | 373 | public synchronized long getNbEvents() { |
3791b5df | 374 | return fNbEvents; |
b0a282fb FC |
375 | } |
376 | ||
3bd46eef AM |
377 | /** |
378 | * @since 2.0 | |
62d1696a | 379 | */ |
d4011df2 | 380 | @Override |
12c155f5 | 381 | public TmfTimeRange getTimeRange() { |
cb866e08 | 382 | return new TmfTimeRange(fStartTime, fEndTime); |
8c8bf09f ASL |
383 | } |
384 | ||
3bd46eef AM |
385 | /** |
386 | * @since 2.0 | |
e31e01e8 | 387 | */ |
d4011df2 | 388 | @Override |
4df4581d | 389 | public ITmfTimestamp getStartTime() { |
4593bd5b | 390 | return fStartTime; |
146a887c FC |
391 | } |
392 | ||
3bd46eef AM |
393 | /** |
394 | * @since 2.0 | |
e31e01e8 | 395 | */ |
d4011df2 | 396 | @Override |
4df4581d | 397 | public ITmfTimestamp getEndTime() { |
4593bd5b | 398 | return fEndTime; |
20658947 FC |
399 | } |
400 | ||
d7ee91bb | 401 | /** |
d7ee91bb PT |
402 | * @since 2.0 |
403 | */ | |
66262ad8 BH |
404 | @Override |
405 | public ITmfTimestamp getInitialRangeOffset() { | |
d7ee91bb PT |
406 | final long DEFAULT_INITIAL_OFFSET_VALUE = (1L * 100 * 1000 * 1000); // .1sec |
407 | return new TmfTimestamp(DEFAULT_INITIAL_OFFSET_VALUE, ITmfTimestamp.NANOSECOND_SCALE); | |
408 | } | |
409 | ||
20658947 | 410 | // ------------------------------------------------------------------------ |
d7ee91bb | 411 | // Convenience setters |
20658947 FC |
412 | // ------------------------------------------------------------------------ |
413 | ||
0316808c FC |
414 | /** |
415 | * Set the trace cache size. Must be done at initialization time. | |
0bfb7d06 | 416 | * |
0316808c FC |
417 | * @param cacheSize The trace cache size |
418 | */ | |
419 | protected void setCacheSize(final int cacheSize) { | |
420 | fCacheSize = cacheSize; | |
421 | } | |
422 | ||
423 | /** | |
424 | * Set the trace known number of events. This can be quite dynamic | |
425 | * during indexing or for live traces. | |
0bfb7d06 | 426 | * |
0316808c FC |
427 | * @param nbEvents The number of events |
428 | */ | |
429 | protected synchronized void setNbEvents(final long nbEvents) { | |
430 | fNbEvents = (nbEvents > 0) ? nbEvents : 0; | |
431 | } | |
432 | ||
20658947 FC |
433 | /** |
434 | * Update the trace events time range | |
0bfb7d06 | 435 | * |
20658947 | 436 | * @param range the new time range |
3bd46eef | 437 | * @since 2.0 |
20658947 FC |
438 | */ |
439 | protected void setTimeRange(final TmfTimeRange range) { | |
4593bd5b AM |
440 | fStartTime = range.getStartTime(); |
441 | fEndTime = range.getEndTime(); | |
20658947 FC |
442 | } |
443 | ||
444 | /** | |
445 | * Update the trace chronologically first event timestamp | |
0bfb7d06 | 446 | * |
20658947 | 447 | * @param startTime the new first event timestamp |
3bd46eef | 448 | * @since 2.0 |
20658947 FC |
449 | */ |
450 | protected void setStartTime(final ITmfTimestamp startTime) { | |
4593bd5b | 451 | fStartTime = startTime; |
20658947 FC |
452 | } |
453 | ||
454 | /** | |
455 | * Update the trace chronologically last event timestamp | |
0bfb7d06 | 456 | * |
20658947 | 457 | * @param endTime the new last event timestamp |
3bd46eef | 458 | * @since 2.0 |
20658947 FC |
459 | */ |
460 | protected void setEndTime(final ITmfTimestamp endTime) { | |
4593bd5b | 461 | fEndTime = endTime; |
20658947 FC |
462 | } |
463 | ||
464 | /** | |
0316808c | 465 | * Set the polling interval for live traces (default = 0 = no streaming). |
0bfb7d06 | 466 | * |
20658947 FC |
467 | * @param interval the new trace streaming interval |
468 | */ | |
469 | protected void setStreamingInterval(final long interval) { | |
1703b536 | 470 | fStreamingInterval = (interval > 0) ? interval : 0; |
146a887c FC |
471 | } |
472 | ||
0316808c FC |
473 | /** |
474 | * Set the trace indexer. Must be done at initialization time. | |
0bfb7d06 | 475 | * |
0316808c FC |
476 | * @param indexer the trace indexer |
477 | */ | |
6256d8ad | 478 | protected void setIndexer(final ITmfTraceIndexer indexer) { |
0316808c FC |
479 | fIndexer = indexer; |
480 | } | |
481 | ||
482 | /** | |
483 | * Set the trace parser. Must be done at initialization time. | |
0bfb7d06 | 484 | * |
0316808c FC |
485 | * @param parser the new trace parser |
486 | */ | |
6256d8ad | 487 | protected void setParser(final ITmfEventParser parser) { |
0316808c FC |
488 | fParser = parser; |
489 | } | |
490 | ||
09e86496 | 491 | // ------------------------------------------------------------------------ |
7e6347b0 | 492 | // ITmfTrace - SeekEvent operations (returning a trace context) |
09e86496 FC |
493 | // ------------------------------------------------------------------------ |
494 | ||
1b70b6dc | 495 | @Override |
7e6347b0 | 496 | public synchronized ITmfContext seekEvent(final long rank) { |
09e86496 | 497 | |
7e6347b0 | 498 | // A rank <= 0 indicates to seek the first event |
2352aed9 | 499 | if (rank <= 0) { |
1e1bef82 | 500 | ITmfContext context = seekEvent((ITmfLocation) null); |
2352aed9 FC |
501 | context.setRank(0); |
502 | return context; | |
503 | } | |
09e86496 | 504 | |
09e86496 | 505 | // Position the trace at the checkpoint |
7e6347b0 | 506 | final ITmfContext context = fIndexer.seekIndex(rank); |
09e86496 FC |
507 | |
508 | // And locate the requested event context | |
7e6347b0 FC |
509 | long pos = context.getRank(); |
510 | if (pos < rank) { | |
c32744d6 | 511 | ITmfEvent event = getNext(context); |
0bfb7d06 | 512 | while ((event != null) && (++pos < rank)) { |
c32744d6 | 513 | event = getNext(context); |
7e6347b0 | 514 | } |
09e86496 FC |
515 | } |
516 | return context; | |
1b70b6dc PT |
517 | } |
518 | ||
3bd46eef AM |
519 | /** |
520 | * @since 2.0 | |
09e86496 FC |
521 | */ |
522 | @Override | |
7e6347b0 | 523 | public synchronized ITmfContext seekEvent(final ITmfTimestamp timestamp) { |
09e86496 | 524 | |
7e6347b0 | 525 | // A null timestamp indicates to seek the first event |
2352aed9 | 526 | if (timestamp == null) { |
1e1bef82 | 527 | ITmfContext context = seekEvent((ITmfLocation) null); |
2352aed9 FC |
528 | context.setRank(0); |
529 | return context; | |
530 | } | |
09e86496 | 531 | |
1703b536 | 532 | // Position the trace at the checkpoint |
408e65d2 | 533 | ITmfContext context = fIndexer.seekIndex(timestamp); |
09e86496 FC |
534 | |
535 | // And locate the requested event context | |
ea271da6 PT |
536 | ITmfLocation previousLocation = context.getLocation(); |
537 | long previousRank = context.getRank(); | |
538 | ITmfEvent event = getNext(context); | |
7e6347b0 | 539 | while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) { |
ea271da6 PT |
540 | previousLocation = context.getLocation(); |
541 | previousRank = context.getRank(); | |
542 | event = getNext(context); | |
09e86496 | 543 | } |
0316808c FC |
544 | if (event == null) { |
545 | context.setLocation(null); | |
546 | context.setRank(ITmfContext.UNKNOWN_RANK); | |
ea271da6 PT |
547 | } else { |
548 | context.dispose(); | |
549 | context = seekEvent(previousLocation); | |
550 | context.setRank(previousRank); | |
0316808c | 551 | } |
09e86496 FC |
552 | return context; |
553 | } | |
0283f7ff | 554 | |
09e86496 FC |
555 | // ------------------------------------------------------------------------ |
556 | // ITmfTrace - Read operations (returning an actual event) | |
557 | // ------------------------------------------------------------------------ | |
558 | ||
d4011df2 | 559 | @Override |
6256d8ad | 560 | public synchronized ITmfEvent getNext(final ITmfContext context) { |
09e86496 | 561 | // parseEvent() does not update the context |
6256d8ad | 562 | final ITmfEvent event = fParser.parseEvent(context); |
09e86496 | 563 | if (event != null) { |
d337369a | 564 | updateAttributes(context, event.getTimestamp()); |
09e86496 FC |
565 | context.setLocation(getCurrentLocation()); |
566 | context.increaseRank(); | |
567 | processEvent(event); | |
568 | } | |
569 | return event; | |
570 | } | |
571 | ||
572 | /** | |
d337369a | 573 | * Hook for special event processing by the concrete class |
7e6347b0 | 574 | * (called by TmfTrace.getEvent()) |
0bfb7d06 | 575 | * |
d337369a | 576 | * @param event the event |
09e86496 FC |
577 | */ |
578 | protected void processEvent(final ITmfEvent event) { | |
d337369a | 579 | // Do nothing |
09e86496 FC |
580 | } |
581 | ||
d337369a FC |
582 | /** |
583 | * Update the trace attributes | |
0bfb7d06 | 584 | * |
d337369a | 585 | * @param context the current trace context |
2848c377 | 586 | * @param timestamp the corresponding timestamp |
3bd46eef | 587 | * @since 2.0 |
d337369a FC |
588 | */ |
589 | protected synchronized void updateAttributes(final ITmfContext context, final ITmfTimestamp timestamp) { | |
0bfb7d06 | 590 | if (fStartTime.equals(TmfTimestamp.BIG_BANG) || (fStartTime.compareTo(timestamp, false) > 0)) { |
4593bd5b | 591 | fStartTime = timestamp; |
09e86496 | 592 | } |
0bfb7d06 | 593 | if (fEndTime.equals(TmfTimestamp.BIG_CRUNCH) || (fEndTime.compareTo(timestamp, false) < 0)) { |
4593bd5b | 594 | fEndTime = timestamp; |
09e86496 FC |
595 | } |
596 | if (context.hasValidRank()) { | |
d337369a | 597 | long rank = context.getRank(); |
09e86496 FC |
598 | if (fNbEvents <= rank) { |
599 | fNbEvents = rank + 1; | |
600 | } | |
200789b3 AM |
601 | if (fIndexer != null) { |
602 | fIndexer.updateIndex(context, timestamp); | |
603 | } | |
09e86496 | 604 | } |
abfad0aa FC |
605 | } |
606 | ||
3791b5df | 607 | // ------------------------------------------------------------------------ |
d337369a | 608 | // TmfDataProvider |
3791b5df FC |
609 | // ------------------------------------------------------------------------ |
610 | ||
77c4a6df AM |
611 | /** |
612 | * @since 2.0 | |
d337369a | 613 | */ |
3791b5df | 614 | @Override |
5419a136 | 615 | public synchronized ITmfContext armRequest(final ITmfDataRequest request) { |
faa38350 PT |
616 | if (executorIsShutdown()) { |
617 | return null; | |
618 | } | |
5419a136 AM |
619 | if ((request instanceof ITmfEventRequest) |
620 | && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest) request).getRange().getStartTime()) | |
621 | && (request.getIndex() == 0)) | |
622 | { | |
623 | final ITmfContext context = seekEvent(((ITmfEventRequest) request).getRange().getStartTime()); | |
624 | ((ITmfEventRequest) request).setStartIndex((int) context.getRank()); | |
8584dc20 | 625 | return context; |
8584dc20 | 626 | |
5419a136 AM |
627 | } |
628 | return seekEvent(request.getIndex()); | |
3791b5df FC |
629 | } |
630 | ||
faa38350 PT |
631 | // ------------------------------------------------------------------------ |
632 | // Signal handlers | |
633 | // ------------------------------------------------------------------------ | |
634 | ||
635 | /** | |
636 | * Handler for the Trace Opened signal | |
637 | * | |
638 | * @param signal | |
639 | * The incoming signal | |
640 | * @since 2.0 | |
641 | */ | |
642 | @TmfSignalHandler | |
643 | public void traceOpened(TmfTraceOpenedSignal signal) { | |
b9a5bf8f AM |
644 | boolean signalIsForUs = false; |
645 | for (ITmfTrace trace : TmfTraceManager.getTraceSet(signal.getTrace())) { | |
646 | if (trace == this) { | |
647 | signalIsForUs = true; | |
fe0c44c4 | 648 | break; |
faa38350 PT |
649 | } |
650 | } | |
faa38350 | 651 | |
b9a5bf8f | 652 | if (!signalIsForUs) { |
fe0c44c4 AM |
653 | return; |
654 | } | |
655 | ||
656 | /* | |
b9a5bf8f | 657 | * The signal is either for this trace, or for an experiment containing |
fe0c44c4 AM |
658 | * this trace. |
659 | */ | |
660 | try { | |
661 | buildStatistics(); | |
662 | buildStateSystem(); | |
663 | } catch (TmfTraceException e) { | |
664 | e.printStackTrace(); | |
665 | } | |
666 | ||
667 | /* Refresh the project, so it can pick up new files that got created. */ | |
668 | try { | |
669 | if (fResource != null) { | |
670 | fResource.getProject().refreshLocal(IResource.DEPTH_INFINITE, null); | |
faa38350 | 671 | } |
fe0c44c4 AM |
672 | } catch (CoreException e) { |
673 | e.printStackTrace(); | |
faa38350 | 674 | } |
fe0c44c4 | 675 | |
faa38350 | 676 | if (signal.getTrace() == this) { |
fe0c44c4 | 677 | /* Additionally, the signal is directly for this trace or experiment. */ |
faa38350 PT |
678 | if (getNbEvents() == 0) { |
679 | return; | |
680 | } | |
681 | ||
682 | final TmfTimeRange timeRange = new TmfTimeRange(getStartTime(), TmfTimestamp.BIG_CRUNCH); | |
683 | final TmfTraceRangeUpdatedSignal rangeUpdatedsignal = new TmfTraceRangeUpdatedSignal(this, this, timeRange); | |
684 | ||
685 | // Broadcast in separate thread to prevent deadlock | |
686 | new Thread() { | |
687 | @Override | |
688 | public void run() { | |
689 | broadcast(rangeUpdatedsignal); | |
690 | } | |
691 | }.start(); | |
692 | return; | |
693 | } | |
694 | } | |
695 | ||
696 | /** | |
697 | * Signal handler for the TmfTraceRangeUpdatedSignal signal | |
698 | * | |
699 | * @param signal The incoming signal | |
700 | * @since 2.0 | |
701 | */ | |
702 | @TmfSignalHandler | |
703 | public void traceRangeUpdated(final TmfTraceRangeUpdatedSignal signal) { | |
704 | if (signal.getTrace() == this) { | |
705 | getIndexer().buildIndex(getNbEvents(), signal.getRange(), false); | |
706 | } | |
707 | } | |
708 | ||
3791b5df | 709 | // ------------------------------------------------------------------------ |
09e86496 | 710 | // toString |
3791b5df FC |
711 | // ------------------------------------------------------------------------ |
712 | ||
12c155f5 | 713 | @Override |
09e86496 | 714 | @SuppressWarnings("nls") |
5419a136 | 715 | public synchronized String toString() { |
20658947 FC |
716 | return "TmfTrace [fPath=" + fPath + ", fCacheSize=" + fCacheSize |
717 | + ", fNbEvents=" + fNbEvents + ", fStartTime=" + fStartTime | |
718 | + ", fEndTime=" + fEndTime + ", fStreamingInterval=" + fStreamingInterval + "]"; | |
12c155f5 FC |
719 | } |
720 | ||
8c8bf09f | 721 | } |