This is an automated email from the ASF dual-hosted git repository.

rong pushed a commit to branch rc/1.3.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/rc/1.3.3 by this push:
     new 0f63b4674e5 Fix TimePartitionUtils Overflow (#13881) (#13885)
0f63b4674e5 is described below

commit 0f63b4674e5261749fa861a9a5b1fd2e6a48eb52
Author: shuwenwei <[email protected]>
AuthorDate: Wed Oct 23 19:51:30 2024 +0800

    Fix TimePartitionUtils Overflow (#13881) (#13885)
---
 .../iotdb/commons/utils/TimePartitionUtils.java    | 104 +++++++++++++++++++--
 .../commons/utils/TimePartitionUtilsTest.java      |  16 ++++
 2 files changed, 110 insertions(+), 10 deletions(-)

diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
index 4fd6d8d9ff1..7b331fddaac 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
@@ -23,6 +23,8 @@ import org.apache.iotdb.commons.conf.CommonDescriptor;
 
 import org.apache.tsfile.read.filter.basic.Filter;
 
+import java.math.BigInteger;
+
 public class TimePartitionUtils {
 
   /**
@@ -36,6 +38,39 @@ public class TimePartitionUtils {
   private static long timePartitionInterval =
       CommonDescriptor.getInstance().getConfig().getTimePartitionInterval();
 
+  private static final BigInteger bigTimePartitionOrigin = 
BigInteger.valueOf(timePartitionOrigin);
+  private static final BigInteger bigTimePartitionInterval =
+      BigInteger.valueOf(timePartitionInterval);
+  private static final boolean originMayCauseOverflow = (timePartitionOrigin 
!= 0);
+  private static final long timePartitionLowerBoundWithoutOverflow;
+  private static final long timePartitionUpperBoundWithoutOverflow;
+
+  static {
+    long minPartition = getTimePartitionIdWithoutOverflow(Long.MIN_VALUE);
+    long maxPartition = getTimePartitionIdWithoutOverflow(Long.MAX_VALUE);
+    BigInteger minPartitionStartTime =
+        BigInteger.valueOf(minPartition)
+            .multiply(bigTimePartitionInterval)
+            .add(bigTimePartitionOrigin);
+    BigInteger maxPartitionEndTime =
+        BigInteger.valueOf(maxPartition)
+            .multiply(bigTimePartitionInterval)
+            .add(bigTimePartitionInterval)
+            .add(bigTimePartitionOrigin);
+    if (minPartitionStartTime.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 
0) {
+      timePartitionLowerBoundWithoutOverflow =
+          minPartitionStartTime.add(bigTimePartitionInterval).longValue();
+    } else {
+      timePartitionLowerBoundWithoutOverflow = 
minPartitionStartTime.longValue();
+    }
+    if (maxPartitionEndTime.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) 
{
+      timePartitionUpperBoundWithoutOverflow =
+          maxPartitionEndTime.subtract(bigTimePartitionInterval).longValue();
+    } else {
+      timePartitionUpperBoundWithoutOverflow = maxPartitionEndTime.longValue();
+    }
+  }
+
   public static TTimePartitionSlot getTimePartitionSlot(long time) {
     TTimePartitionSlot timePartitionSlot = new TTimePartitionSlot();
     timePartitionSlot.setStartTime(getTimePartitionLowerBound(time));
@@ -47,14 +82,27 @@ public class TimePartitionUtils {
   }
 
   public static long getTimePartitionLowerBound(long time) {
-    long lowerBoundOfTimePartition;
-    lowerBoundOfTimePartition =
-        getTimePartitionId(time) * timePartitionInterval + timePartitionOrigin;
-    return lowerBoundOfTimePartition;
+    if (time < timePartitionLowerBoundWithoutOverflow) {
+      return Long.MIN_VALUE;
+    }
+    if (originMayCauseOverflow) {
+      return BigInteger.valueOf(getTimePartitionIdWithoutOverflow(time))
+          .multiply(bigTimePartitionInterval)
+          .add(bigTimePartitionOrigin)
+          .longValue();
+    } else {
+      return getTimePartitionId(time) * timePartitionInterval + 
timePartitionOrigin;
+    }
   }
 
   public static long getTimePartitionUpperBound(long time) {
-    return getTimePartitionLowerBound(time) + timePartitionInterval;
+    if (time >= timePartitionUpperBoundWithoutOverflow) {
+      return Long.MAX_VALUE;
+    }
+    long lowerBound = getTimePartitionLowerBound(time);
+    return lowerBound == Long.MIN_VALUE
+        ? timePartitionLowerBoundWithoutOverflow
+        : lowerBound + timePartitionInterval;
   }
 
   public static long getTimePartitionId(long time) {
@@ -64,19 +112,48 @@ public class TimePartitionUtils {
         : time / timePartitionInterval - 1;
   }
 
+  public static long getTimePartitionIdWithoutOverflow(long time) {
+    BigInteger bigTime = 
BigInteger.valueOf(time).subtract(bigTimePartitionOrigin);
+    BigInteger partitionId =
+        bigTime.compareTo(BigInteger.ZERO) > 0
+                || 
bigTime.remainder(bigTimePartitionInterval).equals(BigInteger.ZERO)
+            ? bigTime.divide(bigTimePartitionInterval)
+            : 
bigTime.divide(bigTimePartitionInterval).subtract(BigInteger.ONE);
+    return partitionId.longValue();
+  }
+
   public static boolean satisfyPartitionId(long startTime, long endTime, long 
partitionId) {
-    return getTimePartitionId(startTime) <= partitionId
-        && getTimePartitionId(endTime) >= partitionId;
+    long startPartition =
+        originMayCauseOverflow
+            ? getTimePartitionIdWithoutOverflow(startTime)
+            : getTimePartitionId(startTime);
+    long endPartition =
+        originMayCauseOverflow
+            ? getTimePartitionIdWithoutOverflow(endTime)
+            : getTimePartitionId(endTime);
+    return startPartition <= partitionId && endPartition >= partitionId;
   }
 
   public static boolean satisfyPartitionStartTime(Filter timeFilter, long 
partitionStartTime) {
+    long partitionEndTime =
+        partitionStartTime >= timePartitionLowerBoundWithoutOverflow
+            ? Long.MAX_VALUE
+            : (partitionStartTime + timePartitionInterval - 1);
     return timeFilter == null
-        || timeFilter.satisfyStartEndTime(
-            partitionStartTime, partitionStartTime + timePartitionInterval - 
1);
+        || timeFilter.satisfyStartEndTime(partitionStartTime, 
partitionEndTime);
   }
 
   public static boolean satisfyTimePartition(Filter timeFilter, long 
partitionId) {
-    long partitionStartTime = partitionId * timePartitionInterval + 
timePartitionOrigin;
+    long partitionStartTime;
+    if (originMayCauseOverflow) {
+      partitionStartTime =
+          BigInteger.valueOf(partitionId)
+              .multiply(bigTimePartitionInterval)
+              .add(bigTimePartitionOrigin)
+              .longValue();
+    } else {
+      partitionStartTime = partitionId * timePartitionInterval + 
timePartitionOrigin;
+    }
     return satisfyPartitionStartTime(timeFilter, partitionStartTime);
   }
 
@@ -85,6 +162,13 @@ public class TimePartitionUtils {
   }
 
   public static long getEstimateTimePartitionSize(long startTime, long 
endTime) {
+    if (endTime > 0 && startTime < 0) {
+      return BigInteger.valueOf(endTime)
+              .subtract(BigInteger.valueOf(startTime))
+              .divide(bigTimePartitionInterval)
+              .longValue()
+          + 1;
+    }
     return (endTime - startTime) / timePartitionInterval + 1;
   }
 }
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
index 372c2068186..ea0eeda45d2 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.commons.utils;
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -89,4 +90,19 @@ public class TimePartitionUtilsTest {
     TTimePartitionSlot actualSlot = 
TimePartitionUtils.getTimePartitionSlot(testTime);
     assertEquals(expectedSlot.getStartTime(), actualSlot.getStartTime());
   }
+
+  @Test
+  public void testOverflow() {
+    long testTime = Long.MIN_VALUE;
+    TTimePartitionSlot actualSlot = 
TimePartitionUtils.getTimePartitionSlot(testTime);
+    Assert.assertTrue(actualSlot.getStartTime() < 0);
+    testTime += 1;
+    long lowerBound = TimePartitionUtils.getTimePartitionLowerBound(testTime);
+    assertEquals(Long.MIN_VALUE, lowerBound);
+    testTime = Long.MAX_VALUE;
+    actualSlot = TimePartitionUtils.getTimePartitionSlot(testTime);
+    Assert.assertTrue(actualSlot.getStartTime() > 0);
+    long upperBound = TimePartitionUtils.getTimePartitionUpperBound(testTime);
+    assertEquals(Long.MAX_VALUE, upperBound);
+  }
 }

Reply via email to