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