Merge master in TmfTraceModel
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / experiment / TmfExperiment.java
CommitLineData
8c8bf09f
ASL
1/*******************************************************************************
2 * Copyright (c) 2009, 2010 Ericsson
ce2388e0 3 *
8c8bf09f
ASL
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
ce2388e0 8 *
8c8bf09f
ASL
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
12
6c13869b 13package org.eclipse.linuxtools.tmf.core.experiment;
8c8bf09f 14
9f584e4c 15import java.util.Collections;
8c8bf09f
ASL
16import java.util.Vector;
17
a1091415 18import org.eclipse.core.resources.IFile;
12c155f5 19import org.eclipse.core.resources.IProject;
828e5592 20import org.eclipse.core.resources.IResource;
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;
6c13869b 25import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider;
72f1e62a 26import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
4df4581d 27import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
6c13869b
FC
28import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
29import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
30import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
31import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
32import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
33import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
1b70b6dc 34import org.eclipse.linuxtools.tmf.core.signal.TmfEndSynchSignal;
6c13869b
FC
35import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentDisposedSignal;
36import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
37import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
38import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal;
39import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
6c13869b
FC
40import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
41import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
42import org.eclipse.linuxtools.tmf.core.trace.ITmfLocation;
43import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
44import org.eclipse.linuxtools.tmf.core.trace.TmfCheckpoint;
45import org.eclipse.linuxtools.tmf.core.trace.TmfContext;
8c8bf09f
ASL
46
47/**
48 * <b><u>TmfExperiment</u></b>
49 * <p>
cbdacf03
FC
50 * TmfExperiment presents a time-ordered, unified view of a set of TmfTraces
51 * that are part of a tracing experiment.
8c8bf09f
ASL
52 * <p>
53 */
72f1e62a 54public class TmfExperiment<T extends ITmfEvent> extends TmfEventProvider<T> implements ITmfTrace<T> {
8c8bf09f
ASL
55
56 // ------------------------------------------------------------------------
57 // Attributes
58 // ------------------------------------------------------------------------
59
a79913eb 60 // The currently selected experiment
82e04272 61 protected static TmfExperiment<?> fCurrentExperiment = null;
e31e01e8 62
a79913eb 63 // The set of traces that constitute the experiment
12c155f5 64 protected ITmfTrace<T>[] fTraces;
8c8bf09f
ASL
65
66 // The total number of events
82e04272 67 protected long fNbEvents;
8c8bf09f
ASL
68
69 // The experiment time range
82e04272 70 protected TmfTimeRange fTimeRange;
8c8bf09f 71
3791b5df 72 // The experiment reference timestamp (default: ZERO)
4df4581d 73 protected ITmfTimestamp fEpoch;
8c8bf09f 74
a79913eb 75 // The experiment index
82e04272 76 protected Vector<TmfCheckpoint> fCheckpoints = new Vector<TmfCheckpoint>();
9f584e4c 77
f6b14ce2
FC
78 // The current experiment context
79 protected TmfExperimentContext fExperimentContext;
a79913eb 80
828e5592
PT
81 // Flag to initialize only once
82 private boolean fInitialized = false;
83
a1091415
PT
84 // The experiment bookmarks file
85 private IFile fBookmarksFile;
86
87 // The properties resource
828e5592
PT
88 private IResource fResource;
89
8c8bf09f
ASL
90 // ------------------------------------------------------------------------
91 // Constructors
92 // ------------------------------------------------------------------------
93
3791b5df
FC
94 @Override
95 public TmfExperiment<T> clone() throws CloneNotSupportedException {
96 throw new CloneNotSupportedException();
97 }
98
12c155f5 99 @Override
cbdacf03 100 public boolean validate(final IProject project, final String path) {
12c155f5
FC
101 return true;
102 }
103
104 @Override
cbdacf03 105 public void initTrace(final String name, final String path, final Class<T> eventType) {
96c6806f
PT
106 }
107
8c8bf09f
ASL
108 /**
109 * @param type
110 * @param id
111 * @param traces
112 * @param epoch
113 * @param indexPageSize
114 */
cbdacf03
FC
115 public TmfExperiment(final Class<T> type, final String id, final ITmfTrace<T>[] traces, final ITmfTimestamp epoch,
116 final int indexPageSize) {
a4115405 117 this(type, id, traces, TmfTimestamp.ZERO, indexPageSize, false);
a79913eb 118 }
cb866e08 119
cbdacf03
FC
120 public TmfExperiment(final Class<T> type, final String id, final ITmfTrace<T>[] traces, final ITmfTimestamp epoch,
121 final int indexPageSize, final boolean preIndexExperiment) {
a79913eb 122 super(id, type);
8c8bf09f 123
a79913eb
FC
124 fTraces = traces;
125 fEpoch = epoch;
126 fIndexPageSize = indexPageSize;
a4115405 127 fTimeRange = TmfTimeRange.NULL_RANGE;
8c8bf09f 128
bfc779a0 129 if (preIndexExperiment) {
8636b448
FC
130 indexExperiment(true, 0, TmfTimeRange.ETERNITY);
131 updateTimeRange();
bfc779a0 132 }
a79913eb 133 }
8c8bf09f 134
cbdacf03 135 protected TmfExperiment(final String id, final Class<T> type) {
82e04272 136 super(id, type);
a79913eb 137 }
82e04272 138
8c8bf09f
ASL
139 /**
140 * @param type
141 * @param id
142 * @param traces
143 */
cbdacf03 144 public TmfExperiment(final Class<T> type, final String id, final ITmfTrace<T>[] traces) {
a4115405 145 this(type, id, traces, TmfTimestamp.ZERO, DEFAULT_INDEX_PAGE_SIZE);
8c8bf09f
ASL
146 }
147
148 /**
149 * @param type
150 * @param id
151 * @param traces
152 * @param indexPageSize
153 */
cbdacf03 154 public TmfExperiment(final Class<T> type, final String id, final ITmfTrace<T>[] traces, final int indexPageSize) {
a4115405 155 this(type, id, traces, TmfTimestamp.ZERO, indexPageSize);
8c8bf09f 156 }
a79913eb 157
8c8bf09f 158 /**
ff4ed569 159 * Clears the experiment
8c8bf09f
ASL
160 */
161 @Override
12c155f5 162 @SuppressWarnings("rawtypes")
a79913eb
FC
163 public synchronized void dispose() {
164
cbdacf03 165 final TmfExperimentDisposedSignal<T> signal = new TmfExperimentDisposedSignal<T>(this, this);
a79913eb 166 broadcast(signal);
cbdacf03 167 if (fCurrentExperiment == this)
09d11238 168 fCurrentExperiment = null;
a79913eb
FC
169
170 if (fTraces != null) {
cbdacf03 171 for (final ITmfTrace trace : fTraces)
a79913eb 172 trace.dispose();
a79913eb
FC
173 fTraces = null;
174 }
cbdacf03 175 if (fCheckpoints != null)
a79913eb 176 fCheckpoints.clear();
2fb2eb37 177 super.dispose();
8c8bf09f
ASL
178 }
179
9f584e4c 180 // ------------------------------------------------------------------------
cbd4ad82 181 // ITmfTrace
9f584e4c
FC
182 // ------------------------------------------------------------------------
183
a79913eb
FC
184 @Override
185 public long getNbEvents() {
186 return fNbEvents;
187 }
9f584e4c 188
d4011df2 189 @Override
3118edf1 190 public int getIndexPageSize() {
54d55ced
FC
191 return fIndexPageSize;
192 }
193
a79913eb
FC
194 @Override
195 public TmfTimeRange getTimeRange() {
196 return fTimeRange;
197 }
9f584e4c 198
a79913eb 199 @Override
4df4581d 200 public ITmfTimestamp getStartTime() {
a79913eb
FC
201 return fTimeRange.getStartTime();
202 }
9f584e4c 203
a79913eb 204 @Override
4df4581d 205 public ITmfTimestamp getEndTime() {
a79913eb
FC
206 return fTimeRange.getEndTime();
207 }
9f584e4c 208
54d55ced 209 public Vector<TmfCheckpoint> getCheckpoints() {
a79913eb 210 return fCheckpoints;
54d55ced
FC
211 }
212
8c8bf09f 213 // ------------------------------------------------------------------------
e31e01e8 214 // Accessors
8c8bf09f
ASL
215 // ------------------------------------------------------------------------
216
cbdacf03
FC
217 public static void setCurrentExperiment(final TmfExperiment<?> experiment) {
218 if (fCurrentExperiment != null && fCurrentExperiment != experiment)
09d11238 219 fCurrentExperiment.dispose();
a79913eb 220 fCurrentExperiment = experiment;
f6b14ce2
FC
221 }
222
e31e01e8 223 public static TmfExperiment<?> getCurrentExperiment() {
a79913eb 224 return fCurrentExperiment;
8c8bf09f
ASL
225 }
226
4df4581d 227 public ITmfTimestamp getEpoch() {
a79913eb 228 return fEpoch;
8c8bf09f
ASL
229 }
230
12c155f5 231 public ITmfTrace<T>[] getTraces() {
a79913eb 232 return fTraces;
8c8bf09f
ASL
233 }
234
235 /**
cbdacf03
FC
236 * Returns the rank of the first event with the requested timestamp. If
237 * none, returns the index of the next event (if any).
a79913eb 238 *
0d9a6d76
FC
239 * @param timestamp the event timestamp
240 * @return the corresponding event rank
8c8bf09f 241 */
d4011df2 242 @Override
cbdacf03
FC
243 public long getRank(final ITmfTimestamp timestamp) {
244 final TmfExperimentContext context = seekEvent(timestamp);
a79913eb 245 return context.getRank();
8c8bf09f
ASL
246 }
247
248 /**
cbdacf03
FC
249 * Returns the timestamp of the event at the requested index. If none,
250 * returns null.
a79913eb 251 *
0d9a6d76
FC
252 * @param index the event index (rank)
253 * @return the corresponding event timestamp
8c8bf09f 254 */
cbdacf03
FC
255 public ITmfTimestamp getTimestamp(final int index) {
256 final TmfExperimentContext context = seekEvent(index);
257 final ITmfEvent event = getNextEvent(context);
a79913eb 258 return (event != null) ? event.getTimestamp() : null;
8c8bf09f
ASL
259 }
260
261 // ------------------------------------------------------------------------
262 // Operators
263 // ------------------------------------------------------------------------
264
8c8bf09f
ASL
265 /**
266 * Update the global time range
267 */
a79913eb 268 protected void updateTimeRange() {
cbdacf03
FC
269 ITmfTimestamp startTime = fTimeRange != TmfTimeRange.NULL_RANGE ? fTimeRange.getStartTime()
270 : TmfTimestamp.BIG_CRUNCH;
a4115405 271 ITmfTimestamp endTime = fTimeRange != TmfTimeRange.NULL_RANGE ? fTimeRange.getEndTime() : TmfTimestamp.BIG_BANG;
a79913eb 272
cbdacf03
FC
273 for (final ITmfTrace<T> trace : fTraces) {
274 final ITmfTimestamp traceStartTime = trace.getStartTime();
a79913eb
FC
275 if (traceStartTime.compareTo(startTime, true) < 0)
276 startTime = traceStartTime;
cbdacf03 277 final ITmfTimestamp traceEndTime = trace.getEndTime();
a79913eb
FC
278 if (traceEndTime.compareTo(endTime, true) > 0)
279 endTime = traceEndTime;
280 }
281 fTimeRange = new TmfTimeRange(startTime, endTime);
8c8bf09f
ASL
282 }
283
284 // ------------------------------------------------------------------------
285 // TmfProvider
286 // ------------------------------------------------------------------------
a79913eb 287 @Override
cbdacf03 288 public ITmfContext armRequest(final ITmfDataRequest<T> request) {
ce2388e0
FC
289 // Tracer.trace("Ctx: Arming request - start");
290 ITmfTimestamp timestamp = (request instanceof ITmfEventRequest<?>) ? ((ITmfEventRequest<T>) request).getRange().getStartTime() : null;
cbdacf03 291 if (TmfTimestamp.BIG_BANG.equals(timestamp) || request.getIndex() > 0)
a79913eb 292 timestamp = null; // use request index
a79913eb
FC
293 TmfExperimentContext context = null;
294 if (timestamp != null) {
295 // seek by timestamp
296 context = seekEvent(timestamp);
297 ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
cbdacf03 298 } else // Seek by rank
ce2388e0
FC
299 if ((fExperimentContext != null) && fExperimentContext.getRank() == request.getIndex())
300 // We are already at the right context -> no need to seek
301 context = fExperimentContext;
302 else
303 context = seekEvent(request.getIndex());
304 // Tracer.trace("Ctx: Arming request - done");
a79913eb
FC
305 return context;
306 }
307
308 @SuppressWarnings("unchecked")
309 @Override
cbdacf03
FC
310 public T getNext(final ITmfContext context) {
311 if (context instanceof TmfExperimentContext)
312 return (T) getNextEvent(context);
a79913eb
FC
313 return null;
314 }
315
316 // ------------------------------------------------------------------------
9f584e4c
FC
317 // ITmfTrace trace positioning
318 // ------------------------------------------------------------------------
319
a79913eb
FC
320 // Returns a brand new context based on the location provided
321 // and initializes the event queues
322 @Override
cbdacf03 323 public synchronized TmfExperimentContext seekLocation(final ITmfLocation<?> location) {
a79913eb 324 // Validate the location
cbdacf03 325 if (location != null && !(location instanceof TmfExperimentLocation))
a79913eb 326 return null; // Throw an exception?
8f50c396 327
cbdacf03 328 if (fTraces == null)
a79913eb 329 return null;
8f50c396 330
a79913eb 331 // Instantiate the location
cbdacf03 332 final TmfExperimentLocation expLocation = (location == null) ? new TmfExperimentLocation(new TmfLocationArray(
ce2388e0 333 new ITmfLocation<?>[fTraces.length]), new long[fTraces.length]) : (TmfExperimentLocation) location.clone();
8f50c396 334
a79913eb 335 // Create and populate the context's traces contexts
ce2388e0
FC
336 final TmfExperimentContext context = new TmfExperimentContext(fTraces, new ITmfContext[fTraces.length]);
337 // Tracer.trace("Ctx: SeekLocation - start");
9b635e61 338
a79913eb
FC
339 long rank = 0;
340 for (int i = 0; i < fTraces.length; i++) {
341 // Get the relevant trace attributes
cbdacf03
FC
342 final ITmfLocation<?> traceLocation = expLocation.getLocation().locations[i];
343 final long traceRank = expLocation.getRanks()[i];
8f50c396 344
a79913eb
FC
345 // Set the corresponding sub-context
346 context.getContexts()[i] = fTraces[i].seekLocation(traceLocation);
347 context.getContexts()[i].setRank(traceRank);
348 rank += traceRank;
8f50c396 349
a79913eb 350 // Set the trace location and read the corresponding event
cbdacf03
FC
351 /*
352 * The (TmfContext) cast should be safe since we created 'context'
353 * ourselves higher up.
354 */
ce2388e0 355 expLocation.getLocation().locations[i] = context.getContexts()[i].getLocation().clone();
a79913eb
FC
356 context.getEvents()[i] = fTraces[i].getNextEvent(context.getContexts()[i]);
357 }
8f50c396 358
ce2388e0 359 // Tracer.trace("Ctx: SeekLocation - done");
9b635e61 360
a79913eb
FC
361 // Finalize context
362 context.setLocation(expLocation);
363 context.setLastTrace(TmfExperimentContext.NO_TRACE);
364 context.setRank(rank);
9b635e61 365
a79913eb 366 fExperimentContext = context;
9b635e61 367
a79913eb
FC
368 return context;
369 }
9f584e4c 370
a79913eb
FC
371 /*
372 * (non-Javadoc)
ce2388e0 373 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools .tmf.event.TmfTimestamp)
a79913eb
FC
374 */
375 @Override
4df4581d 376 public synchronized TmfExperimentContext seekEvent(ITmfTimestamp timestamp) {
9b635e61 377
ce2388e0 378 // Tracer.trace("Ctx: seekEvent(TS) - start");
8c8bf09f 379
cbdacf03 380 if (timestamp == null)
a4115405 381 timestamp = TmfTimestamp.BIG_BANG;
9f584e4c 382
a79913eb
FC
383 // First, find the right checkpoint
384 int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
9f584e4c
FC
385
386 // In the very likely case that the checkpoint was not found, bsearch
387 // returns its negated would-be location (not an offset...). From that
388 // index, we can then position the stream and get the event.
cbdacf03 389 if (index < 0)
9f584e4c 390 index = Math.max(0, -(index + 2));
9f584e4c
FC
391
392 // Position the experiment at the checkpoint
452ad365 393 ITmfLocation<?> location;
9f584e4c 394 synchronized (fCheckpoints) {
a79913eb 395 if (fCheckpoints.size() > 0) {
cbdacf03 396 if (index >= fCheckpoints.size())
a79913eb 397 index = fCheckpoints.size() - 1;
a79913eb 398 location = fCheckpoints.elementAt(index).getLocation();
cbdacf03 399 } else
a79913eb 400 location = null;
9f584e4c
FC
401 }
402
cbdacf03 403 final TmfExperimentContext context = seekLocation(location);
cbd4ad82 404 context.setRank((long) index * fIndexPageSize);
9f584e4c 405
a79913eb 406 // And locate the event
72f1e62a 407 ITmfEvent event = parseEvent(context);
ce2388e0 408 while ((event != null) && (event.getTimestamp().compareTo(timestamp, false) < 0)) {
a79913eb
FC
409 getNextEvent(context);
410 event = parseEvent(context);
9f584e4c
FC
411 }
412
f6b14ce2 413 if (event == null) {
a79913eb
FC
414 context.setLocation(null);
415 context.setRank(ITmfContext.UNKNOWN_RANK);
9b635e61 416 }
f6b14ce2
FC
417
418 return context;
a79913eb 419 }
8c8bf09f 420
a79913eb
FC
421 /*
422 * (non-Javadoc)
ce2388e0 423 *
a79913eb
FC
424 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(long)
425 */
426 @Override
cbdacf03 427 public synchronized TmfExperimentContext seekEvent(final long rank) {
9b635e61 428
ce2388e0 429 // Tracer.trace("Ctx: seekEvent(rank) - start");
9f584e4c 430
54d55ced
FC
431 // Position the stream at the previous checkpoint
432 int index = (int) rank / fIndexPageSize;
433 ITmfLocation<?> location;
434 synchronized (fCheckpoints) {
cbdacf03 435 if (fCheckpoints.size() == 0)
a79913eb 436 location = null;
cbdacf03
FC
437 else {
438 if (index >= fCheckpoints.size())
a79913eb 439 index = fCheckpoints.size() - 1;
a79913eb
FC
440 location = fCheckpoints.elementAt(index).getLocation();
441 }
54d55ced 442 }
e31e01e8 443
cbdacf03 444 final TmfExperimentContext context = seekLocation(location);
9b635e61 445 context.setRank((long) index * fIndexPageSize);
54d55ced 446
a79913eb 447 // And locate the event
72f1e62a 448 ITmfEvent event = parseEvent(context);
9b635e61 449 long pos = context.getRank();
ce2388e0 450 while ((event != null) && (pos++ < rank)) {
a79913eb
FC
451 getNextEvent(context);
452 event = parseEvent(context);
54d55ced 453 }
9f584e4c 454
f6b14ce2 455 if (event == null) {
a79913eb
FC
456 context.setLocation(null);
457 context.setRank(ITmfContext.UNKNOWN_RANK);
9b635e61 458 }
f6b14ce2 459
a79913eb
FC
460 return context;
461 }
8c8bf09f 462
c76c54bb 463 @Override
cbdacf03
FC
464 public TmfContext seekLocation(final double ratio) {
465 final TmfContext context = seekEvent((long) (ratio * getNbEvents()));
c76c54bb
FC
466 return context;
467 }
468
a79913eb 469 @Override
cbdacf03
FC
470 public double getLocationRatio(final ITmfLocation<?> location) {
471 if (location instanceof TmfExperimentLocation)
a79913eb 472 return (double) seekLocation(location).getRank() / getNbEvents();
c76c54bb
FC
473 return 0;
474 }
475
a79913eb
FC
476 @Override
477 public ITmfLocation<?> getCurrentLocation() {
cbdacf03 478 if (fExperimentContext != null)
a79913eb 479 return fExperimentContext.getLocation();
a79913eb
FC
480 return null;
481 }
c76c54bb 482
ce2388e0 483 // private void dumpContext(TmfExperimentContext context, boolean isBefore) {
9b635e61 484
ce2388e0
FC
485 // TmfContext context0 = context.getContexts()[0];
486 // TmfEvent event0 = context.getEvents()[0];
487 // TmfExperimentLocation location0 = (TmfExperimentLocation) context.getLocation();
488 // long rank0 = context.getRank();
489 // int trace = context.getLastTrace();
490 //
491 // StringBuffer result = new StringBuffer("Ctx: " + (isBefore ? "B " : "A "));
492 //
493 // result.append("[Ctx: fLoc= " + context0.getLocation().toString() + ", fRnk= " + context0.getRank() + "] ");
494 // result.append("[Evt: " + event0.getTimestamp().toString() + "] ");
495 // result.append("[Loc: fLoc= " + location0.getLocation()[0].toString() + ", fRnk= " + location0.getRanks()[0] + "] ");
496 // result.append("[Rnk: " + rank0 + "], [Trc: " + trace + "]");
497 // Tracer.trace(result.toString());
498 // }
54d55ced 499
0d9a6d76 500 /**
cbdacf03
FC
501 * Scan the next events from all traces and return the next one in
502 * chronological order.
0d9a6d76
FC
503 *
504 * @param context the trace context
505 * @return the next event
506 */
a79913eb 507 @Override
cbdacf03 508 public synchronized ITmfEvent getNextEvent(final ITmfContext context) {
a79913eb
FC
509
510 // Validate the context
cbdacf03 511 if (!(context instanceof TmfExperimentContext))
a79913eb 512 return null; // Throw an exception?
54d55ced 513
cbdacf03
FC
514 if (!context.equals(fExperimentContext))
515 // Tracer.trace("Ctx: Restoring context");
a79913eb 516 fExperimentContext = seekLocation(context.getLocation());
a79913eb 517
cbdacf03 518 final TmfExperimentContext expContext = (TmfExperimentContext) context;
8f50c396 519
ce2388e0 520 // dumpContext(expContext, true);
9b635e61 521
a79913eb 522 // If an event was consumed previously, get the next one from that trace
cbdacf03 523 final int lastTrace = expContext.getLastTrace();
a79913eb 524 if (lastTrace != TmfExperimentContext.NO_TRACE) {
cbdacf03 525 final ITmfContext traceContext = expContext.getContexts()[lastTrace];
a79913eb
FC
526 expContext.getEvents()[lastTrace] = expContext.getTraces()[lastTrace].getNextEvent(traceContext);
527 expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
528 }
8f50c396 529
a79913eb 530 // Scan the candidate events and identify the "next" trace to read from
cbdacf03
FC
531 final ITmfEvent eventArray[] = expContext.getEvents();
532 if (eventArray == null)
1324801a 533 return null;
a79913eb 534 int trace = TmfExperimentContext.NO_TRACE;
a4115405 535 ITmfTimestamp timestamp = TmfTimestamp.BIG_CRUNCH;
1324801a
FC
536 if (eventArray.length == 1) {
537 if (eventArray[0] != null) {
538 timestamp = eventArray[0].getTimestamp();
539 trace = 0;
540 }
cbdacf03 541 } else
1324801a 542 for (int i = 0; i < eventArray.length; i++) {
cbdacf03 543 final ITmfEvent event = eventArray[i];
1324801a 544 if (event != null && event.getTimestamp() != null) {
cbdacf03 545 final ITmfTimestamp otherTS = event.getTimestamp();
1324801a
FC
546 if (otherTS.compareTo(timestamp, true) < 0) {
547 trace = i;
548 timestamp = otherTS;
549 }
550 }
551 }
1324801a 552 // Update the experiment context and set the "next" event
72f1e62a 553 ITmfEvent event = null;
a79913eb
FC
554 if (trace != TmfExperimentContext.NO_TRACE) {
555 updateIndex(expContext, timestamp);
82e04272 556
cbdacf03
FC
557 final ITmfContext traceContext = expContext.getContexts()[trace];
558 final TmfExperimentLocation expLocation = (TmfExperimentLocation) expContext.getLocation();
ce2388e0 559 // expLocation.getLocation()[trace] = traceContext.getLocation().clone();
cbdacf03 560 expLocation.getLocation().locations[trace] = traceContext.getLocation().clone();
82e04272 561
ce2388e0 562 // updateIndex(expContext, timestamp);
82e04272 563
a79913eb
FC
564 expLocation.getRanks()[trace] = traceContext.getRank();
565 expContext.setLastTrace(trace);
cbdacf03 566 expContext.increaseRank();
a79913eb
FC
567 event = expContext.getEvents()[trace];
568 fExperimentContext = expContext;
569 }
8f50c396 570
ce2388e0
FC
571 // if (event != null) {
572 // Tracer.trace("Exp: " + (expContext.getRank() - 1) + ": " + event.getTimestamp().toString());
573 // dumpContext(expContext, false);
574 // Tracer.trace("Ctx: Event returned= " + event.getTimestamp().toString());
575 // }
9b635e61 576
a79913eb
FC
577 return event;
578 }
579
cbdacf03 580 public synchronized void updateIndex(final ITmfContext context, final ITmfTimestamp timestamp) {
a79913eb 581 // Build the index as we go along
cbdacf03
FC
582 final long rank = context.getRank();
583 if (context.hasValidRank() && (rank % fIndexPageSize) == 0) {
a79913eb 584 // Determine the table position
cbdacf03 585 final long position = rank / fIndexPageSize;
a79913eb
FC
586 // Add new entry at proper location (if empty)
587 if (fCheckpoints.size() == position) {
cbdacf03 588 final ITmfLocation<?> location = context.getLocation().clone();
a79913eb 589 fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location));
ce2388e0
FC
590 // System.out.println(this + "[" + (fCheckpoints.size() - 1) + "] " + timestamp + ", "
591 // + location.toString());
a79913eb
FC
592 }
593 }
594 }
595
ce2388e0
FC
596 /* (non-Javadoc)
597 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#parseEvent(org.eclipse.linuxtools .tmf.trace.TmfContext)
a79913eb
FC
598 */
599 @Override
cbdacf03 600 public ITmfEvent parseEvent(final ITmfContext context) {
a79913eb
FC
601
602 // Validate the context
cbdacf03 603 if (!(context instanceof TmfExperimentContext))
a79913eb 604 return null; // Throw an exception?
a79913eb 605
cbdacf03
FC
606 if (!context.equals(fExperimentContext))
607 // Tracer.trace("Ctx: Restoring context");
a79913eb 608 seekLocation(context.getLocation());
a79913eb 609
cbdacf03 610 final TmfExperimentContext expContext = (TmfExperimentContext) context;
a79913eb
FC
611
612 // If an event was consumed previously, get the next one from that trace
cbdacf03 613 final int lastTrace = expContext.getLastTrace();
a79913eb 614 if (lastTrace != TmfExperimentContext.NO_TRACE) {
cbdacf03 615 final ITmfContext traceContext = expContext.getContexts()[lastTrace];
a79913eb
FC
616 expContext.getEvents()[lastTrace] = expContext.getTraces()[lastTrace].getNextEvent(traceContext);
617 expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
618 fExperimentContext = (TmfExperimentContext) context;
619 }
620
621 // Scan the candidate events and identify the "next" trace to read from
622 int trace = TmfExperimentContext.NO_TRACE;
a4115405 623 ITmfTimestamp timestamp = TmfTimestamp.BIG_CRUNCH;
a79913eb 624 for (int i = 0; i < expContext.getTraces().length; i++) {
cbdacf03 625 final ITmfEvent event = expContext.getEvents()[i];
a79913eb 626 if (event != null && event.getTimestamp() != null) {
cbdacf03 627 final ITmfTimestamp otherTS = event.getTimestamp();
a79913eb
FC
628 if (otherTS.compareTo(timestamp, true) < 0) {
629 trace = i;
630 timestamp = otherTS;
631 }
632 }
633 }
634
72f1e62a 635 ITmfEvent event = null;
cbdacf03 636 if (trace != TmfExperimentContext.NO_TRACE)
a79913eb 637 event = expContext.getEvents()[trace];
a79913eb
FC
638
639 return event;
640 }
641
642 /*
643 * (non-Javadoc)
ce2388e0 644 *
a79913eb
FC
645 * @see java.lang.Object#toString()
646 */
647 @Override
3b38ea61 648 @SuppressWarnings("nls")
a79913eb
FC
649 public String toString() {
650 return "[TmfExperiment (" + getName() + ")]";
651 }
8c8bf09f
ASL
652
653 // ------------------------------------------------------------------------
654 // Indexing
655 // ------------------------------------------------------------------------
656
1b70b6dc 657 private synchronized void initializeStreamingMonitor() {
cbdacf03 658 if (fInitialized)
828e5592 659 return;
828e5592
PT
660 fInitialized = true;
661
1b70b6dc 662 if (getStreamingInterval() == 0) {
cbdacf03
FC
663 final TmfContext context = seekLocation(null);
664 final ITmfEvent event = getNext(context);
665 if (event == null)
1b70b6dc 666 return;
cbdacf03 667 final TmfTimeRange timeRange = new TmfTimeRange(event.getTimestamp().clone(), TmfTimestamp.BIG_CRUNCH);
828e5592
PT
668 final TmfExperimentRangeUpdatedSignal signal = new TmfExperimentRangeUpdatedSignal(this, this, timeRange);
669
670 // Broadcast in separate thread to prevent deadlock
671 new Thread() {
cbdacf03 672
828e5592
PT
673 @Override
674 public void run() {
675 broadcast(signal);
676 }
677 }.start();
1b70b6dc
PT
678 return;
679 }
680
681 final Thread thread = new Thread("Streaming Monitor for experiment " + getName()) { //$NON-NLS-1$
cbdacf03 682
dfee01ae 683 ITmfTimestamp safeTimestamp = null;
1b70b6dc
PT
684 TmfTimeRange timeRange = null;
685
686 @Override
687 public void run() {
688 while (!fExecutor.isShutdown()) {
689 if (!isIndexingBusy()) {
a4115405
FC
690 ITmfTimestamp startTimestamp = TmfTimestamp.BIG_CRUNCH;
691 ITmfTimestamp endTimestamp = TmfTimestamp.BIG_BANG;
cbdacf03
FC
692 for (final ITmfTrace<T> trace : fTraces) {
693 if (trace.getStartTime().compareTo(startTimestamp) < 0)
1b70b6dc 694 startTimestamp = trace.getStartTime();
cbdacf03 695 if (trace.getStreamingInterval() != 0 && trace.getEndTime().compareTo(endTimestamp) > 0)
1b70b6dc 696 endTimestamp = trace.getEndTime();
1b70b6dc 697 }
cbdacf03 698 if (safeTimestamp != null && safeTimestamp.compareTo(getTimeRange().getEndTime(), false) > 0)
1b70b6dc 699 timeRange = new TmfTimeRange(startTimestamp, safeTimestamp);
cbdacf03 700 else
1b70b6dc 701 timeRange = null;
1b70b6dc
PT
702 safeTimestamp = endTimestamp;
703 if (timeRange != null) {
cbdacf03
FC
704 final TmfExperimentRangeUpdatedSignal signal =
705 new TmfExperimentRangeUpdatedSignal(TmfExperiment.this, TmfExperiment.this,
706 timeRange);
1b70b6dc
PT
707 broadcast(signal);
708 }
709 }
710 try {
711 Thread.sleep(getStreamingInterval());
cbdacf03 712 } catch (final InterruptedException e) {
1b70b6dc
PT
713 e.printStackTrace();
714 }
715 }
716 }
717 };
718 thread.start();
719 }
720
cbdacf03
FC
721 /*
722 * (non-Javadoc)
723 *
1b70b6dc
PT
724 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
725 */
726 @Override
727 public long getStreamingInterval() {
728 long interval = 0;
cbdacf03 729 for (final ITmfTrace<T> trace : fTraces)
1b70b6dc 730 interval = Math.max(interval, trace.getStreamingInterval());
1b70b6dc
PT
731 return interval;
732 }
733
a79913eb 734 /*
cbdacf03
FC
735 * The experiment holds the globally ordered events of its set of traces. It
736 * is expected to provide access to each individual event by index i.e. it
737 * must be possible to request the Nth event of the experiment.
a79913eb 738 *
cbdacf03
FC
739 * The purpose of the index is to keep the information needed to rapidly
740 * restore the traces contexts at regular intervals (every INDEX_PAGE_SIZE
741 * event).
a79913eb 742 */
8c8bf09f 743
a79913eb
FC
744 // The index page size
745 private static final int DEFAULT_INDEX_PAGE_SIZE = 5000;
746 protected int fIndexPageSize;
747 protected boolean fIndexing = false;
a4115405 748 protected TmfTimeRange fIndexingPendingRange = TmfTimeRange.NULL_RANGE;
e31e01e8 749
1b70b6dc
PT
750 private Integer fEndSynchReference;
751
ce2388e0
FC
752 // private static BufferedWriter fEventLog = null;
753 // private static BufferedWriter openLogFile(String filename) {
754 // BufferedWriter outfile = null;
755 // try {
756 // outfile = new BufferedWriter(new FileWriter(filename));
757 // } catch (IOException e) {
758 // e.printStackTrace();
759 // }
760 // return outfile;
761 // }
9b635e61 762
a79913eb
FC
763 protected boolean isIndexingBusy() {
764 synchronized (fCheckpoints) {
765 return fIndexing;
766 }
767 }
768
8636b448 769 @Override
cbdacf03
FC
770 public void indexTrace(final boolean waitForCompletion) {
771 if (waitForCompletion)
8636b448 772 initializeStreamingMonitor();
a79913eb
FC
773 }
774
775 @SuppressWarnings("unchecked")
cbdacf03 776 private void indexExperiment(final boolean waitForCompletion, final int index, final TmfTimeRange timeRange) {
a79913eb
FC
777
778 synchronized (fCheckpoints) {
cbdacf03 779 if (fIndexing)
a79913eb 780 return;
a79913eb
FC
781 fIndexing = true;
782 }
783
8a0edc79 784 final Job job = new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
cbdacf03 785
8a0edc79 786 @Override
cbdacf03
FC
787 protected IStatus run(final IProgressMonitor monitor) {
788 while (!monitor.isCanceled())
8a0edc79
FC
789 try {
790 Thread.sleep(100);
cbdacf03 791 } catch (final InterruptedException e) {
8a0edc79
FC
792 return Status.OK_STATUS;
793 }
8a0edc79
FC
794 monitor.done();
795 return Status.OK_STATUS;
796 }
797 };
798 job.schedule();
799
ce2388e0
FC
800 // fEventLog = openLogFile("TraceEvent.log");
801 // System.out.println(System.currentTimeMillis() + ": Experiment indexing started");
550d787e 802
cbdacf03
FC
803 final ITmfEventRequest<ITmfEvent> request = new TmfEventRequest<ITmfEvent>(ITmfEvent.class, timeRange, index,
804 TmfDataRequest.ALL_DATA,
805 fIndexPageSize, ITmfDataRequest.ExecutionType.BACKGROUND) { // PATA
ce2388e0 806 // FOREGROUND
550d787e 807
ce2388e0 808 // long indexingStart = System.nanoTime();
a79913eb 809
a4115405
FC
810 ITmfTimestamp startTime = (fTimeRange == TmfTimeRange.NULL_RANGE) ? null : fTimeRange.getStartTime();
811 ITmfTimestamp lastTime = (fTimeRange == TmfTimeRange.NULL_RANGE) ? null : fTimeRange.getEndTime();
a79913eb
FC
812 long initialNbEvents = fNbEvents;
813
814 @Override
815 public void handleStarted() {
816 super.handleStarted();
817 }
818
819 @Override
cbdacf03 820 public void handleData(final ITmfEvent event) {
a79913eb
FC
821 super.handleData(event);
822 if (event != null) {
cbdacf03 823 final ITmfTimestamp ts = event.getTimestamp();
a79913eb 824 if (startTime == null)
4df4581d 825 startTime = ts.clone();
826 lastTime = ts.clone();
cbdacf03 827 if ((getNbRead() % fIndexPageSize) == 1 && getNbRead() != 1)
a79913eb 828 updateExperiment();
a79913eb
FC
829 }
830 }
831
832 @Override
833 public void handleSuccess() {
ce2388e0 834 // long indexingEnd = System.nanoTime();
9b635e61 835
cbdacf03
FC
836 // if the end time is a real value then it is the streaming safe
837 // time stamp
838 // set the last time to the safe time stamp to prevent
839 // unnecessary indexing requests
840 if (getRange().getEndTime() != TmfTimestamp.BIG_CRUNCH)
a79913eb 841 lastTime = getRange().getEndTime();
a79913eb 842 updateExperiment();
ce2388e0 843 // System.out.println(System.currentTimeMillis() + ": Experiment indexing completed");
f9673903 844
ce2388e0
FC
845 // long average = (indexingEnd - indexingStart) / fNbEvents;
846 // System.out.println(getName() + ": start=" + startTime + ", end=" + lastTime + ", elapsed="
847 // + (indexingEnd * 1.0 - indexingStart) / 1000000000);
848 // System.out.println(getName() + ": nbEvents=" + fNbEvents + " (" + (average / 1000) + "."
849 // + (average % 1000) + " us/evt)");
a79913eb
FC
850 super.handleSuccess();
851 }
e31e01e8 852
05bd3318
FC
853 @Override
854 public void handleCompleted() {
855 job.cancel();
a79913eb
FC
856 super.handleCompleted();
857 synchronized (fCheckpoints) {
858 fIndexing = false;
a4115405 859 if (fIndexingPendingRange != TmfTimeRange.NULL_RANGE) {
a79913eb 860 indexExperiment(false, (int) fNbEvents, fIndexingPendingRange);
a4115405 861 fIndexingPendingRange = TmfTimeRange.NULL_RANGE;
a79913eb
FC
862 }
863 }
05bd3318
FC
864 }
865
a79913eb 866 private void updateExperiment() {
cbdacf03
FC
867 final int nbRead = getNbRead();
868 if (startTime != null)
4df4581d 869 fTimeRange = new TmfTimeRange(startTime, lastTime.clone());
a79913eb 870 if (nbRead != 0) {
ce2388e0
FC
871 // updateTimeRange();
872 // updateNbEvents();
a79913eb
FC
873 fNbEvents = initialNbEvents + nbRead;
874 notifyListeners();
875 }
876 }
877 };
878
879 sendRequest((ITmfDataRequest<T>) request);
880 if (waitForCompletion)
881 try {
882 request.waitForCompletion();
cbdacf03 883 } catch (final InterruptedException e) {
a79913eb
FC
884 e.printStackTrace();
885 }
886 }
887
888 protected void notifyListeners() {
889 broadcast(new TmfExperimentUpdatedSignal(this, this)); // , null));
cbdacf03
FC
890 // broadcast(new TmfExperimentRangeUpdatedSignal(this, this,
891 // fTimeRange)); // , null));
a79913eb
FC
892 }
893
8c8bf09f
ASL
894 // ------------------------------------------------------------------------
895 // Signal handlers
896 // ------------------------------------------------------------------------
897
898 @TmfSignalHandler
cbdacf03
FC
899 public void experimentSelected(final TmfExperimentSelectedSignal<T> signal) {
900 final TmfExperiment<?> experiment = signal.getExperiment();
a79913eb
FC
901 if (experiment == this) {
902 setCurrentExperiment(experiment);
6e85c58d 903 fEndSynchReference = Integer.valueOf(signal.getReference());
a79913eb 904 }
8c8bf09f
ASL
905 }
906
1b70b6dc 907 @TmfSignalHandler
cbdacf03 908 public void endSync(final TmfEndSynchSignal signal) {
1b70b6dc
PT
909 if (fEndSynchReference != null && fEndSynchReference.intValue() == signal.getReference()) {
910 fEndSynchReference = null;
911 initializeStreamingMonitor();
912 }
1b70b6dc
PT
913 }
914
8c8bf09f 915 @TmfSignalHandler
cbdacf03 916 public void experimentUpdated(final TmfExperimentUpdatedSignal signal) {
8c8bf09f
ASL
917 }
918
1b70b6dc 919 @TmfSignalHandler
cbdacf03
FC
920 public void experimentRangeUpdated(final TmfExperimentRangeUpdatedSignal signal) {
921 if (signal.getExperiment() == this)
09d11238 922 indexExperiment(false, (int) fNbEvents, signal.getRange());
1b70b6dc
PT
923 }
924
8c8bf09f 925 @TmfSignalHandler
cbdacf03
FC
926 public void traceUpdated(final TmfTraceUpdatedSignal signal) {
927 for (final ITmfTrace<T> trace : fTraces)
a79913eb
FC
928 if (trace == signal.getTrace()) {
929 synchronized (fCheckpoints) {
930 if (fIndexing) {
cbdacf03 931 if (fIndexingPendingRange == TmfTimeRange.NULL_RANGE)
a79913eb 932 fIndexingPendingRange = signal.getRange();
cbdacf03 933 else {
4df4581d 934 ITmfTimestamp startTime = fIndexingPendingRange.getStartTime();
935 ITmfTimestamp endTime = fIndexingPendingRange.getEndTime();
cbdacf03 936 if (signal.getRange().getStartTime().compareTo(startTime) < 0)
a79913eb 937 startTime = signal.getRange().getStartTime();
cbdacf03 938 if (signal.getRange().getEndTime().compareTo(endTime) > 0)
a79913eb 939 endTime = signal.getRange().getEndTime();
a79913eb
FC
940 fIndexingPendingRange = new TmfTimeRange(startTime, endTime);
941 }
942 return;
943 }
944 }
945 indexExperiment(false, (int) fNbEvents, signal.getRange());
946 return;
947 }
8c8bf09f
ASL
948 }
949
12c155f5
FC
950 @Override
951 public String getPath() {
952 // TODO Auto-generated method stub
953 return null;
954 }
955
828e5592 956 /**
a1091415 957 * Set the file to be used for bookmarks on this experiment
cbdacf03 958 *
a1091415 959 * @param file the bookmarks file
828e5592 960 */
cbdacf03 961 public void setBookmarksFile(final IFile file) {
a1091415
PT
962 fBookmarksFile = file;
963 }
964
965 /**
966 * Get the file used for bookmarks on this experiment
cbdacf03 967 *
a1091415
PT
968 * @return the bookmarks file or null if none is set
969 */
970 public IFile getBookmarksFile() {
971 return fBookmarksFile;
972 }
973
cbdacf03
FC
974 /*
975 * (non-Javadoc)
976 *
977 * @see
978 * org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#setResource(org.eclipse
979 * .core.resources.IResource)
a1091415
PT
980 */
981 @Override
cbdacf03 982 public void setResource(final IResource resource) {
828e5592
PT
983 fResource = resource;
984 }
985
cbdacf03
FC
986 /*
987 * (non-Javadoc)
988 *
a1091415 989 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
828e5592 990 */
a1091415 991 @Override
828e5592
PT
992 public IResource getResource() {
993 return fResource;
994 }
4dc47e28 995}
This page took 0.126524 seconds and 5 git commands to generate.