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