Copyright header update, 2015 edition
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / histogram / HistogramDataModel.java
CommitLineData
c392540b 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2011, 2015 Ericsson
bfe038ff 3 *
c392540b
FC
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
bfe038ff 8 *
c392540b
FC
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
bfe038ff 11 * Bernd Hufmann - Implementation of new interfaces/listeners and support for
fbd124dd 12 * time stamp in any order
e0752744 13 * Francois Chouinard - Moved from LTTng to TMF
00419b1f 14 * Francois Chouinard - Added support for empty initial buckets
0fcf3b09 15 * Patrick Tasse - Support selection range
95aa81ef 16 * Jean-Christian Kouamé, Simon Delisle - Added support to manage lost events
2fc582d2 17 * Xavier Raynaud - Support multi-trace coloring
c392540b
FC
18 *******************************************************************************/
19
2bdf0193 20package org.eclipse.tracecompass.tmf.ui.views.histogram;
c392540b
FC
21
22import java.util.Arrays;
c14c0757 23import java.util.Collection;
2fc582d2
XR
24import java.util.LinkedHashMap;
25import java.util.Map;
c392540b 26
fbd124dd 27import org.eclipse.core.runtime.ListenerList;
2bdf0193
AM
28import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
29import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
30import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
c392540b 31
c14c0757
GB
32import com.google.common.base.Function;
33import com.google.common.collect.FluentIterable;
34
c392540b 35/**
b544077e 36 * Histogram-independent data model.
f8177ba2 37 *
b544077e 38 * It has the following characteristics:
c392540b
FC
39 * <ul>
40 * <li>The <i>basetime</i> is the timestamp of the first event
41 * <li>There is a fixed number (<i>n</i>) of buckets of uniform duration
42 * (<i>d</i>)
43 * <li>The <i>timespan</i> of the model is thus: <i>n</i> * <i>d</i> time units
44 * <li>Bucket <i>i</i> holds the number of events that occurred in time range:
45 * [<i>basetime</i> + <i>i</i> * <i>d</i>, <i>basetime</i> + (<i>i</i> + 1) *
46 * <i>d</i>)
47 * </ul>
48 * Initially, the bucket durations is set to 1ns. As the events are read, they
49 * are tallied (using <i>countEvent()</i>) in the appropriate bucket (relative
50 * to the <i>basetime</i>).
51 * <p>
52 * Eventually, an event will have a timestamp that exceeds the <i>timespan</i>
53 * high end (determined by <i>n</i>, the number of buckets, and <i>d</i>, the
54 * bucket duration). At this point, the histogram needs to be compacted. This is
55 * done by simply merging adjacent buckets by pair, in effect doubling the
56 * <i>timespan</i> (<i>timespan'</i> = <i>n</i> * <i>d'</i>, where <i>d'</i> =
57 * 2<i>d</i>). This compaction happens as needed as the trace is read.
58 * <p>
fbd124dd 59 * The model allows for timestamps in not increasing order. The timestamps can
bfe038ff 60 * be fed to the model in any order. If an event has a timestamp less than the
fbd124dd 61 * <i>basetime</i>, the buckets will be moved to the right to account for the
bfe038ff 62 * new smaller timestamp. The new <i>basetime</i> is a multiple of the bucket
95aa81ef
JCK
63 * duration smaller then the previous <i>basetime</i>. Note that the
64 * <i>basetime</i> might no longer be the timestamp of an event. If necessary,
65 * the buckets will be compacted before moving to the right. This might be
66 * necessary to not lose any event counts at the end of the buckets array.
fbd124dd 67 * <p>
c392540b
FC
68 * The mapping from the model to the UI is performed by the <i>scaleTo()</i>
69 * method. By keeping the number of buckets <i>n</i> relatively large with
70 * respect to to the number of pixels in the actual histogram, we should achieve
71 * a nice result when visualizing the histogram.
72 * <p>
f8177ba2 73 *
00419b1f 74 * @version 2.0
b544077e 75 * @author Francois Chouinard
c392540b 76 */
fbd124dd 77public class HistogramDataModel implements IHistogramDataModel {
c392540b
FC
78
79 // ------------------------------------------------------------------------
80 // Constants
81 // ------------------------------------------------------------------------
82
b544077e 83 /**
95aa81ef 84 * The default number of buckets
b544077e 85 */
c392540b
FC
86 public static final int DEFAULT_NUMBER_OF_BUCKETS = 16 * 1000;
87
b544077e 88 /**
f8177ba2 89 * Number of events after which listeners will be notified.
b544077e 90 */
fbd124dd 91 public static final int REFRESH_FREQUENCY = DEFAULT_NUMBER_OF_BUCKETS;
bfe038ff 92
c392540b
FC
93 // ------------------------------------------------------------------------
94 // Attributes
95 // ------------------------------------------------------------------------
96
2fc582d2
XR
97 // Trace management
98 private ITmfTrace fTrace = null;
99 private final Map<ITmfTrace, Integer> fTraceMap = new LinkedHashMap<>();
100
c392540b
FC
101 // Bucket management
102 private final int fNbBuckets;
2fc582d2 103 private final HistogramBucket[] fBuckets;
95aa81ef 104 private final long[] fLostEventsBuckets;
c392540b
FC
105 private long fBucketDuration;
106 private long fNbEvents;
107 private int fLastBucket;
108
109 // Timestamps
fbd124dd 110 private long fFirstBucketTime; // could be negative when analyzing events with descending order!!!
c392540b 111 private long fFirstEventTime;
d418423b 112 private long fEndTime;
0fcf3b09
PT
113 private long fSelectionBegin;
114 private long fSelectionEnd;
c392540b 115 private long fTimeLimit;
bfe038ff 116
e0752744 117 // Private listener lists
fbd124dd 118 private final ListenerList fModelListeners;
bfe038ff 119
e0752744
FC
120 // ------------------------------------------------------------------------
121 // Constructors
122 // ------------------------------------------------------------------------
123
b544077e
BH
124 /**
125 * Default constructor with default number of buckets.
126 */
c392540b 127 public HistogramDataModel() {
00419b1f
FC
128 this(0, DEFAULT_NUMBER_OF_BUCKETS);
129 }
130
131 /**
132 * Default constructor with default number of buckets.
95aa81ef
JCK
133 *
134 * @param startTime
135 * The histogram start time
00419b1f
FC
136 * @since 2.0
137 */
138 public HistogramDataModel(long startTime) {
139 this(startTime, DEFAULT_NUMBER_OF_BUCKETS);
c392540b
FC
140 }
141
b544077e
BH
142 /**
143 * Constructor with non-default number of buckets.
95aa81ef
JCK
144 *
145 * @param nbBuckets
146 * A number of buckets.
b544077e 147 */
c392540b 148 public HistogramDataModel(int nbBuckets) {
00419b1f
FC
149 this(0, nbBuckets);
150 }
151
152 /**
153 * Constructor with non-default number of buckets.
95aa81ef
JCK
154 *
155 * @param startTime
156 * the histogram start time
157 * @param nbBuckets
158 * A number of buckets.
00419b1f
FC
159 * @since 2.0
160 */
161 public HistogramDataModel(long startTime, int nbBuckets) {
d418423b 162 fFirstBucketTime = fFirstEventTime = fEndTime = startTime;
c392540b 163 fNbBuckets = nbBuckets;
2fc582d2 164 fBuckets = new HistogramBucket[nbBuckets];
95aa81ef 165 fLostEventsBuckets = new long[nbBuckets];
fbd124dd 166 fModelListeners = new ListenerList();
c392540b
FC
167 clear();
168 }
169
b544077e
BH
170 /**
171 * Copy constructor.
95aa81ef
JCK
172 *
173 * @param other
174 * A model to copy.
b544077e 175 */
c392540b
FC
176 public HistogramDataModel(HistogramDataModel other) {
177 fNbBuckets = other.fNbBuckets;
2fc582d2
XR
178 fBuckets = new HistogramBucket[fNbBuckets];
179 for (int i = 0; i < fNbBuckets; i++) {
180 fBuckets[i] = new HistogramBucket(other.fBuckets[i]);
181 }
95aa81ef 182 fLostEventsBuckets = Arrays.copyOf(other.fLostEventsBuckets, fNbBuckets);
00419b1f 183 fBucketDuration = Math.max(other.fBucketDuration, 1);
c392540b
FC
184 fNbEvents = other.fNbEvents;
185 fLastBucket = other.fLastBucket;
fbd124dd 186 fFirstBucketTime = other.fFirstBucketTime;
c392540b 187 fFirstEventTime = other.fFirstEventTime;
d418423b 188 fEndTime = other.fEndTime;
0fcf3b09
PT
189 fSelectionBegin = other.fSelectionBegin;
190 fSelectionEnd = other.fSelectionEnd;
c392540b 191 fTimeLimit = other.fTimeLimit;
fbd124dd
BH
192 fModelListeners = new ListenerList();
193 Object[] listeners = other.fModelListeners.getListeners();
194 for (Object listener : listeners) {
195 fModelListeners.add(listener);
196 }
c392540b
FC
197 }
198
c53a7992
BH
199
200 /**
201 * Disposes the data model
202 * @since 3.0
203 */
204 public void dispose() {
205 fTraceMap.clear();
206 fTrace = null;
207 }
208
c392540b
FC
209 // ------------------------------------------------------------------------
210 // Accessors
211 // ------------------------------------------------------------------------
212
b544077e
BH
213 /**
214 * Returns the number of events in the data model.
95aa81ef 215 *
b544077e
BH
216 * @return number of events.
217 */
c392540b
FC
218 public long getNbEvents() {
219 return fNbEvents;
220 }
221
b544077e
BH
222 /**
223 * Returns the number of buckets in the model.
95aa81ef 224 *
b544077e
BH
225 * @return number of buckets.
226 */
c392540b
FC
227 public int getNbBuckets() {
228 return fNbBuckets;
229 }
230
95aa81ef
JCK
231 /**
232 * Returns the current bucket duration.
233 *
234 * @return bucket duration
235 */
c392540b
FC
236 public long getBucketDuration() {
237 return fBucketDuration;
238 }
bfe038ff 239
b544077e
BH
240 /**
241 * Returns the time value of the first bucket in the model.
95aa81ef 242 *
b544077e
BH
243 * @return time of first bucket.
244 */
fbd124dd
BH
245 public long getFirstBucketTime() {
246 return fFirstBucketTime;
247 }
c392540b 248
b544077e
BH
249 /**
250 * Returns the time of the first event in the model.
95aa81ef 251 *
b544077e
BH
252 * @return time of first event.
253 */
c392540b
FC
254 public long getStartTime() {
255 return fFirstEventTime;
256 }
bfe038ff 257
2fc582d2
XR
258 /**
259 * Sets the trace of this model.
260 * @param trace - a {@link ITmfTrace}
261 * @since 3.0
262 */
263 public void setTrace(ITmfTrace trace) {
264 this.fTrace = trace;
265 fTraceMap.clear();
c14c0757
GB
266 int i = 0;
267 for (ITmfTrace tr : TmfTraceManager.getTraceSet(fTrace)) {
268 fTraceMap.put(tr, i);
269 i++;
2fc582d2
XR
270 }
271 }
272
273 /**
274 * Gets the trace of this model.
275 * @return a {@link ITmfTrace}
276 * @since 3.0
277 */
278 public ITmfTrace getTrace() {
279 return this.fTrace;
280 }
281
282 /**
283 * Gets the traces names of this model.
284 * @return an array of trace names
285 * @since 3.0
286 */
287 public String[] getTraceNames() {
c14c0757
GB
288 FluentIterable<ITmfTrace> traces = FluentIterable.from(TmfTraceManager.getTraceSet(fTrace));
289 FluentIterable<String> traceNames = traces.transform(new Function<ITmfTrace, String>() {
290 @Override
291 public String apply(ITmfTrace input) {
292 return input.getName();
293 }
294 });
295 return traceNames.toArray(String.class);
2fc582d2
XR
296 }
297
298 /**
299 * Gets the number of traces of this model.
300 * @return the number of traces of this model.
301 * @since 3.0
302 */
303 public int getNbTraces() {
c14c0757
GB
304 Collection<ITmfTrace> traces = TmfTraceManager.getTraceSet(fTrace);
305 if (traces.isEmpty()) {
2fc582d2
XR
306 return 1; //
307 }
c14c0757 308 return traces.size();
2fc582d2
XR
309 }
310
00419b1f
FC
311 /**
312 * Sets the model start time
95aa81ef
JCK
313 *
314 * @param startTime
315 * the histogram range start time
316 * @param endTime
317 * the histogram range end time
00419b1f
FC
318 * @since 2.0
319 */
320 public void setTimeRange(long startTime, long endTime) {
d418423b 321 fFirstBucketTime = fFirstEventTime = fEndTime = startTime;
00419b1f
FC
322 fBucketDuration = 1;
323 updateEndTime();
324 while (endTime >= fTimeLimit) {
325 mergeBuckets();
326 }
327 }
328
b544077e 329 /**
d418423b
PT
330 * Set the end time. Setting this ensures that the corresponding bucket is
331 * displayed regardless of the event counts.
95aa81ef 332 *
d418423b
PT
333 * @param endTime
334 * the time of the last used bucket
335 * @since 2.2
336 */
337 public void setEndTime(long endTime) {
338 fEndTime = endTime;
339 fLastBucket = (int) ((endTime - fFirstBucketTime) / fBucketDuration);
340 }
341
342 /**
343 * Returns the end time.
344 *
345 * @return the time of the last used bucket
b544077e 346 */
c392540b 347 public long getEndTime() {
d418423b 348 return fEndTime;
c392540b
FC
349 }
350
0fcf3b09
PT
351 /**
352 * Returns the begin time of the current selection in the model.
95aa81ef 353 *
0fcf3b09
PT
354 * @return the begin time of the current selection.
355 * @since 2.1
356 */
357 public long getSelectionBegin() {
358 return fSelectionBegin;
359 }
360
361 /**
362 * Returns the end time of the current selection in the model.
95aa81ef 363 *
0fcf3b09
PT
364 * @return the end time of the current selection.
365 * @since 2.1
366 */
367 public long getSelectionEnd() {
368 return fSelectionEnd;
c392540b
FC
369 }
370
b544077e
BH
371 /**
372 * Returns the time limit with is: start time + nbBuckets * bucketDuration
95aa81ef 373 *
b544077e
BH
374 * @return the time limit.
375 */
c392540b
FC
376 public long getTimeLimit() {
377 return fTimeLimit;
378 }
bfe038ff 379
fbd124dd
BH
380 // ------------------------------------------------------------------------
381 // Listener handling
382 // ------------------------------------------------------------------------
bfe038ff 383
b544077e
BH
384 /**
385 * Add a listener to the model to be informed about model changes.
95aa81ef
JCK
386 *
387 * @param listener
388 * A listener to add.
b544077e 389 */
fbd124dd 390 public void addHistogramListener(IHistogramModelListener listener) {
bfe038ff 391 fModelListeners.add(listener);
fbd124dd 392 }
bfe038ff 393
b544077e
BH
394 /**
395 * Remove a given model listener.
95aa81ef
JCK
396 *
397 * @param listener
398 * A listener to remove.
b544077e 399 */
fbd124dd
BH
400 public void removeHistogramListener(IHistogramModelListener listener) {
401 fModelListeners.remove(listener);
402 }
c392540b 403
f8177ba2 404 // Notify listeners (always)
fbd124dd
BH
405 private void fireModelUpdateNotification() {
406 fireModelUpdateNotification(0);
407 }
bfe038ff 408
b544077e 409 // Notify listener on boundary
fbd124dd 410 private void fireModelUpdateNotification(long count) {
bfe038ff 411 if ((count % REFRESH_FREQUENCY) == 0) {
fbd124dd 412 Object[] listeners = fModelListeners.getListeners();
bfe038ff
MK
413 for (Object listener2 : listeners) {
414 IHistogramModelListener listener = (IHistogramModelListener) listener2;
fbd124dd
BH
415 listener.modelUpdated();
416 }
417 }
418 }
bfe038ff 419
c392540b
FC
420 // ------------------------------------------------------------------------
421 // Operations
422 // ------------------------------------------------------------------------
e0752744 423
fbd124dd
BH
424 @Override
425 public void complete() {
426 fireModelUpdateNotification();
427 }
c392540b
FC
428
429 /**
430 * Clear the histogram model.
95aa81ef 431 *
2bdf0193 432 * @see org.eclipse.tracecompass.tmf.ui.views.distribution.model.IBaseDistributionModel#clear()
c392540b 433 */
fbd124dd 434 @Override
4540412a 435 public synchronized void clear() {
2fc582d2 436 Arrays.fill(fBuckets, null);
95aa81ef 437 Arrays.fill(fLostEventsBuckets, 0);
c392540b 438 fNbEvents = 0;
fbd124dd 439 fFirstBucketTime = 0;
d418423b 440 fEndTime = 0;
0fcf3b09
PT
441 fSelectionBegin = 0;
442 fSelectionEnd = 0;
c392540b 443 fLastBucket = 0;
f8177ba2 444 fBucketDuration = 1;
c392540b 445 updateEndTime();
fbd124dd 446 fireModelUpdateNotification();
c392540b
FC
447 }
448
0fcf3b09
PT
449 /**
450 * Sets the current selection time range (no notification of listeners)
451 *
95aa81ef
JCK
452 * @param beginTime
453 * The selection begin time.
454 * @param endTime
455 * The selection end time.
0fcf3b09
PT
456 * @since 2.1
457 */
458 public void setSelection(long beginTime, long endTime) {
459 fSelectionBegin = beginTime;
460 fSelectionEnd = endTime;
461 }
462
463 /**
464 * Sets the current selection time range with notification of listeners
465 *
95aa81ef
JCK
466 * @param beginTime
467 * The selection begin time.
468 * @param endTime
469 * The selection end time.
0fcf3b09
PT
470 * @since 2.1
471 */
472 public void setSelectionNotifyListeners(long beginTime, long endTime) {
473 fSelectionBegin = beginTime;
474 fSelectionEnd = endTime;
fbd124dd
BH
475 fireModelUpdateNotification();
476 }
bfe038ff 477
c392540b
FC
478 /**
479 * Add event to the correct bucket, compacting the if needed.
bfe038ff 480 *
95aa81ef
JCK
481 * @param eventCount
482 * The current event Count (for notification purposes)
483 * @param timestamp
484 * The timestamp of the event to count
2fc582d2
XR
485 * @param trace
486 * The event trace
487 * @since 3.0
c392540b 488 */
fbd124dd 489 @Override
4540412a 490 public synchronized void countEvent(long eventCount, long timestamp, ITmfTrace trace) {
bfe038ff 491
fbd124dd
BH
492 // Validate
493 if (timestamp < 0) {
fbd124dd
BH
494 return;
495 }
bfe038ff 496
c392540b 497 // Set the start/end time if not already done
2fc582d2 498 if ((fFirstBucketTime == 0) && (fLastBucket == 0) && (fBuckets[0] == null) && (timestamp > 0)) {
fbd124dd 499 fFirstBucketTime = timestamp;
c392540b
FC
500 fFirstEventTime = timestamp;
501 updateEndTime();
502 }
bfe038ff 503
fbd124dd
BH
504 if (timestamp < fFirstEventTime) {
505 fFirstEventTime = timestamp;
506 }
bfe038ff 507
d418423b
PT
508 if (fEndTime < timestamp) {
509 fEndTime = timestamp;
c392540b 510 }
bfe038ff 511
fbd124dd 512 if (timestamp >= fFirstBucketTime) {
c392540b 513
fbd124dd
BH
514 // Compact as needed
515 while (timestamp >= fTimeLimit) {
516 mergeBuckets();
517 }
c392540b 518
fbd124dd 519 } else {
bfe038ff 520
fbd124dd 521 // get offset for adjustment
4540412a 522 long preMergeOffset = getOffset(timestamp);
fbd124dd
BH
523
524 // Compact as needed
4540412a 525 while ((fLastBucket + preMergeOffset) >= fNbBuckets) {
fbd124dd 526 mergeBuckets();
4540412a 527 preMergeOffset = getOffset(timestamp);
fbd124dd 528 }
bfe038ff 529
4540412a
PT
530 // after merging the offset should be less than number of buckets
531 int offset = (int) preMergeOffset;
fbd124dd
BH
532 moveBuckets(offset);
533
534 fLastBucket = fLastBucket + offset;
c392540b 535
95aa81ef 536 fFirstBucketTime = fFirstBucketTime - (offset * fBucketDuration);
fbd124dd
BH
537 updateEndTime();
538 }
bfe038ff 539
c392540b 540 // Increment the right bucket
fbd124dd 541 int index = (int) ((timestamp - fFirstBucketTime) / fBucketDuration);
2fc582d2
XR
542 if (fBuckets[index] == null) {
543 fBuckets[index] = new HistogramBucket(getNbTraces());
544 }
545 Integer traceIndex = fTraceMap.get(trace);
546 if (traceIndex == null) {
547 traceIndex = 0;
548 }
549 fBuckets[index].addEvent(traceIndex);
c392540b 550 fNbEvents++;
bfe038ff 551 if (fLastBucket < index) {
c392540b 552 fLastBucket = index;
bfe038ff
MK
553 }
554
fbd124dd 555 fireModelUpdateNotification(eventCount);
c392540b
FC
556 }
557
95aa81ef
JCK
558 /**
559 * Add lost event to the correct bucket, compacting the if needed.
560 *
561 * @param timeRange
562 * time range of a lost event
563 * @param nbLostEvents
564 * the number of lost events
565 * @param fullRange
566 * Full range or time range for histogram request
46a59db7 567 * @since 2.2
95aa81ef
JCK
568 */
569 public void countLostEvent(TmfTimeRange timeRange, long nbLostEvents, boolean fullRange) {
570
571 // Validate
572 if (timeRange.getStartTime().getValue() < 0 || timeRange.getEndTime().getValue() < 0) {
573 return;
574 }
575
576 // Compact as needed
577 if (fullRange) {
578 while (timeRange.getEndTime().getValue() >= fTimeLimit) {
579 mergeBuckets();
580 }
581 }
582
583 int indexStart = (int) ((timeRange.getStartTime().getValue() - fFirstBucketTime) / fBucketDuration);
584 int indexEnd = (int) ((timeRange.getEndTime().getValue() - fFirstBucketTime) / fBucketDuration);
585 int nbBucketRange = (indexEnd - indexStart) + 1;
586
587 int lostEventPerBucket = (int) Math.ceil((double) nbLostEvents / nbBucketRange);
588 long lastLostCol = Math.max(1, nbLostEvents - lostEventPerBucket * (nbBucketRange - 1));
589
590 // Increment the right bucket, bear in mind that ranges make it almost certain that some lost events are out of range
591 for (int index = indexStart; index <= indexEnd && index < fLostEventsBuckets.length; index++) {
592 if (index == (indexStart + nbBucketRange - 1)) {
593 fLostEventsBuckets[index] += lastLostCol;
594 } else {
595 fLostEventsBuckets[index] += lostEventPerBucket;
596 }
597 }
598
599 fNbEvents++;
600
601 fireModelUpdateNotification(nbLostEvents);
602 }
603
c392540b 604 /**
fbd124dd 605 * Scale the model data to the width, height and bar width requested.
bfe038ff 606 *
95aa81ef
JCK
607 * @param width
608 * A width of the histogram canvas
609 * @param height
610 * A height of the histogram canvas
611 * @param barWidth
612 * A width (in pixel) of a histogram bar
613 * @return the result array of size [width] and where the highest value
614 * doesn't exceed [height]
f8177ba2 615 *
2bdf0193 616 * @see org.eclipse.tracecompass.tmf.ui.views.histogram.IHistogramDataModel#scaleTo(int,
95aa81ef 617 * int, int)
c392540b 618 */
fbd124dd
BH
619 @Override
620 public HistogramScaledData scaleTo(int width, int height, int barWidth) {
c392540b 621 // Basic validation
95aa81ef
JCK
622 if ((width <= 0) || (height <= 0) || (barWidth <= 0))
623 {
fbd124dd 624 throw new AssertionError("Invalid histogram dimensions (" + width + "x" + height + ", barWidth=" + barWidth + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
bfe038ff 625 }
c392540b
FC
626
627 // The result structure
fbd124dd 628 HistogramScaledData result = new HistogramScaledData(width, height, barWidth);
c392540b
FC
629
630 // Scale horizontally
74237cc3 631 result.fMaxValue = 0;
bfe038ff 632
fbd124dd 633 int nbBars = width / barWidth;
bfe038ff 634 int bucketsPerBar = (fLastBucket / nbBars) + 1;
95aa81ef 635 result.fBucketDuration = Math.max(bucketsPerBar * fBucketDuration, 1);
fbd124dd 636 for (int i = 0; i < nbBars; i++) {
c392540b 637 int count = 0;
95aa81ef 638 int countLostEvent = 0;
2fc582d2 639 result.fData[i] = new HistogramBucket(getNbTraces());
bfe038ff
MK
640 for (int j = i * bucketsPerBar; j < ((i + 1) * bucketsPerBar); j++) {
641 if (fNbBuckets <= j) {
c392540b 642 break;
bfe038ff 643 }
2fc582d2
XR
644 if (fBuckets[j] != null) {
645 count += fBuckets[j].getNbEvents();
646 result.fData[i].add(fBuckets[j]);
647 }
95aa81ef 648 countLostEvent += fLostEventsBuckets[j];
c392540b 649 }
95aa81ef 650 result.fLostEventsData[i] = countLostEvent;
c392540b 651 result.fLastBucket = i;
bfe038ff 652 if (result.fMaxValue < count) {
c392540b 653 result.fMaxValue = count;
bfe038ff 654 }
95aa81ef
JCK
655 if (result.fMaxCombinedValue < count + countLostEvent) {
656 result.fMaxCombinedValue = count + countLostEvent;
657 }
c392540b
FC
658 }
659
660 // Scale vertically
661 if (result.fMaxValue > 0) {
662 result.fScalingFactor = (double) height / result.fMaxValue;
663 }
95aa81ef
JCK
664 if (result.fMaxCombinedValue > 0) {
665 result.fScalingFactorCombined = (double) height / result.fMaxCombinedValue;
666 }
c392540b 667
bfe038ff 668 fBucketDuration = Math.max(fBucketDuration, 1);
0fcf3b09 669 // Set selection begin and end index in the scaled histogram
cc817e65
PT
670 result.fSelectionBeginBucket = (int) ((fSelectionBegin - fFirstBucketTime) / fBucketDuration) / bucketsPerBar;
671 result.fSelectionEndBucket = (int) ((fSelectionEnd - fFirstBucketTime) / fBucketDuration) / bucketsPerBar;
c392540b 672
fbd124dd
BH
673 result.fFirstBucketTime = fFirstBucketTime;
674 result.fFirstEventTime = fFirstEventTime;
c392540b
FC
675 return result;
676 }
677
678 // ------------------------------------------------------------------------
679 // Helper functions
680 // ------------------------------------------------------------------------
681
682 private void updateEndTime() {
bfe038ff 683 fTimeLimit = fFirstBucketTime + (fNbBuckets * fBucketDuration);
c392540b
FC
684 }
685
686 private void mergeBuckets() {
bfe038ff 687 for (int i = 0; i < (fNbBuckets / 2); i++) {
2fc582d2 688 fBuckets[i] = new HistogramBucket(fBuckets[2 * i], fBuckets[(2 * i) + 1]);
95aa81ef 689 fLostEventsBuckets[i] = fLostEventsBuckets[2 * i] + fLostEventsBuckets[(2 * i) + 1];
c392540b 690 }
2fc582d2 691 Arrays.fill(fBuckets, fNbBuckets / 2, fNbBuckets, null);
95aa81ef 692 Arrays.fill(fLostEventsBuckets, fNbBuckets / 2, fNbBuckets, 0);
c392540b
FC
693 fBucketDuration *= 2;
694 updateEndTime();
bfe038ff 695 fLastBucket = (fNbBuckets / 2) - 1;
c392540b 696 }
bfe038ff 697
fbd124dd 698 private void moveBuckets(int offset) {
95aa81ef 699 for (int i = fNbBuckets - 1; i >= offset; i--) {
2fc582d2 700 fBuckets[i] = new HistogramBucket(fBuckets[i - offset]);
95aa81ef 701 fLostEventsBuckets[i] = fLostEventsBuckets[i - offset];
fbd124dd
BH
702 }
703
704 for (int i = 0; i < offset; i++) {
2fc582d2 705 fBuckets[i] = null;
95aa81ef 706 fLostEventsBuckets[i] = 0;
fbd124dd
BH
707 }
708 }
709
4540412a
PT
710 private long getOffset(long timestamp) {
711 long offset = (fFirstBucketTime - timestamp) / fBucketDuration;
bfe038ff 712 if (((fFirstBucketTime - timestamp) % fBucketDuration) != 0) {
fbd124dd
BH
713 offset++;
714 }
715 return offset;
716 }
c392540b 717}
This page took 0.109782 seconds and 5 git commands to generate.