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