Monster fix: TMF model update + corresponding LTTng adaptations + JUnits
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / trace / TmfTrace.java
CommitLineData
8c8bf09f 1/*******************************************************************************
165c977c 2 * Copyright (c) 2009 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;
8d2e2848 24import org.eclipse.linuxtools.tmf.component.TmfComponent;
8c8bf09f
ASL
25import org.eclipse.linuxtools.tmf.event.TmfEvent;
26import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
27import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
4e3aa37d
FC
28import org.eclipse.linuxtools.tmf.request.ITmfRequestHandler;
29import org.eclipse.linuxtools.tmf.request.TmfDataRequest;
8c8bf09f
ASL
30
31/**
146a887c 32 * <b><u>TmfTrace</u></b>
8c8bf09f 33 * <p>
146a887c
FC
34 * Abstract implementation of ITmfTrace. It should be sufficient to extend this
35 * class and provide implementation for <code>getCurrentLocation()</code> and
36 * <code>seekLocation()</code>, as well as a proper parser, to have a working
4e3aa37d
FC
37 * concrete implementation.
38 *
39 * TODO: Add support for live streaming (notifications, incremental indexing, ...)
8c8bf09f 40 */
8d2e2848 41public abstract class TmfTrace extends TmfComponent implements ITmfTrace, ITmfRequestHandler<TmfEvent> {
62d1696a
FC
42
43 // ========================================================================
44 // Constants
45 // ========================================================================
46
47 // The default number of events to cache
8d2e2848 48 public static final int DEFAULT_CACHE_SIZE = 1000;
8c8bf09f 49
165c977c 50 // ========================================================================
8c8bf09f 51 // Attributes
165c977c 52 // ========================================================================
8c8bf09f 53
b0a282fb
FC
54 // The trace path
55 private final String fPath;
56
57 // The trace name
62d1696a
FC
58 private final String fName;
59
8d2e2848
FC
60 // The cache page size AND checkpoints interval
61 private final int fCacheSize;
62d1696a 62
4e3aa37d
FC
63 // Indicate if the stream should be pre-indexed
64 private final boolean fWaitForIndexCompletion;
52e28818 65
62d1696a 66 // The set of event stream checkpoints (for random access)
146a887c 67 protected Vector<TmfTraceCheckpoint> fCheckpoints = new Vector<TmfTraceCheckpoint>();
62d1696a
FC
68
69 // The number of events collected
4e3aa37d 70 private long fNbEvents = 0;
62d1696a
FC
71
72 // The time span of the event stream
73 private TmfTimeRange fTimeRange = new TmfTimeRange(TmfTimestamp.BigBang, TmfTimestamp.BigBang);
74
165c977c 75 // ========================================================================
50adc88e 76 // Constructors
165c977c 77 // ========================================================================
8c8bf09f 78
62d1696a 79 /**
146a887c 80 * @param name
52e28818 81 * @param pageSize
8d2e2848 82 * @param data.index
62d1696a
FC
83 * @throws FileNotFoundException
84 */
4e3aa37d 85 protected TmfTrace(String path, int pageSize, boolean waitForIndexCompletion) throws FileNotFoundException {
8d2e2848 86 super();
b0a282fb
FC
87 int sep = path.lastIndexOf(File.separator);
88 fName = (sep >= 0) ? path.substring(sep + 1) : path;
89 fPath = path;
8d2e2848 90 fCacheSize = (pageSize > 0) ? pageSize : DEFAULT_CACHE_SIZE;
4e3aa37d 91 fWaitForIndexCompletion = waitForIndexCompletion;
52e28818
FC
92 }
93
94 /**
95 * @param name
96 * @param cacheSize
97 * @throws FileNotFoundException
98 */
4e3aa37d 99 protected TmfTrace(String name, boolean waitForIndexCompletion) throws FileNotFoundException {
8d2e2848 100 this(name, DEFAULT_CACHE_SIZE, waitForIndexCompletion);
52e28818
FC
101 }
102
103 /**
104 * @param name
105 * @param cacheSize
106 * @throws FileNotFoundException
107 */
108 protected TmfTrace(String name, int pageSize) throws FileNotFoundException {
109 this(name, pageSize, false);
8c8bf09f
ASL
110 }
111
62d1696a 112 /**
146a887c 113 * @param name
62d1696a
FC
114 * @throws FileNotFoundException
115 */
146a887c 116 protected TmfTrace(String name) throws FileNotFoundException {
8d2e2848 117 this(name, DEFAULT_CACHE_SIZE, false);
8c8bf09f
ASL
118 }
119
165c977c 120 // ========================================================================
8c8bf09f 121 // Accessors
165c977c 122 // ========================================================================
8c8bf09f 123
62d1696a 124 /**
b0a282fb 125 * @return the trace path
62d1696a 126 */
b0a282fb
FC
127 public String getPath() {
128 return fPath;
8c8bf09f
ASL
129 }
130
62d1696a 131 /**
146a887c 132 * @return the trace name
62d1696a
FC
133 */
134 public String getName() {
135 return fName;
8c8bf09f
ASL
136 }
137
62d1696a
FC
138 /* (non-Javadoc)
139 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
140 */
4e3aa37d 141 public long getNbEvents() {
62d1696a 142 return fNbEvents;
8c8bf09f
ASL
143 }
144
b0a282fb
FC
145 /**
146 * @return the size of the cache
147 */
8d2e2848
FC
148 public int getCacheSize() {
149 return fCacheSize;
b0a282fb
FC
150 }
151
62d1696a
FC
152 /* (non-Javadoc)
153 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
154 */
8c8bf09f 155 public TmfTimeRange getTimeRange() {
62d1696a 156 return fTimeRange;
8c8bf09f
ASL
157 }
158
146a887c
FC
159 public TmfTimestamp getStartTime() {
160 return fTimeRange.getStartTime();
161 }
162
163 public TmfTimestamp getEndTime() {
164 return fTimeRange.getEndTime();
165 }
166
4e3aa37d 167 protected long getIndex(TmfTimestamp timestamp) {
146a887c 168 TmfTraceContext context = seekEvent(timestamp);
8d2e2848 169 return context.getIndex();
8c8bf09f
ASL
170 }
171
4e3aa37d 172 protected TmfTimestamp getTimestamp(int index) {
146a887c 173 TmfTraceContext context = seekEvent(index);
8d2e2848 174 return context.getTimestamp();
82b08e62
FC
175 }
176
165c977c 177 // ========================================================================
8c8bf09f 178 // Operators
165c977c 179 // ========================================================================
8c8bf09f 180
4e3aa37d
FC
181 protected void setTimeRange(TmfTimeRange range) {
182 fTimeRange = range;
183 }
184
185 protected void setStartTime(TmfTimestamp startTime) {
186 fTimeRange = new TmfTimeRange(startTime, fTimeRange.getEndTime());
187 }
188
189 protected void setEndTime(TmfTimestamp endTime) {
190 fTimeRange = new TmfTimeRange(fTimeRange.getStartTime(), endTime);
191 }
192
146a887c
FC
193 /* (non-Javadoc)
194 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
195 */
196 public TmfTraceContext seekEvent(TmfTimestamp timestamp) {
62d1696a 197
4e3aa37d
FC
198 if (timestamp == null) {
199 timestamp = TmfTimestamp.BigBang;
200 }
201
202 // First, find the right checkpoint
146a887c 203 int index = Collections.binarySearch(fCheckpoints, new TmfTraceCheckpoint(timestamp, 0));
62d1696a 204
8d2e2848 205 // In the very likely case that the checkpoint was not found, bsearch
62d1696a
FC
206 // returns its negated would-be location (not an offset...). From that
207 // index, we can then position the stream and get the event.
208 if (index < 0) {
209 index = Math.max(0, -(index + 2));
210 }
211
212 // Position the stream at the checkpoint
8d2e2848
FC
213 Object location;
214 synchronized (fCheckpoints) { //Just in case we are re-indexing
215 location = (index < fCheckpoints.size()) ? fCheckpoints.elementAt(index).getLocation() : null;
216 }
4e3aa37d 217 TmfTraceContext nextEventContext = seekLocation(location);
8d2e2848 218 nextEventContext.setIndex(index * fCacheSize);
4e3aa37d 219 TmfTraceContext currentEventContext = new TmfTraceContext(nextEventContext);
62d1696a
FC
220
221 // And get the event
222 TmfEvent event = getNextEvent(nextEventContext);
223 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
8d2e2848
FC
224 currentEventContext.setLocation(nextEventContext.getLocation());
225 currentEventContext.incrIndex();
62d1696a
FC
226 event = getNextEvent(nextEventContext);
227 }
228
8d2e2848 229 currentEventContext.setTimestamp((event != null) ? event.getTimestamp() : null);
62d1696a
FC
230 return currentEventContext;
231 }
232
146a887c
FC
233 /* (non-Javadoc)
234 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int)
235 */
4e3aa37d 236 public TmfTraceContext seekEvent(long position) {
62d1696a
FC
237
238 // Position the stream at the previous checkpoint
8d2e2848
FC
239 int index = (int) position / fCacheSize;
240 Object location;
241 synchronized (fCheckpoints) { //Just in case we are re-indexing
242 location = (index < fCheckpoints.size()) ? fCheckpoints.elementAt(index).getLocation() : null;
243 }
4e3aa37d 244 TmfTraceContext nextEventContext = seekLocation(location);
8d2e2848 245 nextEventContext.setIndex(index * fCacheSize);
146a887c 246 TmfTraceContext currentEventContext = new TmfTraceContext(nextEventContext);
62d1696a
FC
247
248 // And locate the event (if it exists)
62d1696a 249 TmfEvent event = getNextEvent(nextEventContext);
8d2e2848
FC
250 while (event != null && currentEventContext.getIndex() < position) {
251 currentEventContext.setLocation(nextEventContext.getLocation());
252 currentEventContext.setTimestamp(event.getTimestamp());
253 currentEventContext.incrIndex();
62d1696a 254 event = getNextEvent(nextEventContext);
165c977c 255 }
62d1696a
FC
256
257 return currentEventContext;
8c8bf09f
ASL
258 }
259
146a887c
FC
260 /* (non-Javadoc)
261 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext)
262 */
8d2e2848
FC
263 public TmfEvent getNextEvent(TmfTraceContext context) {
264 // parseEvent updates the context
cc6eec3e 265 TmfEvent event = parseEvent(context);
4e3aa37d 266 if (event != null) {
4e3aa37d
FC
267 processEvent(event);
268 }
146a887c
FC
269 return event;
270 }
8c8bf09f 271
4e3aa37d 272 /**
8d2e2848 273 * To be implemented by the subclass.
4e3aa37d
FC
274 */
275 public abstract Object getCurrentLocation();
cc6eec3e 276 public abstract TmfEvent parseEvent(TmfTraceContext context);
4e3aa37d 277
146a887c
FC
278 /**
279 * Hook for "special" processing by the extending class
280 * @param event
281 */
282 public void processEvent(TmfEvent event) {
283 // Do nothing by default
62d1696a 284 }
146a887c
FC
285
286 // ========================================================================
4e3aa37d
FC
287 // ITmfRequestHandler
288 // ========================================================================
289
290 /* (non-Javadoc)
291 * @see org.eclipse.linuxtools.tmf.eventlog.ITmfRequestHandler#processRequest(org.eclipse.linuxtools.tmf.eventlog.TmfDataRequest, boolean)
292 */
293 public void processRequest(TmfDataRequest<TmfEvent> request, boolean waitForCompletion) {
294
295 // Process the request
8d2e2848 296 processDataRequest(request);
4e3aa37d
FC
297
298 // Wait for completion if needed
299 if (waitForCompletion) {
300 request.waitForCompletion();
301 }
302 }
303
304 /**
305 * Process a data request
306 *
307 * @param request
308 */
8d2e2848 309 private void processDataRequest(final TmfDataRequest<TmfEvent> request) {
4e3aa37d
FC
310
311 // Initialize the trace context
312 final TmfTraceContext context = (request.getRange() != null) ?
313 seekEvent(request.getRange().getStartTime()) :
314 seekEvent(request.getIndex());
315
316 final TmfTimestamp endTime = (request.getRange() != null) ?
317 request.getRange().getEndTime() :
318 TmfTimestamp.BigCrunch;
319
320 // Process the request
321 Thread thread = new Thread() {
322
323 @Override
324 public void run() {
325 // Extract the general request information
326 int blockSize = request.getBlockize();
28b94d61 327 int nbRequestedEvents = request.getNbRequestedEvents();
4e3aa37d
FC
328 if (nbRequestedEvents == -1) {
329 nbRequestedEvents = Integer.MAX_VALUE;
330 }
331
332 // Create the result buffer
333 Vector<TmfEvent> events = new Vector<TmfEvent>();
334 int nbEvents = 0;
335
336 // Get the ordered events
337 TmfEvent event = getNextEvent(context);
338 while (!request.isCancelled() && nbEvents < nbRequestedEvents && event != null
339 && event.getTimestamp().compareTo(endTime, false) <= 0)
340 {
341 events.add(event);
342 if (++nbEvents % blockSize == 0) {
8d2e2848 343 pushData(request, events);
4e3aa37d
FC
344 }
345 // To avoid an unnecessary read passed the last event requested
346 if (nbEvents < nbRequestedEvents)
347 event = getNextEvent(context);
348 }
8d2e2848 349 pushData(request, events);
4e3aa37d
FC
350 request.done();
351 }
352 };
353 thread.start();
354 }
355
8d2e2848
FC
356 /**
357 * Format the result data and notify the requester.
358 * Note: after handling, the data is *removed*.
359 *
360 * @param request
361 * @param events
362 */
363 private void pushData(TmfDataRequest<TmfEvent> request, Vector<TmfEvent> events) {
364 TmfEvent[] result = new TmfEvent[events.size()];
365 events.toArray(result);
366 request.setData(result);
367 request.handleData();
368 events.removeAllElements();
369 }
370
371 /* (non-Javadoc)
372 * @see java.lang.Object#toString()
373 */
374 @Override
375 public String toString() {
376 return "[TmfTrace (" + fName + "]";
377 }
378
4e3aa37d
FC
379 // ========================================================================
380 // Trace indexing. Essentially, parse the stream asynchronously and build
146a887c
FC
381 // the checkpoints index. This index is used to quickly find an event based
382 // on a timestamp or an index.
383 // ========================================================================
384
4e3aa37d 385 private Boolean fIndexing = false;
146a887c 386 public void indexStream() {
4e3aa37d
FC
387 synchronized (fIndexing) {
388 if (fIndexing) {
389 return;
390 }
391 fIndexing = true;
392 }
393
394 final IndexingJob job = new IndexingJob("Indexing " + fName);
62d1696a 395 job.schedule();
4e3aa37d
FC
396
397 if (fWaitForIndexCompletion) {
398 try {
399 job.join();
400 } catch (InterruptedException e) {
401 // TODO Auto-generated catch block
402 e.printStackTrace();
403 }
52e28818 404 }
62d1696a
FC
405 }
406
407 private class IndexingJob extends Job {
408
409 public IndexingJob(String name) {
410 super(name);
411 }
412
413 /* (non-Javadoc)
414 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
415 */
416 @Override
417 protected IStatus run(IProgressMonitor monitor) {
418
419 int nbEvents = 0;
420 TmfTimestamp startTime = new TmfTimestamp();
421 TmfTimestamp lastTime = new TmfTimestamp();
62d1696a
FC
422
423 monitor.beginTask("Indexing " + fName, IProgressMonitor.UNKNOWN);
424
98029bc9
FC
425 try {
426 // Position the trace at the beginning
427 TmfTraceContext context = seekLocation(null);
428 if (context.getTimestamp() == null) {
4e3aa37d 429 return Status.OK_STATUS;
165c977c 430 }
98029bc9
FC
431 // FIXME: LTTng hack - start
432// fCheckpoints.add(new TmfTraceCheckpoint(context.getTimestamp(), context.getLocation())); // TMF
433 // FIXME: LTTng hack - end
434
435 TmfEvent event;
436 startTime = context.getTimestamp();
437 lastTime = context.getTimestamp();
438 while ((event = getNextEvent(context)) != null) {
439 TmfTimestamp timestamp = context.getTimestamp();
440 if (timestamp != null) {
441 lastTime = timestamp;
442 }
443 // FIXME: LTTng hack - start
444// if (((++nbEvents % fCacheSize) == 0) && (timestamp != null)) { // TMF
445 if (((nbEvents++ % fCacheSize) == 0) && (timestamp != null)) { // LTTng
446 // FIXME: LTTng hack - end
447 fCheckpoints.add(new TmfTraceCheckpoint(timestamp, context.getLocation()));
448 fNbEvents = nbEvents - 1;
449 lastTime = context.getTimestamp();
450 fTimeRange = new TmfTimeRange(startTime, lastTime);
451 notifyListeners(new TmfTimeRange(startTime, lastTime));
4e3aa37d 452
62d1696a 453 monitor.worked(1);
4e3aa37d 454
62d1696a
FC
455 // Check monitor *after* fCheckpoints has been updated
456 if (monitor.isCanceled()) {
4e3aa37d 457 monitor.done();
62d1696a
FC
458 return Status.CANCEL_STATUS;
459 }
165c977c 460 }
165c977c 461
146a887c
FC
462 // Do whatever
463 processEvent(event);
62d1696a
FC
464 }
465 }
466 finally {
467 synchronized(this) {
98029bc9 468 fNbEvents = nbEvents;
62d1696a 469 fTimeRange = new TmfTimeRange(startTime, lastTime);
4e3aa37d 470 fIndexing = false;
62d1696a 471 }
98029bc9 472 notifyListeners(new TmfTimeRange(startTime, lastTime));
62d1696a 473 monitor.done();
98029bc9 474
8c8bf09f 475 }
62d1696a 476
98029bc9
FC
477// createOffsetsFile();
478// dumpCheckpoints();
479
4e3aa37d 480 return Status.OK_STATUS;
62d1696a 481 }
8c8bf09f
ASL
482 }
483
146a887c 484 private void notifyListeners(TmfTimeRange range) {
8d2e2848 485 broadcastSignal(new TmfTraceUpdatedSignal(this, this, range));
146a887c
FC
486 }
487
98029bc9
FC
488// /**
489// * Dump the trace checkpoints
490// */
491// private void dumpCheckpoints() {
492// System.out.println("-----");
493// System.out.println("Checkpoints of " + fName);
494// for (int i = 0; i < fCheckpoints.size(); i++) {
495// TmfTraceCheckpoint checkpoint = fCheckpoints.get(i);
496// TmfTraceContext context = new TmfTraceContext(checkpoint.getLocation());
497// TmfEvent event = getNextEvent(context);
498// System.out.println(" Entry: " + i + " timestamp: " + checkpoint.getTimestamp() + ", event: " + event.getTimestamp());
499// assert((checkpoint.getTimestamp().compareTo(event.getTimestamp(), false) == 0));
500// }
501// System.out.println();
502// }
503
504// private void createOffsetsFile() {
505//
506// try {
507// ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("LTTngOffsets.dat")));
508//
509// TmfTraceContext context = null;
510// context = seekLocation(null);
511// out.writeObject(context.getLocation());
512//
513// int nbEvents = 0;
514// while (getNextEvent(context) != null) {
515// out.writeObject(context.getLocation());
516// nbEvents++;
517// }
518// out.close();
519// System.out.println("TmfTrace wrote " + nbEvents + " events");
520// } catch (FileNotFoundException e) {
521// // TODO Auto-generated catch block
522// e.printStackTrace();
523// } catch (IOException e) {
524// // TODO Auto-generated catch block
525// e.printStackTrace();
526// }
527// }
528
529// private void createOffsetsFile() {
530//
531// try {
532// DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("LTTngOffsets.dat")));
533//
534// TmfTraceContext context = null;
535// context = seekLocation(null);
536//
537// TmfEvent event;
538// int nbEvents = 0;
539// while ((event = getNextEvent(context)) != null) {
540// out.writeUTF(event.getTimestamp().toString());
541// nbEvents++;
542// }
543// out.close();
544// System.out.println("TmfTrace wrote " + nbEvents + " events");
545// } catch (FileNotFoundException e) {
546// // TODO Auto-generated catch block
547// e.printStackTrace();
548// } catch (IOException e) {
549// // TODO Auto-generated catch block
550// e.printStackTrace();
551// }
552// }
553
8c8bf09f 554}
This page took 0.075461 seconds and 5 git commands to generate.