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