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