Various fixes following code review
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfTrace.java
CommitLineData
8c8bf09f 1/*******************************************************************************
e31e01e8 2 * Copyright (c) 2009, 2010 Ericsson
8c8bf09f
ASL
3 *
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
8 *
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
12
6c13869b 13package org.eclipse.linuxtools.tmf.core.trace;
8c8bf09f 14
6f4a1d2b 15import java.io.File;
62d1696a 16import java.io.FileNotFoundException;
62d1696a 17import java.util.Collections;
8c8bf09f
ASL
18import java.util.Vector;
19
12c155f5 20import org.eclipse.core.resources.IProject;
828e5592 21import org.eclipse.core.resources.IResource;
05bd3318
FC
22import org.eclipse.core.runtime.IProgressMonitor;
23import org.eclipse.core.runtime.IStatus;
c7e2f194 24import org.eclipse.core.runtime.Path;
05bd3318
FC
25import org.eclipse.core.runtime.Status;
26import org.eclipse.core.runtime.jobs.Job;
6c13869b 27import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider;
4df4581d 28import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
6c13869b
FC
29import org.eclipse.linuxtools.tmf.core.event.TmfEvent;
30import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
31import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
32import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
33import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
34import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
35import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
36import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
8c8bf09f
ASL
37
38/**
146a887c 39 * <b><u>TmfTrace</u></b>
8c8bf09f 40 * <p>
12c155f5
FC
41 * Abstract implementation of ITmfTrace. It should be sufficient to extend this class and provide implementation for
42 * <code>getCurrentLocation()</code> and <code>seekLocation()</code>, as well as a proper parser, to have a working
4e3aa37d 43 * concrete implementation.
ff4ed569 44 * <p>
12c155f5
FC
45 * Note: The notion of event rank is still under heavy discussion. Although used by the Events View and probably useful
46 * in the general case, there is no easy way to implement it for LTTng (actually a strong case is being made that this
47 * is useless).
ff4ed569 48 * <p>
12c155f5
FC
49 * That it is not supported by LTTng does by no mean indicate that it is not useful for (just about) every other tracing
50 * tool. Therefore, this class provides a minimal (and partial) implementation of rank. However, the current
ff4ed569 51 * implementation should not be relied on in the general case.
54d55ced 52 *
4e3aa37d 53 * TODO: Add support for live streaming (notifications, incremental indexing, ...)
8c8bf09f 54 */
12c155f5 55public abstract class TmfTrace<T extends TmfEvent> extends TmfEventProvider<T> implements ITmfTrace<T>, Cloneable {
62d1696a 56
e31e01e8 57 // ------------------------------------------------------------------------
62d1696a 58 // Constants
e31e01e8 59 // ------------------------------------------------------------------------
62d1696a
FC
60
61 // The default number of events to cache
12c155f5 62 // TODO: Make the DEFAULT_CACHE_SIZE a preference
b12f4544 63 public static final int DEFAULT_INDEX_PAGE_SIZE = 50000;
8c8bf09f 64
e31e01e8 65 // ------------------------------------------------------------------------
8c8bf09f 66 // Attributes
e31e01e8 67 // ------------------------------------------------------------------------
8c8bf09f 68
b0a282fb 69 // The trace path
12c155f5 70 private String fPath;
b0a282fb 71
00641a97 72 // The trace name
c5b45b39 73 private String fTraceName;
00641a97 74
8d2e2848 75 // The cache page size AND checkpoints interval
12c155f5 76 protected int fIndexPageSize = DEFAULT_INDEX_PAGE_SIZE;
62d1696a
FC
77
78 // The set of event stream checkpoints (for random access)
9f584e4c 79 protected Vector<TmfCheckpoint> fCheckpoints = new Vector<TmfCheckpoint>();
62d1696a
FC
80
81 // The number of events collected
a3fe52fc 82 protected long fNbEvents = 0;
62d1696a
FC
83
84 // The time span of the event stream
4df4581d 85 private ITmfTimestamp fStartTime = TmfTimestamp.BigCrunch;
86 private ITmfTimestamp fEndTime = TmfTimestamp.BigBang;
62d1696a 87
828e5592
PT
88 // The trace resource
89 private IResource fResource;
90
e31e01e8 91 // ------------------------------------------------------------------------
50adc88e 92 // Constructors
e31e01e8 93 // ------------------------------------------------------------------------
8c8bf09f 94
12c155f5 95 public TmfTrace() {
00641a97 96 super();
12c155f5
FC
97 }
98
99 @Override
100 public void initTrace(String path, Class<T> eventType) throws FileNotFoundException {
96c6806f 101 initTmfTrace(path, eventType, DEFAULT_INDEX_PAGE_SIZE, false, null);
12c155f5
FC
102 }
103
104 @Override
105 public void initTrace(String path, Class<T> eventType, int cacheSize) throws FileNotFoundException {
96c6806f 106 initTmfTrace(path, eventType, cacheSize, false, null);
12c155f5
FC
107 }
108
109 @Override
110 public void initTrace(String path, Class<T> eventType, boolean indexTrace) throws FileNotFoundException {
96c6806f 111 initTmfTrace(path, eventType, DEFAULT_INDEX_PAGE_SIZE, indexTrace, null);
12c155f5
FC
112 }
113
114 @Override
115 public void initTrace(String path, Class<T> eventType, int cacheSize, boolean indexTrace) throws FileNotFoundException {
96c6806f 116 initTmfTrace(path, eventType, cacheSize, indexTrace, null);
c5b45b39
FC
117 }
118
96c6806f
PT
119 @Override
120 public void initTrace(String path, Class<T> eventType, int cacheSize, boolean indexTrace, String name) throws FileNotFoundException {
121 initTmfTrace(path, eventType, cacheSize, indexTrace, name);
122 }
123
124 private void initTmfTrace(String path, Class<T> eventType, int cacheSize, boolean indexTrace, String name) throws FileNotFoundException {
12c155f5 125 fPath = path;
96c6806f
PT
126 if (name != null) {
127 fTraceName = name;
128 }
c5b45b39
FC
129 if (fTraceName == null) {
130 fTraceName = ""; //$NON-NLS-1$
00641a97 131 if (path != null) {
c7e2f194 132 int sep = path.lastIndexOf(Path.SEPARATOR);
c5b45b39 133 fTraceName = (sep >= 0) ? path.substring(sep + 1) : path;
00641a97 134 }
12c155f5 135 }
c5b45b39 136 super.init(fTraceName, eventType);
12c155f5 137 fIndexPageSize = (cacheSize > 0) ? cacheSize : DEFAULT_INDEX_PAGE_SIZE;
12c155f5
FC
138 if (indexTrace)
139 indexTrace(false);
140 }
141
142 @Override
143 public boolean validate(IProject project, String path) {
144 File file = new File(path);
145 return file.exists();
146 }
147
ff4ed569
FC
148 /**
149 * @param path
150 * @throws FileNotFoundException
151 */
ce785d7d 152 protected TmfTrace(String name, Class<T> type, String path) throws FileNotFoundException {
12c155f5 153 this(name, type, path, DEFAULT_INDEX_PAGE_SIZE, true);
ff4ed569
FC
154 }
155
62d1696a 156 /**
e31e01e8
FC
157 * @param path
158 * @param cacheSize
62d1696a
FC
159 * @throws FileNotFoundException
160 */
ce785d7d 161 protected TmfTrace(String name, Class<T> type, String path, int cacheSize) throws FileNotFoundException {
12c155f5 162 this(name, type, path, cacheSize, true);
05bd3318
FC
163 }
164
165 /**
166 * @param path
167 * @param indexTrace
168 * @throws FileNotFoundException
169 */
170 protected TmfTrace(String name, Class<T> type, String path, boolean indexTrace) throws FileNotFoundException {
12c155f5 171 this(name, type, path, DEFAULT_INDEX_PAGE_SIZE, indexTrace);
05bd3318
FC
172 }
173
174 /**
175 * @param path
176 * @param cacheSize
177 * @param indexTrace
178 * @throws FileNotFoundException
179 */
180 protected TmfTrace(String name, Class<T> type, String path, int cacheSize, boolean indexTrace) throws FileNotFoundException {
00641a97 181 super();
c5b45b39 182 fTraceName = name;
00641a97 183 initTrace(path, type, cacheSize, indexTrace);
8c8bf09f
ASL
184 }
185
ff4ed569 186 @SuppressWarnings("unchecked")
12c155f5
FC
187 @Override
188 public TmfTrace<T> clone() throws CloneNotSupportedException {
189 TmfTrace<T> clone = (TmfTrace<T>) super.clone();
190 clone.fCheckpoints = fCheckpoints;
4df4581d 191 clone.fStartTime = fStartTime.clone();
192 clone.fEndTime = fEndTime.clone();
12c155f5 193 return clone;
8c8bf09f
ASL
194 }
195
e31e01e8 196 // ------------------------------------------------------------------------
8c8bf09f 197 // Accessors
e31e01e8 198 // ------------------------------------------------------------------------
8c8bf09f 199
62d1696a 200 /**
b0a282fb 201 * @return the trace path
62d1696a 202 */
d4011df2 203 @Override
12c155f5 204 public String getPath() {
b0a282fb 205 return fPath;
8c8bf09f
ASL
206 }
207
62d1696a
FC
208 /* (non-Javadoc)
209 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
210 */
d4011df2 211 @Override
12c155f5 212 public long getNbEvents() {
62d1696a 213 return fNbEvents;
8c8bf09f
ASL
214 }
215
b0a282fb
FC
216 /**
217 * @return the size of the cache
218 */
d4011df2 219 @Override
12c155f5 220 public int getCacheSize() {
9f584e4c 221 return fIndexPageSize;
b0a282fb
FC
222 }
223
62d1696a
FC
224 /* (non-Javadoc)
225 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
226 */
d4011df2 227 @Override
12c155f5 228 public TmfTimeRange getTimeRange() {
cb866e08 229 return new TmfTimeRange(fStartTime, fEndTime);
8c8bf09f
ASL
230 }
231
e31e01e8
FC
232 /* (non-Javadoc)
233 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime()
234 */
d4011df2 235 @Override
4df4581d 236 public ITmfTimestamp getStartTime() {
12c155f5 237 return fStartTime;
146a887c
FC
238 }
239
e31e01e8
FC
240 /* (non-Javadoc)
241 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime()
242 */
d4011df2 243 @Override
4df4581d 244 public ITmfTimestamp getEndTime() {
12c155f5 245 return fEndTime;
146a887c
FC
246 }
247
1b70b6dc
PT
248 /* (non-Javadoc)
249 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
250 */
251 @Override
252 public long getStreamingInterval() {
253 return 0;
254 }
255
ff4ed569 256 @SuppressWarnings("unchecked")
12c155f5
FC
257 public Vector<TmfCheckpoint> getCheckpoints() {
258 return (Vector<TmfCheckpoint>) fCheckpoints.clone();
54d55ced
FC
259 }
260
abfad0aa 261 /**
12c155f5
FC
262 * Returns the rank of the first event with the requested timestamp. If none, returns the index of the next event
263 * (if any).
264 *
abfad0aa
FC
265 * @param timestamp
266 * @return
267 */
d4011df2 268 @Override
4df4581d 269 public long getRank(ITmfTimestamp timestamp) {
abfad0aa
FC
270 TmfContext context = seekEvent(timestamp);
271 return context.getRank();
272 }
273
e31e01e8 274 // ------------------------------------------------------------------------
8c8bf09f 275 // Operators
e31e01e8 276 // ------------------------------------------------------------------------
8c8bf09f 277
4e3aa37d 278 protected void setTimeRange(TmfTimeRange range) {
12c155f5
FC
279 fStartTime = range.getStartTime();
280 fEndTime = range.getEndTime();
4e3aa37d
FC
281 }
282
d7dbf09a 283 protected void setStartTime(ITmfTimestamp startTime) {
12c155f5 284 fStartTime = startTime;
4e3aa37d
FC
285 }
286
dfee01ae 287 protected void setEndTime(ITmfTimestamp endTime) {
12c155f5
FC
288 fEndTime = endTime;
289 }
290
291 // ------------------------------------------------------------------------
292 // TmfProvider
293 // ------------------------------------------------------------------------
294
295 @Override
296 public ITmfContext armRequest(ITmfDataRequest<T> request) {
297 if (request instanceof ITmfEventRequest<?>
298 && !TmfTimestamp.BigBang.equals(((ITmfEventRequest<T>) request).getRange().getStartTime()) && request.getIndex() == 0) {
299 ITmfContext context = seekEvent(((ITmfEventRequest<T>) request).getRange().getStartTime());
300 ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
301 return context;
302
303 }
304 return seekEvent(request.getIndex());
305 }
306
307 /**
308 * Return the next piece of data based on the context supplied. The context would typically be updated for the
309 * subsequent read.
310 *
311 * @param context
312 * @return
313 */
314 @SuppressWarnings("unchecked")
315 @Override
316 public T getNext(ITmfContext context) {
317 if (context instanceof TmfContext) {
318 return (T) getNextEvent((TmfContext) context);
319 }
320 return null;
321 }
322
323 // ------------------------------------------------------------------------
324 // ITmfTrace
325 // ------------------------------------------------------------------------
e31e01e8 326
146a887c
FC
327 /* (non-Javadoc)
328 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
329 */
d4011df2 330 @Override
4df4581d 331 public TmfContext seekEvent(ITmfTimestamp timestamp) {
62d1696a 332
12c155f5
FC
333 if (timestamp == null) {
334 timestamp = TmfTimestamp.BigBang;
335 }
4e3aa37d 336
12c155f5
FC
337 // First, find the right checkpoint
338 int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
62d1696a 339
8d2e2848 340 // In the very likely case that the checkpoint was not found, bsearch
62d1696a
FC
341 // returns its negated would-be location (not an offset...). From that
342 // index, we can then position the stream and get the event.
343 if (index < 0) {
344 index = Math.max(0, -(index + 2));
345 }
346
347 // Position the stream at the checkpoint
452ad365 348 ITmfLocation<?> location;
e31e01e8 349 synchronized (fCheckpoints) {
12c155f5
FC
350 if (fCheckpoints.size() > 0) {
351 if (index >= fCheckpoints.size()) {
352 index = fCheckpoints.size() - 1;
353 }
354 location = fCheckpoints.elementAt(index).getLocation();
355 } else {
356 location = null;
357 }
8d2e2848 358 }
54d55ced
FC
359 TmfContext context = seekLocation(location);
360 context.setRank(index * fIndexPageSize);
62d1696a 361
54d55ced 362 // And locate the event
ff4ed569 363 TmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype...
62d1696a
FC
364 TmfEvent event = getNextEvent(nextEventContext);
365 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
12c155f5
FC
366 context.setLocation(nextEventContext.getLocation().clone());
367 context.updateRank(1);
368 event = getNextEvent(nextEventContext);
62d1696a
FC
369 }
370
54d55ced 371 return context;
62d1696a
FC
372 }
373
146a887c
FC
374 /* (non-Javadoc)
375 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int)
376 */
d4011df2 377 @Override
12c155f5 378 public TmfContext seekEvent(long rank) {
62d1696a
FC
379
380 // Position the stream at the previous checkpoint
9f584e4c 381 int index = (int) rank / fIndexPageSize;
452ad365 382 ITmfLocation<?> location;
e31e01e8 383 synchronized (fCheckpoints) {
12c155f5
FC
384 if (fCheckpoints.size() == 0) {
385 location = null;
386 } else {
387 if (index >= fCheckpoints.size()) {
388 index = fCheckpoints.size() - 1;
389 }
390 location = fCheckpoints.elementAt(index).getLocation();
391 }
8d2e2848 392 }
54d55ced 393
9f584e4c
FC
394 TmfContext context = seekLocation(location);
395 long pos = index * fIndexPageSize;
396 context.setRank(pos);
e31e01e8 397
9f584e4c 398 if (pos < rank) {
e31e01e8 399 TmfEvent event = getNextEvent(context);
9f584e4c 400 while (event != null && ++pos < rank) {
12c155f5 401 event = getNextEvent(context);
e31e01e8 402 }
165c977c 403 }
62d1696a 404
8f50c396 405 return context;
8c8bf09f
ASL
406 }
407
12c155f5
FC
408 /*
409 * (non-Javadoc)
410 *
411 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.
412 * linuxtools.tmf.trace.ITmfTrace.TraceContext)
413 */
414 @Override
415 public synchronized TmfEvent getNextEvent(TmfContext context) {
416 // parseEvent() does not update the context
417 TmfEvent event = parseEvent(context);
418 if (event != null) {
419 updateIndex(context, context.getRank(), event.getTimestamp());
420 context.setLocation(getCurrentLocation());
421 context.updateRank(1);
422 processEvent(event);
423 }
424 return event;
425 }
550d787e 426
4df4581d 427 protected synchronized void updateIndex(ITmfContext context, long rank, ITmfTimestamp timestamp) {
12c155f5
FC
428 if (fStartTime.compareTo(timestamp, false) > 0)
429 fStartTime = timestamp;
430 if (fEndTime.compareTo(timestamp, false) < 0)
431 fEndTime = timestamp;
432 if (context.isValidRank()) {
433 if (fNbEvents <= rank)
434 fNbEvents = rank + 1;
435 // Build the index as we go along
436 if ((rank % fIndexPageSize) == 0) {
437 // Determine the table position
438 long position = rank / fIndexPageSize;
439 // Add new entry at proper location (if empty)
440 if (fCheckpoints.size() == position) {
441 ITmfLocation<?> location = context.getLocation().clone();
442 fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location));
443 // System.out.println(getName() + "[" + (fCheckpoints.size()
444 // - 1) + "] " + timestamp + ", " + location.toString());
445 }
446 }
447 }
448 }
4e3aa37d 449
e31e01e8 450 /**
12c155f5
FC
451 * Hook for special processing by the concrete class (called by getNextEvent())
452 *
453 * @param event
454 */
455 protected void processEvent(TmfEvent event) {
456 // Do nothing by default
457 }
458
459 // ------------------------------------------------------------------------
460 // toString
461 // ------------------------------------------------------------------------
462
463 /* (non-Javadoc)
464 * @see java.lang.Object#toString()
4e3aa37d 465 */
d4011df2 466 @Override
12c155f5
FC
467 @SuppressWarnings("nls")
468 public String toString() {
469 return "[TmfTrace (" + getName() + ")]";
470 }
471
664902f7
FC
472 // ------------------------------------------------------------------------
473 // Indexing
474 // ------------------------------------------------------------------------
475
12c155f5
FC
476 /*
477 * The purpose of the index is to keep the information needed to rapidly
478 * restore the traces contexts at regular intervals (every INDEX_PAGE_SIZE
479 * event).
480 */
83e13355 481
8e31f2d2 482 @SuppressWarnings({ "unchecked" })
a79913eb 483 protected void indexTrace(boolean waitForCompletion) {
83e13355 484
12c155f5
FC
485 final Job job = new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
486 @Override
487 protected IStatus run(IProgressMonitor monitor) {
488 while (!monitor.isCanceled()) {
489 try {
490 Thread.sleep(100);
491 } catch (InterruptedException e) {
492 return Status.OK_STATUS;
493 }
494 }
495 monitor.done();
496 return Status.OK_STATUS;
497 }
498 };
499 job.schedule();
500
501 fCheckpoints.clear();
502 ITmfEventRequest<TmfEvent> request = new TmfEventRequest<TmfEvent>(TmfEvent.class, TmfTimeRange.Eternity, TmfDataRequest.ALL_DATA,
503 fIndexPageSize, ITmfDataRequest.ExecutionType.BACKGROUND) {
504
4df4581d 505 ITmfTimestamp startTime = null;
506 ITmfTimestamp lastTime = null;
83e13355
FC
507
508 @Override
509 public void handleData(TmfEvent event) {
510 super.handleData(event);
511 if (event != null) {
4df4581d 512 ITmfTimestamp ts = event.getTimestamp();
83e13355 513 if (startTime == null)
4df4581d 514 startTime = ts.clone();
515 lastTime = ts.clone();
83e13355 516
64267c9d 517 if ((getNbRead() % fIndexPageSize) == 0) {
83e13355
FC
518 updateTrace();
519 }
520 }
521 }
522
523 @Override
524 public void handleSuccess() {
525 updateTrace();
526 }
527
05bd3318
FC
528 @Override
529 public void handleCompleted() {
12c155f5
FC
530 job.cancel();
531 super.handleCompleted();
05bd3318
FC
532 }
533
83e13355
FC
534 private void updateTrace() {
535 int nbRead = getNbRead();
536 if (nbRead != 0) {
537 fStartTime = startTime;
538 fEndTime = lastTime;
12c155f5 539 fNbEvents = nbRead;
83e13355
FC
540 notifyListeners();
541 }
542 }
543 };
544
545 sendRequest((ITmfDataRequest<T>) request);
546 if (waitForCompletion)
547 try {
548 request.waitForCompletion();
549 } catch (InterruptedException e) {
550 e.printStackTrace();
551 }
552 }
553
12c155f5
FC
554 protected void notifyListeners() {
555 broadcast(new TmfTraceUpdatedSignal(this, this, new TmfTimeRange(fStartTime, fEndTime)));
556 }
828e5592
PT
557
558 /**
559 * Set the resource to be used for bookmarks on this trace
560 * @param resource the bookmarks resource
561 */
562 public void setResource(IResource resource) {
563 fResource = resource;
564 }
565
566 /**
567 * Get the resource used for bookmarks on this trace
568 * @return the bookmarks resource or null if none is set
569 */
570 public IResource getResource() {
571 return fResource;
572 }
8c8bf09f 573}
This page took 0.069644 seconds and 5 git commands to generate.