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