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