Fixes the last (?) warning in LTTng stuff
[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
b0a282fb 15import java.io.File;
62d1696a 16import java.io.FileNotFoundException;
62d1696a 17import java.util.Collections;
8c8bf09f
ASL
18import java.util.Vector;
19
62d1696a
FC
20import org.eclipse.core.runtime.IProgressMonitor;
21import org.eclipse.core.runtime.IStatus;
22import org.eclipse.core.runtime.Status;
23import org.eclipse.core.runtime.jobs.Job;
fc6ccf6f 24import org.eclipse.linuxtools.tmf.component.TmfEventProvider;
8c8bf09f
ASL
25import org.eclipse.linuxtools.tmf.event.TmfEvent;
26import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
27import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
2fb2eb37
FC
28import org.eclipse.linuxtools.tmf.request.ITmfDataRequest;
29import org.eclipse.linuxtools.tmf.request.ITmfEventRequest;
ff4ed569 30import org.eclipse.linuxtools.tmf.signal.TmfTraceUpdatedSignal;
8c8bf09f
ASL
31
32/**
146a887c 33 * <b><u>TmfTrace</u></b>
8c8bf09f 34 * <p>
146a887c
FC
35 * Abstract implementation of ITmfTrace. It should be sufficient to extend this
36 * class and provide implementation for <code>getCurrentLocation()</code> and
37 * <code>seekLocation()</code>, as well as a proper parser, to have a working
4e3aa37d 38 * concrete implementation.
ff4ed569 39 * <p>
54d55ced 40 * Note: The notion of event rank is still under heavy discussion. Although
ff4ed569 41 * used by the Events View and probably useful in the general case, there
54d55ced 42 * is no easy way to implement it for LTTng (actually a strong case is being
ff4ed569
FC
43 * made that this is useless).
44 * <p>
45 * That it is not supported by LTTng does by no mean indicate that it is not
46 * useful for (just about) every other tracing tool. Therefore, this class
47 * provides a minimal (and partial) implementation of rank. However, the current
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 */
ff4ed569 52public abstract class TmfTrace<T extends TmfEvent> extends TmfEventProvider<T> implements ITmfTrace, Cloneable {
62d1696a 53
e31e01e8 54 // ------------------------------------------------------------------------
62d1696a 55 // Constants
e31e01e8 56 // ------------------------------------------------------------------------
62d1696a
FC
57
58 // The default number of events to cache
e31e01e8 59 // TODO: Make the DEFAULT_CACHE_SIZE a preference
8d2e2848 60 public static final int DEFAULT_CACHE_SIZE = 1000;
8c8bf09f 61
e31e01e8 62 // ------------------------------------------------------------------------
8c8bf09f 63 // Attributes
e31e01e8 64 // ------------------------------------------------------------------------
8c8bf09f 65
b0a282fb
FC
66 // The trace path
67 private final String fPath;
68
69 // The trace name
62d1696a
FC
70 private final String fName;
71
8d2e2848 72 // The cache page size AND checkpoints interval
9f584e4c 73 protected int fIndexPageSize;
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
82 private TmfTimeRange fTimeRange = new TmfTimeRange(TmfTimestamp.BigBang, TmfTimestamp.BigBang);
83
e31e01e8 84 // ------------------------------------------------------------------------
50adc88e 85 // Constructors
e31e01e8 86 // ------------------------------------------------------------------------
8c8bf09f 87
ff4ed569
FC
88 /**
89 * @param path
90 * @throws FileNotFoundException
91 */
92 protected TmfTrace(Class<T> type, String path) throws FileNotFoundException {
93 this(type, path, DEFAULT_CACHE_SIZE);
94 }
95
62d1696a 96 /**
e31e01e8
FC
97 * @param path
98 * @param cacheSize
62d1696a
FC
99 * @throws FileNotFoundException
100 */
e31e01e8
FC
101 protected TmfTrace(Class<T> type, String path, int cacheSize) throws FileNotFoundException {
102 super(type);
b0a282fb
FC
103 int sep = path.lastIndexOf(File.separator);
104 fName = (sep >= 0) ? path.substring(sep + 1) : path;
105 fPath = path;
9f584e4c 106 fIndexPageSize = (cacheSize > 0) ? cacheSize : DEFAULT_CACHE_SIZE;
8c8bf09f
ASL
107 }
108
ff4ed569
FC
109 /* (non-Javadoc)
110 * @see java.lang.Object#clone()
62d1696a 111 */
ff4ed569
FC
112 @SuppressWarnings("unchecked")
113 @Override
114 public TmfTrace<T> clone() throws CloneNotSupportedException {
115 TmfTrace<T> clone = (TmfTrace<T>) super.clone();
116 clone.fCheckpoints = (Vector<TmfCheckpoint>) fCheckpoints.clone();
117 clone.fTimeRange = new TmfTimeRange(fTimeRange);
118 return clone;
8c8bf09f
ASL
119 }
120
e31e01e8 121 // ------------------------------------------------------------------------
8c8bf09f 122 // Accessors
e31e01e8 123 // ------------------------------------------------------------------------
8c8bf09f 124
62d1696a 125 /**
b0a282fb 126 * @return the trace path
62d1696a 127 */
b0a282fb
FC
128 public String getPath() {
129 return fPath;
8c8bf09f
ASL
130 }
131
62d1696a 132 /**
146a887c 133 * @return the trace name
62d1696a 134 */
fc6ccf6f
FC
135 @Override
136 public String getName() {
62d1696a 137 return fName;
8c8bf09f
ASL
138 }
139
62d1696a
FC
140 /* (non-Javadoc)
141 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
142 */
4e3aa37d 143 public long getNbEvents() {
62d1696a 144 return fNbEvents;
8c8bf09f
ASL
145 }
146
b0a282fb
FC
147 /**
148 * @return the size of the cache
149 */
8d2e2848 150 public int getCacheSize() {
9f584e4c 151 return fIndexPageSize;
b0a282fb
FC
152 }
153
62d1696a
FC
154 /* (non-Javadoc)
155 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
156 */
8c8bf09f 157 public TmfTimeRange getTimeRange() {
62d1696a 158 return fTimeRange;
8c8bf09f
ASL
159 }
160
e31e01e8
FC
161 /* (non-Javadoc)
162 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime()
163 */
146a887c
FC
164 public TmfTimestamp getStartTime() {
165 return fTimeRange.getStartTime();
166 }
167
e31e01e8
FC
168 /* (non-Javadoc)
169 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime()
170 */
146a887c
FC
171 public TmfTimestamp getEndTime() {
172 return fTimeRange.getEndTime();
173 }
174
ff4ed569
FC
175 @SuppressWarnings("unchecked")
176 public Vector<TmfCheckpoint> getCheckpoints() {
177 return (Vector<TmfCheckpoint>) fCheckpoints.clone();
54d55ced
FC
178 }
179
e31e01e8 180 // ------------------------------------------------------------------------
8c8bf09f 181 // Operators
e31e01e8 182 // ------------------------------------------------------------------------
8c8bf09f 183
4e3aa37d
FC
184 protected void setTimeRange(TmfTimeRange range) {
185 fTimeRange = range;
186 }
187
188 protected void setStartTime(TmfTimestamp startTime) {
189 fTimeRange = new TmfTimeRange(startTime, fTimeRange.getEndTime());
190 }
191
192 protected void setEndTime(TmfTimestamp endTime) {
193 fTimeRange = new TmfTimeRange(fTimeRange.getStartTime(), endTime);
194 }
195
e31e01e8
FC
196 // ------------------------------------------------------------------------
197 // TmfProvider
198 // ------------------------------------------------------------------------
199
200 @Override
2fb2eb37
FC
201 public ITmfContext armRequest(ITmfDataRequest<T> request) {
202 if (request instanceof ITmfEventRequest<?>) {
203 return seekEvent(((ITmfEventRequest<T>) request).getRange().getStartTime());
e31e01e8 204 }
ff4ed569 205 return seekEvent(request.getIndex());
e31e01e8
FC
206 }
207
208 /**
209 * Return the next piece of data based on the context supplied. The context
210 * would typically be updated for the subsequent read.
211 *
212 * @param context
213 * @return
214 */
215 @SuppressWarnings("unchecked")
216 @Override
217 public T getNext(ITmfContext context) {
9f584e4c
FC
218 if (context instanceof TmfContext) {
219 return (T) getNextEvent((TmfContext) context);
e31e01e8
FC
220 }
221 return null;
222 }
223
e31e01e8
FC
224 // ------------------------------------------------------------------------
225 // ITmfTrace
226 // ------------------------------------------------------------------------
227
146a887c
FC
228 /* (non-Javadoc)
229 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
230 */
9f584e4c 231 public TmfContext seekEvent(TmfTimestamp timestamp) {
62d1696a 232
4e3aa37d
FC
233 if (timestamp == null) {
234 timestamp = TmfTimestamp.BigBang;
235 }
236
237 // First, find the right checkpoint
9f584e4c 238 int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
62d1696a 239
8d2e2848 240 // In the very likely case that the checkpoint was not found, bsearch
62d1696a
FC
241 // returns its negated would-be location (not an offset...). From that
242 // index, we can then position the stream and get the event.
243 if (index < 0) {
244 index = Math.max(0, -(index + 2));
245 }
246
247 // Position the stream at the checkpoint
452ad365 248 ITmfLocation<?> location;
e31e01e8
FC
249 synchronized (fCheckpoints) {
250 if (fCheckpoints.size() > 0) {
251 if (index >= fCheckpoints.size()) {
252 index = fCheckpoints.size() - 1;
253 }
254 location = fCheckpoints.elementAt(index).getLocation();
255 }
256 else {
257 location = null;
258 }
8d2e2848 259 }
54d55ced
FC
260 TmfContext context = seekLocation(location);
261 context.setRank(index * fIndexPageSize);
62d1696a 262
54d55ced 263 // And locate the event
ff4ed569 264 TmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype...
62d1696a
FC
265 TmfEvent event = getNextEvent(nextEventContext);
266 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
54d55ced
FC
267 context.setLocation(nextEventContext.getLocation().clone());
268 context.updateRank(1);
62d1696a
FC
269 event = getNextEvent(nextEventContext);
270 }
271
54d55ced 272 return context;
62d1696a
FC
273 }
274
146a887c
FC
275 /* (non-Javadoc)
276 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int)
277 */
9f584e4c 278 public TmfContext seekEvent(long rank) {
62d1696a
FC
279
280 // Position the stream at the previous checkpoint
9f584e4c 281 int index = (int) rank / fIndexPageSize;
452ad365 282 ITmfLocation<?> location;
e31e01e8 283 synchronized (fCheckpoints) {
54d55ced
FC
284 if (fCheckpoints.size() == 0) {
285 location = null;
286 }
287 else {
e31e01e8 288 if (index >= fCheckpoints.size()) {
54d55ced 289 index = fCheckpoints.size() - 1;
e31e01e8
FC
290 }
291 location = fCheckpoints.elementAt(index).getLocation();
292 }
8d2e2848 293 }
54d55ced 294
9f584e4c
FC
295 TmfContext context = seekLocation(location);
296 long pos = index * fIndexPageSize;
297 context.setRank(pos);
e31e01e8 298
9f584e4c 299 if (pos < rank) {
e31e01e8 300 TmfEvent event = getNextEvent(context);
9f584e4c 301 while (event != null && ++pos < rank) {
e31e01e8
FC
302 event = getNextEvent(context);
303 }
165c977c 304 }
62d1696a 305
8f50c396 306 return context;
8c8bf09f
ASL
307 }
308
146a887c
FC
309 /* (non-Javadoc)
310 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext)
311 */
9f584e4c 312 public synchronized TmfEvent getNextEvent(TmfContext context) {
e31e01e8 313 // parseEvent() does not update the context
cc6eec3e 314 TmfEvent event = parseEvent(context);
4e3aa37d 315 if (event != null) {
54d55ced
FC
316 context.setLocation(getCurrentLocation());
317 context.updateRank(1);
4e3aa37d
FC
318 processEvent(event);
319 }
146a887c
FC
320 return event;
321 }
8c8bf09f 322
4e3aa37d 323 /**
e31e01e8
FC
324 * Hook for "special" processing by the concrete class
325 * (called by getNextEvent())
326 *
146a887c
FC
327 * @param event
328 */
ff4ed569 329 protected void processEvent(TmfEvent event) {
146a887c 330 // Do nothing by default
62d1696a 331 }
4e3aa37d 332
e31e01e8
FC
333 /**
334 * To be implemented by the concrete class
4e3aa37d 335 */
452ad365
FC
336 public abstract TmfContext seekLocation(ITmfLocation<?> location);
337 public abstract ITmfLocation<?> getCurrentLocation();
9f584e4c 338 public abstract TmfEvent parseEvent(TmfContext context);
4e3aa37d 339
e31e01e8
FC
340 // ------------------------------------------------------------------------
341 // toString
342 // ------------------------------------------------------------------------
8d2e2848
FC
343
344 /* (non-Javadoc)
345 * @see java.lang.Object#toString()
346 */
347 @Override
348 public String toString() {
ff4ed569 349 return "[TmfTrace (" + fName + ")]";
8d2e2848
FC
350 }
351
e31e01e8
FC
352 // ------------------------------------------------------------------------
353 // Indexing
354 // ------------------------------------------------------------------------
146a887c 355
e31e01e8 356 /*
ff4ed569
FC
357 * The purpose of the index is to perform a pass over the trace and collect
358 * basic information that can be later used to rapidly access a trace events.
359 *
360 * The information collected:
361 * - fCheckpoints, the list of evenly separated checkpoints (timestamp + location)
362 * - fTimeRange, the trace time span
363 * - fNbEvents, the number of events in the trace
e31e01e8 364 *
ff4ed569 365 * NOTE: Doesn't work for streaming traces.
e31e01e8
FC
366 */
367
368 private IndexingJob job;
9f584e4c
FC
369
370 // Indicates that an indexing job is already running
cbd4ad82 371 private boolean fIndexing = false;
9f584e4c 372 private Boolean fIndexed = false;
e31e01e8
FC
373
374 public void indexTrace(boolean waitForCompletion) {
ff4ed569 375 synchronized (this) {
9f584e4c 376 if (fIndexed || fIndexing) {
4e3aa37d
FC
377 return;
378 }
379 fIndexing = true;
380 }
381
e31e01e8 382 job = new IndexingJob("Indexing " + fName);
62d1696a 383 job.schedule();
4e3aa37d 384
e31e01e8 385 if (waitForCompletion) {
4e3aa37d
FC
386 try {
387 job.join();
388 } catch (InterruptedException e) {
4e3aa37d
FC
389 e.printStackTrace();
390 }
52e28818 391 }
62d1696a
FC
392 }
393
394 private class IndexingJob extends Job {
395
396 public IndexingJob(String name) {
397 super(name);
398 }
399
400 /* (non-Javadoc)
401 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
402 */
403 @Override
404 protected IStatus run(IProgressMonitor monitor) {
405
62d1696a
FC
406 monitor.beginTask("Indexing " + fName, IProgressMonitor.UNKNOWN);
407
e31e01e8
FC
408 int nbEvents = 0;
409 TmfTimestamp startTime = null;
410 TmfTimestamp lastTime = null;
411
9f584e4c
FC
412 // Reset the index
413 fCheckpoints = new Vector<TmfCheckpoint>();
e31e01e8 414
98029bc9
FC
415 try {
416 // Position the trace at the beginning
9f584e4c 417 TmfContext context = seekLocation(null);
54d55ced 418 ITmfLocation<?> location = context.getLocation().clone();
e31e01e8 419
9f584e4c 420 // Get the first event
e31e01e8 421 TmfEvent event = getNextEvent(context);
9f584e4c
FC
422 if (event != null) {
423 startTime = new TmfTimestamp(event.getTimestamp());
424 }
425
426 // Index the trace
427 while (event != null) {
e31e01e8 428 lastTime = event.getTimestamp();
9f584e4c 429 if ((nbEvents++ % fIndexPageSize) == 0) {
e31e01e8 430 lastTime = new TmfTimestamp(event.getTimestamp());
8f50c396 431 fCheckpoints.add(new TmfCheckpoint(lastTime, location));
4e3aa37d 432
62d1696a 433 monitor.worked(1);
4e3aa37d 434
62d1696a
FC
435 // Check monitor *after* fCheckpoints has been updated
436 if (monitor.isCanceled()) {
4e3aa37d 437 monitor.done();
62d1696a
FC
438 return Status.CANCEL_STATUS;
439 }
165c977c 440 }
165c977c 441
e31e01e8 442 // We will need this location at the next iteration
9f584e4c 443 if ((nbEvents % fIndexPageSize) == 0) {
54d55ced 444 location = context.getLocation().clone();
e31e01e8
FC
445 }
446
447 event = getNextEvent(context);
62d1696a
FC
448 }
449 }
450 finally {
451 synchronized(this) {
98029bc9 452 fNbEvents = nbEvents;
62d1696a 453 fTimeRange = new TmfTimeRange(startTime, lastTime);
4e3aa37d 454 fIndexing = false;
9f584e4c 455 fIndexed = true;
62d1696a 456 }
36548af3 457 notifyListeners(fTimeRange);
62d1696a 458 monitor.done();
8c8bf09f 459 }
62d1696a 460
4e3aa37d 461 return Status.OK_STATUS;
62d1696a 462 }
8c8bf09f
ASL
463 }
464
a3fe52fc 465 protected void notifyListeners(TmfTimeRange range) {
e31e01e8 466 broadcast(new TmfTraceUpdatedSignal(this, this, range));
146a887c
FC
467 }
468
8c8bf09f 469}
This page took 0.055035 seconds and 5 git commands to generate.