Finalize ITmfTrace API
[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;
72f1e62a 28import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
4df4581d 29import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
6c13869b
FC
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 */
72f1e62a 55public abstract class TmfTrace<T extends ITmfEvent> 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
a4115405
FC
85 private ITmfTimestamp fStartTime = TmfTimestamp.BIG_CRUNCH;
86 private ITmfTimestamp fEndTime = TmfTimestamp.BIG_BANG;
62d1696a 87
a1091415 88 // The properties resource
828e5592
PT
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
3118edf1 100 public void initTrace(String name, String path, Class<T> eventType) throws FileNotFoundException {
12c155f5 101 fPath = path;
96c6806f
PT
102 if (name != null) {
103 fTraceName = name;
104 }
c5b45b39
FC
105 if (fTraceName == null) {
106 fTraceName = ""; //$NON-NLS-1$
00641a97 107 if (path != null) {
c7e2f194 108 int sep = path.lastIndexOf(Path.SEPARATOR);
c5b45b39 109 fTraceName = (sep >= 0) ? path.substring(sep + 1) : path;
00641a97 110 }
12c155f5 111 }
c5b45b39 112 super.init(fTraceName, eventType);
12c155f5
FC
113 }
114
115 @Override
116 public boolean validate(IProject project, String path) {
117 File file = new File(path);
118 return file.exists();
119 }
120
ff4ed569
FC
121 /**
122 * @param path
123 * @throws FileNotFoundException
124 */
ce785d7d 125 protected TmfTrace(String name, Class<T> type, String path) throws FileNotFoundException {
12c155f5 126 this(name, type, path, DEFAULT_INDEX_PAGE_SIZE, true);
ff4ed569
FC
127 }
128
62d1696a 129 /**
e31e01e8
FC
130 * @param path
131 * @param cacheSize
62d1696a
FC
132 * @throws FileNotFoundException
133 */
ce785d7d 134 protected TmfTrace(String name, Class<T> type, String path, int cacheSize) throws FileNotFoundException {
12c155f5 135 this(name, type, path, cacheSize, true);
05bd3318
FC
136 }
137
138 /**
139 * @param path
140 * @param indexTrace
141 * @throws FileNotFoundException
142 */
143 protected TmfTrace(String name, Class<T> type, String path, boolean indexTrace) throws FileNotFoundException {
12c155f5 144 this(name, type, path, DEFAULT_INDEX_PAGE_SIZE, indexTrace);
05bd3318
FC
145 }
146
147 /**
148 * @param path
149 * @param cacheSize
150 * @param indexTrace
151 * @throws FileNotFoundException
152 */
3118edf1 153 protected TmfTrace(String name, Class<T> type, String path, int indexPageSize, boolean indexTrace) throws FileNotFoundException {
00641a97 154 super();
3118edf1
FC
155 initTrace(name, path, type);
156 fIndexPageSize = (indexPageSize >0) ? indexPageSize : DEFAULT_INDEX_PAGE_SIZE;
157 if (indexTrace)
158 indexTrace(false);
8c8bf09f
ASL
159 }
160
ff4ed569 161 @SuppressWarnings("unchecked")
12c155f5
FC
162 @Override
163 public TmfTrace<T> clone() throws CloneNotSupportedException {
164 TmfTrace<T> clone = (TmfTrace<T>) super.clone();
165 clone.fCheckpoints = fCheckpoints;
4df4581d 166 clone.fStartTime = fStartTime.clone();
167 clone.fEndTime = fEndTime.clone();
12c155f5 168 return clone;
8c8bf09f
ASL
169 }
170
e31e01e8 171 // ------------------------------------------------------------------------
8c8bf09f 172 // Accessors
e31e01e8 173 // ------------------------------------------------------------------------
8c8bf09f 174
62d1696a 175 /**
b0a282fb 176 * @return the trace path
62d1696a 177 */
d4011df2 178 @Override
12c155f5 179 public String getPath() {
b0a282fb 180 return fPath;
8c8bf09f
ASL
181 }
182
62d1696a
FC
183 /* (non-Javadoc)
184 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
185 */
d4011df2 186 @Override
beae214a 187 public synchronized long getNbEvents() {
62d1696a 188 return fNbEvents;
8c8bf09f
ASL
189 }
190
b0a282fb
FC
191 /**
192 * @return the size of the cache
193 */
d4011df2 194 @Override
3118edf1 195 public int getIndexPageSize() {
9f584e4c 196 return fIndexPageSize;
b0a282fb
FC
197 }
198
62d1696a
FC
199 /* (non-Javadoc)
200 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
201 */
d4011df2 202 @Override
12c155f5 203 public TmfTimeRange getTimeRange() {
cb866e08 204 return new TmfTimeRange(fStartTime, fEndTime);
8c8bf09f
ASL
205 }
206
e31e01e8
FC
207 /* (non-Javadoc)
208 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime()
209 */
d4011df2 210 @Override
4df4581d 211 public ITmfTimestamp getStartTime() {
12c155f5 212 return fStartTime;
146a887c
FC
213 }
214
e31e01e8
FC
215 /* (non-Javadoc)
216 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime()
217 */
d4011df2 218 @Override
4df4581d 219 public ITmfTimestamp getEndTime() {
12c155f5 220 return fEndTime;
146a887c
FC
221 }
222
1b70b6dc
PT
223 /* (non-Javadoc)
224 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
225 */
226 @Override
227 public long getStreamingInterval() {
228 return 0;
229 }
230
ff4ed569 231 @SuppressWarnings("unchecked")
12c155f5
FC
232 public Vector<TmfCheckpoint> getCheckpoints() {
233 return (Vector<TmfCheckpoint>) fCheckpoints.clone();
54d55ced
FC
234 }
235
abfad0aa 236 /**
12c155f5
FC
237 * Returns the rank of the first event with the requested timestamp. If none, returns the index of the next event
238 * (if any).
239 *
0d9a6d76
FC
240 * @param timestamp the requested event timestamp
241 * @return the corresponding event rank
abfad0aa 242 */
d4011df2 243 @Override
4df4581d 244 public long getRank(ITmfTimestamp timestamp) {
abfad0aa
FC
245 TmfContext context = seekEvent(timestamp);
246 return context.getRank();
247 }
248
e31e01e8 249 // ------------------------------------------------------------------------
8c8bf09f 250 // Operators
e31e01e8 251 // ------------------------------------------------------------------------
8c8bf09f 252
4e3aa37d 253 protected void setTimeRange(TmfTimeRange range) {
12c155f5
FC
254 fStartTime = range.getStartTime();
255 fEndTime = range.getEndTime();
4e3aa37d
FC
256 }
257
d7dbf09a 258 protected void setStartTime(ITmfTimestamp startTime) {
12c155f5 259 fStartTime = startTime;
4e3aa37d
FC
260 }
261
dfee01ae 262 protected void setEndTime(ITmfTimestamp endTime) {
12c155f5
FC
263 fEndTime = endTime;
264 }
265
266 // ------------------------------------------------------------------------
267 // TmfProvider
268 // ------------------------------------------------------------------------
269
270 @Override
271 public ITmfContext armRequest(ITmfDataRequest<T> request) {
272 if (request instanceof ITmfEventRequest<?>
a4115405 273 && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest<T>) request).getRange().getStartTime()) && request.getIndex() == 0) {
12c155f5
FC
274 ITmfContext context = seekEvent(((ITmfEventRequest<T>) request).getRange().getStartTime());
275 ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
276 return context;
277
278 }
279 return seekEvent(request.getIndex());
280 }
281
282 /**
283 * Return the next piece of data based on the context supplied. The context would typically be updated for the
284 * subsequent read.
285 *
286 * @param context
0d9a6d76 287 * @return the event referred to by context
12c155f5
FC
288 */
289 @SuppressWarnings("unchecked")
290 @Override
291 public T getNext(ITmfContext context) {
292 if (context instanceof TmfContext) {
293 return (T) getNextEvent((TmfContext) context);
294 }
295 return null;
296 }
297
298 // ------------------------------------------------------------------------
299 // ITmfTrace
300 // ------------------------------------------------------------------------
e31e01e8 301
34ccf9a9
AM
302 @Override
303 public abstract TmfContext seekLocation(ITmfLocation<?> location);
304
146a887c
FC
305 /* (non-Javadoc)
306 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
307 */
d4011df2 308 @Override
beae214a 309 public TmfContext seekEvent(ITmfTimestamp ts) {
62d1696a 310
beae214a 311 ITmfTimestamp timestamp = ts;
12c155f5 312 if (timestamp == null) {
a4115405 313 timestamp = TmfTimestamp.BIG_BANG;
12c155f5 314 }
4e3aa37d 315
12c155f5
FC
316 // First, find the right checkpoint
317 int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
62d1696a 318
8d2e2848 319 // In the very likely case that the checkpoint was not found, bsearch
62d1696a
FC
320 // returns its negated would-be location (not an offset...). From that
321 // index, we can then position the stream and get the event.
322 if (index < 0) {
323 index = Math.max(0, -(index + 2));
324 }
325
326 // Position the stream at the checkpoint
452ad365 327 ITmfLocation<?> location;
e31e01e8 328 synchronized (fCheckpoints) {
beae214a 329 if (!fCheckpoints.isEmpty()) {
12c155f5
FC
330 if (index >= fCheckpoints.size()) {
331 index = fCheckpoints.size() - 1;
332 }
333 location = fCheckpoints.elementAt(index).getLocation();
334 } else {
335 location = null;
336 }
8d2e2848 337 }
54d55ced
FC
338 TmfContext context = seekLocation(location);
339 context.setRank(index * fIndexPageSize);
62d1696a 340
54d55ced 341 // And locate the event
ff4ed569 342 TmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype...
72f1e62a 343 ITmfEvent event = getNextEvent(nextEventContext);
62d1696a 344 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
12c155f5
FC
345 context.setLocation(nextEventContext.getLocation().clone());
346 context.updateRank(1);
347 event = getNextEvent(nextEventContext);
62d1696a
FC
348 }
349
54d55ced 350 return context;
62d1696a
FC
351 }
352
146a887c
FC
353 /* (non-Javadoc)
354 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int)
355 */
d4011df2 356 @Override
12c155f5 357 public TmfContext seekEvent(long rank) {
62d1696a
FC
358
359 // Position the stream at the previous checkpoint
9f584e4c 360 int index = (int) rank / fIndexPageSize;
452ad365 361 ITmfLocation<?> location;
e31e01e8 362 synchronized (fCheckpoints) {
beae214a 363 if (fCheckpoints.isEmpty()) {
12c155f5
FC
364 location = null;
365 } else {
366 if (index >= fCheckpoints.size()) {
367 index = fCheckpoints.size() - 1;
368 }
369 location = fCheckpoints.elementAt(index).getLocation();
370 }
8d2e2848 371 }
54d55ced 372
9f584e4c
FC
373 TmfContext context = seekLocation(location);
374 long pos = index * fIndexPageSize;
375 context.setRank(pos);
e31e01e8 376
9f584e4c 377 if (pos < rank) {
72f1e62a 378 ITmfEvent event = getNextEvent(context);
9f584e4c 379 while (event != null && ++pos < rank) {
12c155f5 380 event = getNextEvent(context);
e31e01e8 381 }
165c977c 382 }
62d1696a 383
8f50c396 384 return context;
8c8bf09f
ASL
385 }
386
12c155f5
FC
387 /*
388 * (non-Javadoc)
389 *
390 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.
391 * linuxtools.tmf.trace.ITmfTrace.TraceContext)
392 */
393 @Override
a1440d1f 394 public synchronized ITmfEvent getNextEvent(ITmfContext context) {
12c155f5 395 // parseEvent() does not update the context
72f1e62a 396 ITmfEvent event = parseEvent(context);
12c155f5
FC
397 if (event != null) {
398 updateIndex(context, context.getRank(), event.getTimestamp());
399 context.setLocation(getCurrentLocation());
400 context.updateRank(1);
401 processEvent(event);
402 }
403 return event;
404 }
550d787e 405
4df4581d 406 protected synchronized void updateIndex(ITmfContext context, long rank, ITmfTimestamp timestamp) {
12c155f5
FC
407 if (fStartTime.compareTo(timestamp, false) > 0)
408 fStartTime = timestamp;
409 if (fEndTime.compareTo(timestamp, false) < 0)
410 fEndTime = timestamp;
411 if (context.isValidRank()) {
412 if (fNbEvents <= rank)
413 fNbEvents = rank + 1;
414 // Build the index as we go along
415 if ((rank % fIndexPageSize) == 0) {
416 // Determine the table position
417 long position = rank / fIndexPageSize;
418 // Add new entry at proper location (if empty)
419 if (fCheckpoints.size() == position) {
420 ITmfLocation<?> location = context.getLocation().clone();
421 fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location));
422 // System.out.println(getName() + "[" + (fCheckpoints.size()
423 // - 1) + "] " + timestamp + ", " + location.toString());
424 }
425 }
426 }
427 }
4e3aa37d 428
e31e01e8 429 /**
12c155f5
FC
430 * Hook for special processing by the concrete class (called by getNextEvent())
431 *
432 * @param event
433 */
72f1e62a 434 protected void processEvent(ITmfEvent event) {
12c155f5
FC
435 // Do nothing by default
436 }
437
438 // ------------------------------------------------------------------------
439 // toString
440 // ------------------------------------------------------------------------
441
442 /* (non-Javadoc)
443 * @see java.lang.Object#toString()
4e3aa37d 444 */
d4011df2 445 @Override
12c155f5
FC
446 @SuppressWarnings("nls")
447 public String toString() {
448 return "[TmfTrace (" + getName() + ")]";
449 }
450
664902f7
FC
451 // ------------------------------------------------------------------------
452 // Indexing
453 // ------------------------------------------------------------------------
454
12c155f5
FC
455 /*
456 * The purpose of the index is to keep the information needed to rapidly
457 * restore the traces contexts at regular intervals (every INDEX_PAGE_SIZE
458 * event).
459 */
83e13355 460
8636b448 461 @Override
8e31f2d2 462 @SuppressWarnings({ "unchecked" })
8636b448 463 public void indexTrace(boolean waitForCompletion) {
83e13355 464
12c155f5
FC
465 final Job job = new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
466 @Override
467 protected IStatus run(IProgressMonitor monitor) {
468 while (!monitor.isCanceled()) {
469 try {
470 Thread.sleep(100);
471 } catch (InterruptedException e) {
472 return Status.OK_STATUS;
473 }
474 }
475 monitor.done();
476 return Status.OK_STATUS;
477 }
478 };
479 job.schedule();
480
481 fCheckpoints.clear();
a4115405 482 ITmfEventRequest<ITmfEvent> request = new TmfEventRequest<ITmfEvent>(ITmfEvent.class, TmfTimeRange.ETERNITY, TmfDataRequest.ALL_DATA,
12c155f5
FC
483 fIndexPageSize, ITmfDataRequest.ExecutionType.BACKGROUND) {
484
4df4581d 485 ITmfTimestamp startTime = null;
486 ITmfTimestamp lastTime = null;
83e13355
FC
487
488 @Override
72f1e62a 489 public void handleData(ITmfEvent event) {
83e13355
FC
490 super.handleData(event);
491 if (event != null) {
4df4581d 492 ITmfTimestamp ts = event.getTimestamp();
83e13355 493 if (startTime == null)
4df4581d 494 startTime = ts.clone();
495 lastTime = ts.clone();
83e13355 496
64267c9d 497 if ((getNbRead() % fIndexPageSize) == 0) {
83e13355
FC
498 updateTrace();
499 }
500 }
501 }
502
503 @Override
504 public void handleSuccess() {
505 updateTrace();
506 }
507
05bd3318
FC
508 @Override
509 public void handleCompleted() {
12c155f5
FC
510 job.cancel();
511 super.handleCompleted();
05bd3318
FC
512 }
513
beae214a 514 private synchronized void updateTrace() {
83e13355
FC
515 int nbRead = getNbRead();
516 if (nbRead != 0) {
517 fStartTime = startTime;
518 fEndTime = lastTime;
12c155f5 519 fNbEvents = nbRead;
83e13355
FC
520 notifyListeners();
521 }
522 }
523 };
524
525 sendRequest((ITmfDataRequest<T>) request);
526 if (waitForCompletion)
527 try {
528 request.waitForCompletion();
529 } catch (InterruptedException e) {
beae214a 530// e.printStackTrace();
83e13355
FC
531 }
532 }
533
12c155f5
FC
534 protected void notifyListeners() {
535 broadcast(new TmfTraceUpdatedSignal(this, this, new TmfTimeRange(fStartTime, fEndTime)));
536 }
828e5592 537
a1091415
PT
538 /*
539 * (non-Javadoc)
540 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#setResource(org.eclipse.core.resources.IResource)
828e5592 541 */
a1091415 542 @Override
828e5592
PT
543 public void setResource(IResource resource) {
544 fResource = resource;
545 }
546
a1091415
PT
547 /*
548 * (non-Javadoc)
549 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
828e5592 550 */
a1091415 551 @Override
828e5592
PT
552 public IResource getResource() {
553 return fResource;
554 }
8c8bf09f 555}
This page took 0.07525 seconds and 5 git commands to generate.