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