Work on TmfCheckpoint
[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
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
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) {
9b635e61 289// Tracer.trace("Ctx: Arming request - start");
cbdacf03
FC
290 ITmfTimestamp timestamp = (request instanceof ITmfEventRequest<?>) ? ((ITmfEventRequest<T>) request).getRange()
291 .getStartTime()
12c155f5 292 : null;
a79913eb 293
cbdacf03 294 if (TmfTimestamp.BIG_BANG.equals(timestamp) || request.getIndex() > 0)
a79913eb 295 timestamp = null; // use request index
a79913eb
FC
296
297 TmfExperimentContext context = null;
298 if (timestamp != null) {
299 // seek by timestamp
300 context = seekEvent(timestamp);
301 ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
cbdacf03
FC
302 } else // Seek by rank
303 if ((fExperimentContext != null) && fExperimentContext.getRank() == request.getIndex())
304 // We are already at the right context -> no need to seek
305 context = fExperimentContext;
306 else
307 context = seekEvent(request.getIndex());
9b635e61 308// Tracer.trace("Ctx: Arming request - done");
a79913eb
FC
309 return context;
310 }
311
312 @SuppressWarnings("unchecked")
313 @Override
cbdacf03
FC
314 public T getNext(final ITmfContext context) {
315 if (context instanceof TmfExperimentContext)
316 return (T) getNextEvent(context);
a79913eb
FC
317 return null;
318 }
319
320 // ------------------------------------------------------------------------
9f584e4c
FC
321 // ITmfTrace trace positioning
322 // ------------------------------------------------------------------------
323
a79913eb
FC
324 // Returns a brand new context based on the location provided
325 // and initializes the event queues
326 @Override
cbdacf03 327 public synchronized TmfExperimentContext seekLocation(final ITmfLocation<?> location) {
a79913eb 328 // Validate the location
cbdacf03 329 if (location != null && !(location instanceof TmfExperimentLocation))
a79913eb 330 return null; // Throw an exception?
8f50c396 331
cbdacf03 332 if (fTraces == null)
a79913eb 333 return null;
8f50c396 334
a79913eb 335 // Instantiate the location
cbdacf03
FC
336 final TmfExperimentLocation expLocation = (location == null) ? new TmfExperimentLocation(new TmfLocationArray(
337 new ITmfLocation<?>[fTraces.length]), new long[fTraces.length]) : (TmfExperimentLocation) location
338 .clone();
8f50c396 339
a79913eb 340 // Create and populate the context's traces contexts
cbdacf03 341 final TmfExperimentContext context = new TmfExperimentContext(fTraces, new TmfContext[fTraces.length]);
9b635e61
FC
342// Tracer.trace("Ctx: SeekLocation - start");
343
a79913eb
FC
344 long rank = 0;
345 for (int i = 0; i < fTraces.length; i++) {
346 // Get the relevant trace attributes
cbdacf03
FC
347 final ITmfLocation<?> traceLocation = expLocation.getLocation().locations[i];
348 final long traceRank = expLocation.getRanks()[i];
8f50c396 349
a79913eb
FC
350 // Set the corresponding sub-context
351 context.getContexts()[i] = fTraces[i].seekLocation(traceLocation);
352 context.getContexts()[i].setRank(traceRank);
353 rank += traceRank;
8f50c396 354
a79913eb 355 // Set the trace location and read the corresponding event
cbdacf03
FC
356 /*
357 * The (TmfContext) cast should be safe since we created 'context'
358 * ourselves higher up.
359 */
34ccf9a9 360 expLocation.getLocation().locations[i] = ((TmfContext) context.getContexts()[i]).getLocation().clone();
a79913eb
FC
361 context.getEvents()[i] = fTraces[i].getNextEvent(context.getContexts()[i]);
362 }
8f50c396 363
9b635e61
FC
364// Tracer.trace("Ctx: SeekLocation - done");
365
a79913eb
FC
366 // Finalize context
367 context.setLocation(expLocation);
368 context.setLastTrace(TmfExperimentContext.NO_TRACE);
369 context.setRank(rank);
9b635e61 370
a79913eb 371 fExperimentContext = context;
9b635e61 372
a79913eb
FC
373 return context;
374 }
9f584e4c 375
a79913eb
FC
376 /*
377 * (non-Javadoc)
378 *
cbdacf03
FC
379 * @see
380 * org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools
381 * .tmf.event.TmfTimestamp)
a79913eb
FC
382 */
383 @Override
4df4581d 384 public synchronized TmfExperimentContext seekEvent(ITmfTimestamp timestamp) {
9b635e61
FC
385
386// Tracer.trace("Ctx: seekEvent(TS) - start");
8c8bf09f 387
cbdacf03 388 if (timestamp == null)
a4115405 389 timestamp = TmfTimestamp.BIG_BANG;
9f584e4c 390
a79913eb
FC
391 // First, find the right checkpoint
392 int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
9f584e4c
FC
393
394 // In the very likely case that the checkpoint was not found, bsearch
395 // returns its negated would-be location (not an offset...). From that
396 // index, we can then position the stream and get the event.
cbdacf03 397 if (index < 0)
9f584e4c 398 index = Math.max(0, -(index + 2));
9f584e4c
FC
399
400 // Position the experiment at the checkpoint
452ad365 401 ITmfLocation<?> location;
9f584e4c 402 synchronized (fCheckpoints) {
a79913eb 403 if (fCheckpoints.size() > 0) {
cbdacf03 404 if (index >= fCheckpoints.size())
a79913eb 405 index = fCheckpoints.size() - 1;
a79913eb 406 location = fCheckpoints.elementAt(index).getLocation();
cbdacf03 407 } else
a79913eb 408 location = null;
9f584e4c
FC
409 }
410
cbdacf03 411 final TmfExperimentContext context = seekLocation(location);
cbd4ad82 412 context.setRank((long) index * fIndexPageSize);
9f584e4c 413
a79913eb 414 // And locate the event
72f1e62a 415 ITmfEvent event = parseEvent(context);
9f584e4c 416 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
a79913eb
FC
417 getNextEvent(context);
418 event = parseEvent(context);
9f584e4c
FC
419 }
420
f6b14ce2 421 if (event == null) {
a79913eb
FC
422 context.setLocation(null);
423 context.setRank(ITmfContext.UNKNOWN_RANK);
9b635e61 424 }
f6b14ce2
FC
425
426 return context;
a79913eb 427 }
8c8bf09f 428
a79913eb
FC
429 /*
430 * (non-Javadoc)
431 *
432 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(long)
433 */
434 @Override
cbdacf03 435 public synchronized TmfExperimentContext seekEvent(final long rank) {
9b635e61
FC
436
437// Tracer.trace("Ctx: seekEvent(rank) - start");
9f584e4c 438
54d55ced
FC
439 // Position the stream at the previous checkpoint
440 int index = (int) rank / fIndexPageSize;
441 ITmfLocation<?> location;
442 synchronized (fCheckpoints) {
cbdacf03 443 if (fCheckpoints.size() == 0)
a79913eb 444 location = null;
cbdacf03
FC
445 else {
446 if (index >= fCheckpoints.size())
a79913eb 447 index = fCheckpoints.size() - 1;
a79913eb
FC
448 location = fCheckpoints.elementAt(index).getLocation();
449 }
54d55ced 450 }
e31e01e8 451
cbdacf03 452 final TmfExperimentContext context = seekLocation(location);
9b635e61 453 context.setRank((long) index * fIndexPageSize);
54d55ced 454
a79913eb 455 // And locate the event
72f1e62a 456 ITmfEvent event = parseEvent(context);
9b635e61 457 long pos = context.getRank();
fa867360 458 while (event != null && pos++ < rank) {
a79913eb
FC
459 getNextEvent(context);
460 event = parseEvent(context);
54d55ced 461 }
9f584e4c 462
f6b14ce2 463 if (event == null) {
a79913eb
FC
464 context.setLocation(null);
465 context.setRank(ITmfContext.UNKNOWN_RANK);
9b635e61 466 }
f6b14ce2 467
a79913eb
FC
468 return context;
469 }
8c8bf09f 470
c76c54bb 471 @Override
cbdacf03
FC
472 public TmfContext seekLocation(final double ratio) {
473 final TmfContext context = seekEvent((long) (ratio * getNbEvents()));
c76c54bb
FC
474 return context;
475 }
476
a79913eb 477 @Override
cbdacf03
FC
478 public double getLocationRatio(final ITmfLocation<?> location) {
479 if (location instanceof TmfExperimentLocation)
a79913eb 480 return (double) seekLocation(location).getRank() / getNbEvents();
c76c54bb
FC
481 return 0;
482 }
483
a79913eb
FC
484 @Override
485 public ITmfLocation<?> getCurrentLocation() {
cbdacf03 486 if (fExperimentContext != null)
a79913eb 487 return fExperimentContext.getLocation();
a79913eb
FC
488 return null;
489 }
c76c54bb 490
9b635e61
FC
491// private void dumpContext(TmfExperimentContext context, boolean isBefore) {
492
493// TmfContext context0 = context.getContexts()[0];
494// TmfEvent event0 = context.getEvents()[0];
495// TmfExperimentLocation location0 = (TmfExperimentLocation) context.getLocation();
496// long rank0 = context.getRank();
497// int trace = context.getLastTrace();
498//
499// StringBuffer result = new StringBuffer("Ctx: " + (isBefore ? "B " : "A "));
500//
501// result.append("[Ctx: fLoc= " + context0.getLocation().toString() + ", fRnk= " + context0.getRank() + "] ");
502// result.append("[Evt: " + event0.getTimestamp().toString() + "] ");
503// result.append("[Loc: fLoc= " + location0.getLocation()[0].toString() + ", fRnk= " + location0.getRanks()[0] + "] ");
504// result.append("[Rnk: " + rank0 + "], [Trc: " + trace + "]");
505// Tracer.trace(result.toString());
506// }
54d55ced 507
0d9a6d76 508 /**
cbdacf03
FC
509 * Scan the next events from all traces and return the next one in
510 * chronological order.
0d9a6d76
FC
511 *
512 * @param context the trace context
513 * @return the next event
514 */
a79913eb 515 @Override
cbdacf03 516 public synchronized ITmfEvent getNextEvent(final ITmfContext context) {
a79913eb
FC
517
518 // Validate the context
cbdacf03 519 if (!(context instanceof TmfExperimentContext))
a79913eb 520 return null; // Throw an exception?
54d55ced 521
cbdacf03
FC
522 if (!context.equals(fExperimentContext))
523 // Tracer.trace("Ctx: Restoring context");
a79913eb 524 fExperimentContext = seekLocation(context.getLocation());
a79913eb 525
cbdacf03 526 final TmfExperimentContext expContext = (TmfExperimentContext) context;
8f50c396 527
9b635e61
FC
528// dumpContext(expContext, true);
529
a79913eb 530 // If an event was consumed previously, get the next one from that trace
cbdacf03 531 final int lastTrace = expContext.getLastTrace();
a79913eb 532 if (lastTrace != TmfExperimentContext.NO_TRACE) {
cbdacf03 533 final ITmfContext traceContext = expContext.getContexts()[lastTrace];
a79913eb
FC
534 expContext.getEvents()[lastTrace] = expContext.getTraces()[lastTrace].getNextEvent(traceContext);
535 expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
536 }
8f50c396 537
a79913eb 538 // Scan the candidate events and identify the "next" trace to read from
cbdacf03
FC
539 final ITmfEvent eventArray[] = expContext.getEvents();
540 if (eventArray == null)
1324801a 541 return null;
a79913eb 542 int trace = TmfExperimentContext.NO_TRACE;
a4115405 543 ITmfTimestamp timestamp = TmfTimestamp.BIG_CRUNCH;
1324801a
FC
544 if (eventArray.length == 1) {
545 if (eventArray[0] != null) {
546 timestamp = eventArray[0].getTimestamp();
547 trace = 0;
548 }
cbdacf03 549 } else
1324801a 550 for (int i = 0; i < eventArray.length; i++) {
cbdacf03 551 final ITmfEvent event = eventArray[i];
1324801a 552 if (event != null && event.getTimestamp() != null) {
cbdacf03 553 final ITmfTimestamp otherTS = event.getTimestamp();
1324801a
FC
554 if (otherTS.compareTo(timestamp, true) < 0) {
555 trace = i;
556 timestamp = otherTS;
557 }
558 }
559 }
1324801a 560 // Update the experiment context and set the "next" event
72f1e62a 561 ITmfEvent event = null;
a79913eb
FC
562 if (trace != TmfExperimentContext.NO_TRACE) {
563 updateIndex(expContext, timestamp);
82e04272 564
cbdacf03
FC
565 final ITmfContext traceContext = expContext.getContexts()[trace];
566 final TmfExperimentLocation expLocation = (TmfExperimentLocation) expContext.getLocation();
64fe8e8a 567// expLocation.getLocation()[trace] = traceContext.getLocation().clone();
cbdacf03 568 expLocation.getLocation().locations[trace] = traceContext.getLocation().clone();
82e04272
FC
569
570// updateIndex(expContext, timestamp);
571
a79913eb
FC
572 expLocation.getRanks()[trace] = traceContext.getRank();
573 expContext.setLastTrace(trace);
cbdacf03 574 expContext.increaseRank();
a79913eb
FC
575 event = expContext.getEvents()[trace];
576 fExperimentContext = expContext;
577 }
8f50c396 578
9b635e61
FC
579// if (event != null) {
580// Tracer.trace("Exp: " + (expContext.getRank() - 1) + ": " + event.getTimestamp().toString());
581// dumpContext(expContext, false);
582// Tracer.trace("Ctx: Event returned= " + event.getTimestamp().toString());
583// }
584
a79913eb
FC
585 return event;
586 }
587
cbdacf03 588 public synchronized void updateIndex(final ITmfContext context, final ITmfTimestamp timestamp) {
a79913eb 589 // Build the index as we go along
cbdacf03
FC
590 final long rank = context.getRank();
591 if (context.hasValidRank() && (rank % fIndexPageSize) == 0) {
a79913eb 592 // Determine the table position
cbdacf03 593 final long position = rank / fIndexPageSize;
a79913eb
FC
594 // Add new entry at proper location (if empty)
595 if (fCheckpoints.size() == position) {
cbdacf03 596 final ITmfLocation<?> location = context.getLocation().clone();
a79913eb 597 fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location));
12c155f5
FC
598// System.out.println(this + "[" + (fCheckpoints.size() - 1) + "] " + timestamp + ", "
599// + location.toString());
a79913eb
FC
600 }
601 }
602 }
603
604 /*
605 * (non-Javadoc)
606 *
cbdacf03
FC
607 * @see
608 * org.eclipse.linuxtools.tmf.trace.ITmfTrace#parseEvent(org.eclipse.linuxtools
609 * .tmf.trace.TmfContext)
a79913eb
FC
610 */
611 @Override
cbdacf03 612 public ITmfEvent parseEvent(final ITmfContext context) {
a79913eb
FC
613
614 // Validate the context
cbdacf03 615 if (!(context instanceof TmfExperimentContext))
a79913eb 616 return null; // Throw an exception?
a79913eb 617
cbdacf03
FC
618 if (!context.equals(fExperimentContext))
619 // Tracer.trace("Ctx: Restoring context");
a79913eb 620 seekLocation(context.getLocation());
a79913eb 621
cbdacf03 622 final TmfExperimentContext expContext = (TmfExperimentContext) context;
a79913eb
FC
623
624 // If an event was consumed previously, get the next one from that trace
cbdacf03 625 final int lastTrace = expContext.getLastTrace();
a79913eb 626 if (lastTrace != TmfExperimentContext.NO_TRACE) {
cbdacf03 627 final ITmfContext traceContext = expContext.getContexts()[lastTrace];
a79913eb
FC
628 expContext.getEvents()[lastTrace] = expContext.getTraces()[lastTrace].getNextEvent(traceContext);
629 expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
630 fExperimentContext = (TmfExperimentContext) context;
631 }
632
633 // Scan the candidate events and identify the "next" trace to read from
634 int trace = TmfExperimentContext.NO_TRACE;
a4115405 635 ITmfTimestamp timestamp = TmfTimestamp.BIG_CRUNCH;
a79913eb 636 for (int i = 0; i < expContext.getTraces().length; i++) {
cbdacf03 637 final ITmfEvent event = expContext.getEvents()[i];
a79913eb 638 if (event != null && event.getTimestamp() != null) {
cbdacf03 639 final ITmfTimestamp otherTS = event.getTimestamp();
a79913eb
FC
640 if (otherTS.compareTo(timestamp, true) < 0) {
641 trace = i;
642 timestamp = otherTS;
643 }
644 }
645 }
646
72f1e62a 647 ITmfEvent event = null;
cbdacf03 648 if (trace != TmfExperimentContext.NO_TRACE)
a79913eb 649 event = expContext.getEvents()[trace];
a79913eb
FC
650
651 return event;
652 }
653
654 /*
655 * (non-Javadoc)
656 *
657 * @see java.lang.Object#toString()
658 */
659 @Override
3b38ea61 660 @SuppressWarnings("nls")
a79913eb
FC
661 public String toString() {
662 return "[TmfExperiment (" + getName() + ")]";
663 }
8c8bf09f
ASL
664
665 // ------------------------------------------------------------------------
666 // Indexing
667 // ------------------------------------------------------------------------
668
1b70b6dc 669 private synchronized void initializeStreamingMonitor() {
cbdacf03 670 if (fInitialized)
828e5592 671 return;
828e5592
PT
672 fInitialized = true;
673
1b70b6dc 674 if (getStreamingInterval() == 0) {
cbdacf03
FC
675 final TmfContext context = seekLocation(null);
676 final ITmfEvent event = getNext(context);
677 if (event == null)
1b70b6dc 678 return;
cbdacf03 679 final TmfTimeRange timeRange = new TmfTimeRange(event.getTimestamp().clone(), TmfTimestamp.BIG_CRUNCH);
828e5592
PT
680 final TmfExperimentRangeUpdatedSignal signal = new TmfExperimentRangeUpdatedSignal(this, this, timeRange);
681
682 // Broadcast in separate thread to prevent deadlock
683 new Thread() {
cbdacf03 684
828e5592
PT
685 @Override
686 public void run() {
687 broadcast(signal);
688 }
689 }.start();
1b70b6dc
PT
690 return;
691 }
692
693 final Thread thread = new Thread("Streaming Monitor for experiment " + getName()) { //$NON-NLS-1$
cbdacf03 694
dfee01ae 695 ITmfTimestamp safeTimestamp = null;
1b70b6dc
PT
696 TmfTimeRange timeRange = null;
697
698 @Override
699 public void run() {
700 while (!fExecutor.isShutdown()) {
701 if (!isIndexingBusy()) {
a4115405
FC
702 ITmfTimestamp startTimestamp = TmfTimestamp.BIG_CRUNCH;
703 ITmfTimestamp endTimestamp = TmfTimestamp.BIG_BANG;
cbdacf03
FC
704 for (final ITmfTrace<T> trace : fTraces) {
705 if (trace.getStartTime().compareTo(startTimestamp) < 0)
1b70b6dc 706 startTimestamp = trace.getStartTime();
cbdacf03 707 if (trace.getStreamingInterval() != 0 && trace.getEndTime().compareTo(endTimestamp) > 0)
1b70b6dc 708 endTimestamp = trace.getEndTime();
1b70b6dc 709 }
cbdacf03 710 if (safeTimestamp != null && safeTimestamp.compareTo(getTimeRange().getEndTime(), false) > 0)
1b70b6dc 711 timeRange = new TmfTimeRange(startTimestamp, safeTimestamp);
cbdacf03 712 else
1b70b6dc 713 timeRange = null;
1b70b6dc
PT
714 safeTimestamp = endTimestamp;
715 if (timeRange != null) {
cbdacf03
FC
716 final TmfExperimentRangeUpdatedSignal signal =
717 new TmfExperimentRangeUpdatedSignal(TmfExperiment.this, TmfExperiment.this,
718 timeRange);
1b70b6dc
PT
719 broadcast(signal);
720 }
721 }
722 try {
723 Thread.sleep(getStreamingInterval());
cbdacf03 724 } catch (final InterruptedException e) {
1b70b6dc
PT
725 e.printStackTrace();
726 }
727 }
728 }
729 };
730 thread.start();
731 }
732
cbdacf03
FC
733 /*
734 * (non-Javadoc)
735 *
1b70b6dc
PT
736 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
737 */
738 @Override
739 public long getStreamingInterval() {
740 long interval = 0;
cbdacf03 741 for (final ITmfTrace<T> trace : fTraces)
1b70b6dc 742 interval = Math.max(interval, trace.getStreamingInterval());
1b70b6dc
PT
743 return interval;
744 }
745
a79913eb 746 /*
cbdacf03
FC
747 * The experiment holds the globally ordered events of its set of traces. It
748 * is expected to provide access to each individual event by index i.e. it
749 * must be possible to request the Nth event of the experiment.
a79913eb 750 *
cbdacf03
FC
751 * The purpose of the index is to keep the information needed to rapidly
752 * restore the traces contexts at regular intervals (every INDEX_PAGE_SIZE
753 * event).
a79913eb 754 */
8c8bf09f 755
a79913eb
FC
756 // The index page size
757 private static final int DEFAULT_INDEX_PAGE_SIZE = 5000;
758 protected int fIndexPageSize;
759 protected boolean fIndexing = false;
a4115405 760 protected TmfTimeRange fIndexingPendingRange = TmfTimeRange.NULL_RANGE;
e31e01e8 761
1b70b6dc
PT
762 private Integer fEndSynchReference;
763
9b635e61
FC
764// private static BufferedWriter fEventLog = null;
765// private static BufferedWriter openLogFile(String filename) {
766// BufferedWriter outfile = null;
767// try {
768// outfile = new BufferedWriter(new FileWriter(filename));
769// } catch (IOException e) {
770// e.printStackTrace();
771// }
772// return outfile;
773// }
774
a79913eb
FC
775 protected boolean isIndexingBusy() {
776 synchronized (fCheckpoints) {
777 return fIndexing;
778 }
779 }
780
8636b448 781 @Override
cbdacf03
FC
782 public void indexTrace(final boolean waitForCompletion) {
783 if (waitForCompletion)
8636b448 784 initializeStreamingMonitor();
a79913eb
FC
785 }
786
787 @SuppressWarnings("unchecked")
cbdacf03 788 private void indexExperiment(final boolean waitForCompletion, final int index, final TmfTimeRange timeRange) {
a79913eb
FC
789
790 synchronized (fCheckpoints) {
cbdacf03 791 if (fIndexing)
a79913eb 792 return;
a79913eb
FC
793 fIndexing = true;
794 }
795
8a0edc79 796 final Job job = new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
cbdacf03 797
8a0edc79 798 @Override
cbdacf03
FC
799 protected IStatus run(final IProgressMonitor monitor) {
800 while (!monitor.isCanceled())
8a0edc79
FC
801 try {
802 Thread.sleep(100);
cbdacf03 803 } catch (final InterruptedException e) {
8a0edc79
FC
804 return Status.OK_STATUS;
805 }
8a0edc79
FC
806 monitor.done();
807 return Status.OK_STATUS;
808 }
809 };
810 job.schedule();
811
9b635e61 812// fEventLog = openLogFile("TraceEvent.log");
12c155f5 813// System.out.println(System.currentTimeMillis() + ": Experiment indexing started");
550d787e 814
cbdacf03
FC
815 final ITmfEventRequest<ITmfEvent> request = new TmfEventRequest<ITmfEvent>(ITmfEvent.class, timeRange, index,
816 TmfDataRequest.ALL_DATA,
817 fIndexPageSize, ITmfDataRequest.ExecutionType.BACKGROUND) { // PATA
818 // FOREGROUND
550d787e 819
12c155f5 820// long indexingStart = System.nanoTime();
a79913eb 821
a4115405
FC
822 ITmfTimestamp startTime = (fTimeRange == TmfTimeRange.NULL_RANGE) ? null : fTimeRange.getStartTime();
823 ITmfTimestamp lastTime = (fTimeRange == TmfTimeRange.NULL_RANGE) ? null : fTimeRange.getEndTime();
a79913eb
FC
824 long initialNbEvents = fNbEvents;
825
826 @Override
827 public void handleStarted() {
828 super.handleStarted();
829 }
830
831 @Override
cbdacf03 832 public void handleData(final ITmfEvent event) {
a79913eb
FC
833 super.handleData(event);
834 if (event != null) {
cbdacf03 835 final ITmfTimestamp ts = event.getTimestamp();
a79913eb 836 if (startTime == null)
4df4581d 837 startTime = ts.clone();
838 lastTime = ts.clone();
cbdacf03 839 if ((getNbRead() % fIndexPageSize) == 1 && getNbRead() != 1)
a79913eb 840 updateExperiment();
a79913eb
FC
841 }
842 }
843
844 @Override
845 public void handleSuccess() {
12c155f5 846// long indexingEnd = System.nanoTime();
9b635e61 847
cbdacf03
FC
848 // if the end time is a real value then it is the streaming safe
849 // time stamp
850 // set the last time to the safe time stamp to prevent
851 // unnecessary indexing requests
852 if (getRange().getEndTime() != TmfTimestamp.BIG_CRUNCH)
a79913eb 853 lastTime = getRange().getEndTime();
a79913eb 854 updateExperiment();
12c155f5 855// System.out.println(System.currentTimeMillis() + ": Experiment indexing completed");
f9673903 856
12c155f5
FC
857// long average = (indexingEnd - indexingStart) / fNbEvents;
858// System.out.println(getName() + ": start=" + startTime + ", end=" + lastTime + ", elapsed="
859// + (indexingEnd * 1.0 - indexingStart) / 1000000000);
860// System.out.println(getName() + ": nbEvents=" + fNbEvents + " (" + (average / 1000) + "."
861// + (average % 1000) + " us/evt)");
a79913eb
FC
862 super.handleSuccess();
863 }
e31e01e8 864
05bd3318
FC
865 @Override
866 public void handleCompleted() {
867 job.cancel();
a79913eb
FC
868 super.handleCompleted();
869 synchronized (fCheckpoints) {
870 fIndexing = false;
a4115405 871 if (fIndexingPendingRange != TmfTimeRange.NULL_RANGE) {
a79913eb 872 indexExperiment(false, (int) fNbEvents, fIndexingPendingRange);
a4115405 873 fIndexingPendingRange = TmfTimeRange.NULL_RANGE;
a79913eb
FC
874 }
875 }
05bd3318
FC
876 }
877
a79913eb 878 private void updateExperiment() {
cbdacf03
FC
879 final int nbRead = getNbRead();
880 if (startTime != null)
4df4581d 881 fTimeRange = new TmfTimeRange(startTime, lastTime.clone());
a79913eb 882 if (nbRead != 0) {
0c2a2e08
FC
883// updateTimeRange();
884// updateNbEvents();
a79913eb
FC
885 fNbEvents = initialNbEvents + nbRead;
886 notifyListeners();
887 }
888 }
889 };
890
891 sendRequest((ITmfDataRequest<T>) request);
892 if (waitForCompletion)
893 try {
894 request.waitForCompletion();
cbdacf03 895 } catch (final InterruptedException e) {
a79913eb
FC
896 e.printStackTrace();
897 }
898 }
899
900 protected void notifyListeners() {
901 broadcast(new TmfExperimentUpdatedSignal(this, this)); // , null));
cbdacf03
FC
902 // broadcast(new TmfExperimentRangeUpdatedSignal(this, this,
903 // fTimeRange)); // , null));
a79913eb
FC
904 }
905
8c8bf09f
ASL
906 // ------------------------------------------------------------------------
907 // Signal handlers
908 // ------------------------------------------------------------------------
909
910 @TmfSignalHandler
cbdacf03
FC
911 public void experimentSelected(final TmfExperimentSelectedSignal<T> signal) {
912 final TmfExperiment<?> experiment = signal.getExperiment();
a79913eb
FC
913 if (experiment == this) {
914 setCurrentExperiment(experiment);
6e85c58d 915 fEndSynchReference = Integer.valueOf(signal.getReference());
a79913eb 916 }
8c8bf09f
ASL
917 }
918
1b70b6dc 919 @TmfSignalHandler
cbdacf03 920 public void endSync(final TmfEndSynchSignal signal) {
1b70b6dc
PT
921 if (fEndSynchReference != null && fEndSynchReference.intValue() == signal.getReference()) {
922 fEndSynchReference = null;
923 initializeStreamingMonitor();
924 }
cbdacf03 925
1b70b6dc
PT
926 }
927
8c8bf09f 928 @TmfSignalHandler
cbdacf03 929 public void experimentUpdated(final TmfExperimentUpdatedSignal signal) {
8c8bf09f
ASL
930 }
931
1b70b6dc 932 @TmfSignalHandler
cbdacf03
FC
933 public void experimentRangeUpdated(final TmfExperimentRangeUpdatedSignal signal) {
934 if (signal.getExperiment() == this)
09d11238 935 indexExperiment(false, (int) fNbEvents, signal.getRange());
1b70b6dc
PT
936 }
937
8c8bf09f 938 @TmfSignalHandler
cbdacf03
FC
939 public void traceUpdated(final TmfTraceUpdatedSignal signal) {
940 for (final ITmfTrace<T> trace : fTraces)
a79913eb
FC
941 if (trace == signal.getTrace()) {
942 synchronized (fCheckpoints) {
943 if (fIndexing) {
cbdacf03 944 if (fIndexingPendingRange == TmfTimeRange.NULL_RANGE)
a79913eb 945 fIndexingPendingRange = signal.getRange();
cbdacf03 946 else {
4df4581d 947 ITmfTimestamp startTime = fIndexingPendingRange.getStartTime();
948 ITmfTimestamp endTime = fIndexingPendingRange.getEndTime();
cbdacf03 949 if (signal.getRange().getStartTime().compareTo(startTime) < 0)
a79913eb 950 startTime = signal.getRange().getStartTime();
cbdacf03 951 if (signal.getRange().getEndTime().compareTo(endTime) > 0)
a79913eb 952 endTime = signal.getRange().getEndTime();
a79913eb
FC
953 fIndexingPendingRange = new TmfTimeRange(startTime, endTime);
954 }
955 return;
956 }
957 }
958 indexExperiment(false, (int) fNbEvents, signal.getRange());
959 return;
960 }
8c8bf09f
ASL
961 }
962
12c155f5
FC
963 @Override
964 public String getPath() {
965 // TODO Auto-generated method stub
966 return null;
967 }
968
828e5592 969 /**
a1091415 970 * Set the file to be used for bookmarks on this experiment
cbdacf03 971 *
a1091415 972 * @param file the bookmarks file
828e5592 973 */
cbdacf03 974 public void setBookmarksFile(final IFile file) {
a1091415
PT
975 fBookmarksFile = file;
976 }
977
978 /**
979 * Get the file used for bookmarks on this experiment
cbdacf03 980 *
a1091415
PT
981 * @return the bookmarks file or null if none is set
982 */
983 public IFile getBookmarksFile() {
984 return fBookmarksFile;
985 }
986
cbdacf03
FC
987 /*
988 * (non-Javadoc)
989 *
990 * @see
991 * org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#setResource(org.eclipse
992 * .core.resources.IResource)
a1091415
PT
993 */
994 @Override
cbdacf03 995 public void setResource(final IResource resource) {
828e5592
PT
996 fResource = resource;
997 }
998
cbdacf03
FC
999 /*
1000 * (non-Javadoc)
1001 *
a1091415 1002 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
828e5592 1003 */
a1091415 1004 @Override
828e5592
PT
1005 public IResource getResource() {
1006 return fResource;
1007 }
4dc47e28 1008}
This page took 0.09953 seconds and 5 git commands to generate.