tmf.ui: Fix histogram deadlock when max time is Long.MAX_VALUE

If the maximum time of the trace is Long.MAX_VALUE, there was an
infinite loop since the limit never gets higher than the timestamp.

Change-Id: I2abafb63a1865613fa0118fedbcb1c106273f67b
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/160275
Tested-by: Trace Compass Bot <tracecompass-bot@eclipse.org>
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/histogram/HistogramDataModelTest.java b/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/histogram/HistogramDataModelTest.java
index 18e705c..64cc443 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/histogram/HistogramDataModelTest.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/histogram/HistogramDataModelTest.java
@@ -251,6 +251,30 @@
     }
 
     /**
+     * Test counting events when the timestamp limit would overflow because of
+     * large trace time range
+     */
+    @Test
+    public void testCountEventLimitOverflow() {
+        final int nbBuckets = 2;
+        final long beginTime = 4294967296000L;
+        final long endTime = Long.MAX_VALUE - 1;
+        final int maxHeight = 10;
+        // Bucket duration is a power of 2 and must include both begin and end time
+        long bucketDuration = (long) Math.pow(2, (int) (Math.log((endTime - beginTime) / nbBuckets) / Math.log(2)) + 1);
+
+        HistogramDataModel model = new HistogramDataModel(nbBuckets);
+        model.countEvent(0, beginTime, null);
+        model.countEvent(1, endTime, null);
+
+        HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1);
+
+        assertArrayEqualsInt(1, result.fData);
+
+        testModelConsistency(model, nbBuckets, nbBuckets, bucketDuration, beginTime, beginTime, endTime, Long.MAX_VALUE);
+    }
+
+    /**
      * Test method for {@link HistogramDataModel#scaleTo(int,int,int)}.
      */
     @Test
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramDataModel.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramDataModel.java
index 9ac87f1..96af19a 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramDataModel.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramDataModel.java
@@ -308,10 +308,10 @@
      *            the histogram range end time
      */
     public void setTimeRange(long startTime, long endTime) {
-        fFirstBucketTime = fFirstEventTime = fEndTime = startTime;
+        fFirstBucketTime = fFirstEventTime = fEndTime = fTimeLimit = startTime;
         fBucketDuration = 1;
         updateEndTime();
-        while (endTime >= fTimeLimit) {
+        while (endTime >= fTimeLimit && fTimeLimit < Long.MAX_VALUE) {
             mergeBuckets();
         }
     }
@@ -497,7 +497,7 @@
         if (timestamp >= fFirstBucketTime) {
 
             // Compact as needed
-            while (timestamp >= fTimeLimit) {
+            while (timestamp >= fTimeLimit && fTimeLimit < Long.MAX_VALUE) {
                 mergeBuckets();
             }
 
@@ -570,7 +570,7 @@
         // Compact as needed
         if (fullRange) {
             fEndTime = Math.max(fEndTime, endTime);
-            while (endTime >= fTimeLimit) {
+            while (endTime >= fTimeLimit && fTimeLimit < Long.MAX_VALUE) {
                 mergeBuckets();
             }
         }
@@ -715,7 +715,9 @@
     // ------------------------------------------------------------------------
 
     private void updateEndTime() {
-        fTimeLimit = fFirstBucketTime + (fNbBuckets * fBucketDuration);
+        long newLimit = fFirstBucketTime + (fNbBuckets * fBucketDuration);
+        // Make sure there is no overflow
+        fTimeLimit = fFirstBucketTime <= newLimit ? newLimit : Long.MAX_VALUE;
     }
 
     private void mergeBuckets() {