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