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