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

leirui pushed a commit to branch research/LTS-visualization
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 99576c5372c8fc2321faefab75bff7b6ecc36959
Author: Lei Rui <[email protected]>
AuthorDate: Sun Jan 28 02:07:37 2024 +0800

    minmaxLTTB
---
 .../dataset/groupby/GroupByEngineDataSet.java      |   6 +-
 .../groupby/GroupByWithoutValueFilterDataSet.java  | 217 +++++++++++++++++----
 .../groupby/LocalGroupByExecutorTri_MinMax.java    |   6 +-
 .../iotdb/db/integration/tri/MyTest_MinMax.java    |  10 +-
 .../{MyTest_MinMax.java => MyTest_MinMaxLTTB.java} | 107 ++++++++--
 .../iotdb/tsfile/read/common/IOMonitor2.java       |   5 +
 6 files changed, 294 insertions(+), 57 deletions(-)

diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java
 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java
index 7194633765d..8feafc55602 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByEngineDataSet.java
@@ -129,7 +129,11 @@ public abstract class GroupByEngineDataSet extends 
QueryDataSet {
         curStartTime += curSlidingStep;
       }
       // This is an open interval , [0-100)
-      if (curStartTime >= endTime) {
+      if (curStartTime + interval >= endTime) {
+        // + interval to make the last bucket complete
+        // e.g, T=11,nout=3,interval=floor(11/3)=3,
+        // [0,3),[3,6),[6,9), no need incomplete [9,11)
+        // then the number of buckets must be 
Math.floor((endTime-startTime)/interval)
         return false;
       }
     } else {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java
 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java
index 9472f1f62fa..71538e8c3dd 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithoutValueFilterDataSet.java
@@ -33,6 +33,7 @@ import 
org.apache.iotdb.db.query.factory.AggregateResultFactory;
 import org.apache.iotdb.db.query.filter.TsFileFilter;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.statistics.MinMaxInfo;
 import org.apache.iotdb.tsfile.read.common.IOMonitor2;
 import org.apache.iotdb.tsfile.read.common.IOMonitor2.DataSetType;
 import org.apache.iotdb.tsfile.read.common.Path;
@@ -132,37 +133,13 @@ public class GroupByWithoutValueFilterDataSet extends 
GroupByEngineDataSet {
     }
   }
 
-  /** Each row correspond to result of a bucket */
-  public List<List<AggregateResult>> getAll() throws IOException, 
QueryProcessException {
-    List<List<AggregateResult>> resultsAllBuckets = new ArrayList<>();
-    GroupByExecutor executor = null;
-    for (Entry<PartialPath, GroupByExecutor> pathToExecutorEntry : 
pathExecutors.entrySet()) {
-      executor = pathToExecutorEntry.getValue(); // assume only one series here
-      break;
-    }
-    for (long localCurStartTime = startTime;
-        localCurStartTime < endTime;
-        localCurStartTime += interval) { // not change real 
curStartTime&curEndTime
-      List<AggregateResult> aggregations =
-          executor.calcResult(
-              localCurStartTime, localCurStartTime + interval, startTime, 
endTime, interval);
-      resultsAllBuckets.add(aggregations); // needs deep copy!!
-    }
-
-    // make the next hasNextWithoutConstraint() false
-    curStartTime = endTime;
-    hasCachedTimeInterval = false;
-
-    return resultsAllBuckets;
-  }
-
   @Override
   public RowRecord nextWithoutConstraint() throws IOException {
     if (CONFIG.getEnableTri().equals("MinMax")) {
       return nextWithoutConstraintTri_MinMax();
+    } else if (CONFIG.getEnableTri().equals("MinMaxLTTB")) {
+      return nextWithoutConstraintTri_MinMaxLTTB();
     }
-    //    } else if (CONFIG.getEnableTri().equals("MinMaxLTTB")) {
-    //      // TODO
     //    } else if (CONFIG.getEnableTri().equals("M4LTTB")) {
     //      // TODO
     //    } else if (CONFIG.getEnableTri().equals("LTTB")) {
@@ -175,6 +152,182 @@ public class GroupByWithoutValueFilterDataSet extends 
GroupByEngineDataSet {
     }
   }
 
+  public RowRecord nextWithoutConstraintTri_MinMaxLTTB() throws IOException {
+    RowRecord record;
+
+    // TODO tmp p1,pn,rps later passed by config
+    long p1t = 0;
+    double p1v = -1.2079272;
+    long pnt = 2100;
+    double pnv = -0.0211206;
+    int rps = 4;
+    int divide = 2; // one LTTB bucket corresponds to rps/2 MinMax buckets
+
+    // concat results into a string
+    record = new RowRecord(0);
+    StringBuilder series = new StringBuilder();
+
+    try {
+      // First step: get the MinMax preselection result
+      List<Long> times = new ArrayList<>();
+      List<Object> values = new ArrayList<>();
+      GroupByExecutor executor = null;
+      for (Entry<PartialPath, GroupByExecutor> pathToExecutorEntry : 
pathExecutors.entrySet()) {
+        executor = pathToExecutorEntry.getValue(); // assume only one series 
here
+        break;
+      }
+      for (long localCurStartTime = startTime;
+          localCurStartTime + interval <= endTime;
+          // 注意有等号!
+          // + interval to make the last bucket complete
+          // e.g, T=11,nout=3,interval=floor(11/3)=3,
+          // [0,3),[3,6),[6,9), no need incomplete [9,11)
+          // then the number of buckets must be 
Math.floor((endTime-startTime)/interval)
+          localCurStartTime += interval) {
+        System.out.println(localCurStartTime);
+        // not change real curStartTime&curEndTime
+        // attention the returned aggregations need deep copy if using directly
+        List<AggregateResult> aggregations =
+            executor.calcResult(
+                localCurStartTime, localCurStartTime + interval, startTime, 
endTime, interval);
+        for (AggregateResult aggregation : aggregations) {
+          // Each row correspond to (bucketLeftBound, minV[bottomT], 
maxV[topT]) of a MinMax bucket
+          MinMaxInfo minMaxInfo = (MinMaxInfo) aggregation.getResult();
+          if (minMaxInfo == null) {
+            times.add(null);
+            values.add(null);
+          } else {
+            times.add(minMaxInfo.timestamp);
+            values.add(minMaxInfo.val);
+          }
+        }
+      }
+
+      // Second step: apply LTTB on the MinMax preselection result
+      System.out.println(times);
+      System.out.println(values);
+      int N1 = (int) Math.floor((endTime * 1.0 - startTime) / interval); // 
MinMax桶数
+      int N2 = N1 / (rps / divide); // LTTB桶数
+      // 全局首点
+      series.append(p1v).append("[").append(p1t).append("]").append(",");
+      long lt = p1t; // left fixed t
+      double lv = p1v; // left fixed v
+      // 找第一个不为空的LTTB当前桶
+      int currentBucket = 0;
+      for (; currentBucket < N2; currentBucket++) {
+        boolean emptyBucket = true;
+        for (int j = currentBucket * rps; j < (currentBucket + 1) * rps; j++) {
+          // 一个LTTB桶里有rps个MinMax预选点(包含重复和null)
+          if (times.get(j) != null) {
+            emptyBucket = false; // 只要有一个MinMax预选点不是null,这个LTTB桶就不是空桶
+            break;
+          }
+        }
+        if (!emptyBucket) {
+          break;
+        }
+      }
+      // 现在找到了不为空的LTTB当前桶,下面找第一个不为空的LTTB右边桶
+      for (int nextBucket = currentBucket + 1; nextBucket < N2; nextBucket++) {
+        boolean emptyBucket = true;
+        for (int j = nextBucket * rps; j < (nextBucket + 1) * rps; j++) {
+          // 一个LTTB桶里有rps个MinMax预选点(包含重复和null)
+          if (times.get(j) != null) {
+            emptyBucket = false; // 只要有一个MinMax预选点不是null,这个LTTB桶就不是空桶
+            break;
+          }
+        }
+        if (emptyBucket) {
+          continue; // 继续往右边找非空桶
+        }
+
+        // 现在计算右边非空LTTB桶的平均点
+        double rt = 0;
+        double rv = 0;
+        int cnt = 0;
+        for (int j = nextBucket * rps; j < (nextBucket + 1) * rps; j++) {
+          // 一个LTTB桶里有rps个MinMax预选点(包含重复和null)
+          if (times.get(j) != null) {
+            rt += times.get(j);
+            rv += (double) values.get(j); // TODO
+            cnt++;
+          }
+        }
+        rt = rt / cnt;
+        rv = rv / cnt;
+
+        // 现在找到当前非空桶里距离lr垂直距离最远的点
+        double maxArea = -1;
+        long select_t = -1;
+        double select_v = -1;
+        for (int j = currentBucket * rps; j < (currentBucket + 1) * rps; j++) {
+          // 一个LTTB桶里有rps个MinMax预选点(包含重复和null)
+          if (times.get(j) != null) {
+            long t = times.get(j);
+            double v = (double) values.get(j); // TODO
+            double area = IOMonitor2.calculateTri(lt, lv, t, v, rt, rv);
+            System.out.printf("curr=%d,t=%d,area=%f,lt=%d%n", currentBucket, 
t, area, lt);
+            if (area > maxArea) {
+              maxArea = area;
+              select_t = t;
+              select_v = v;
+            }
+          }
+        }
+        if (select_t < 0) {
+          throw new IOException("something is wrong");
+        }
+        
series.append(select_v).append("[").append(select_t).append("]").append(",");
+
+        // 现在更新当前桶和左边固定点,并且把结果点加到series里
+        currentBucket = nextBucket;
+        lt = select_t;
+        lv = select_v;
+      }
+
+      // 下面处理最后一个桶
+      // 现在找到当前非空桶里距离lr垂直距离最远的点
+      double maxArea = -1;
+      long select_t = -1;
+      double select_v = -1;
+      for (int j = currentBucket * rps; j < (currentBucket + 1) * rps; j++) {
+        // 一个LTTB桶里有rps个MinMax预选点(包含重复和null)
+        if (times.get(j) != null) {
+          long t = times.get(j);
+          double v = (double) values.get(j); // TODO
+          double area = IOMonitor2.calculateTri(lt, lv, t, v, pnt, pnv); // 
全局尾点作为右边固定点
+          System.out.printf("curr=%d,t=%d,area=%f,lt=%d%n", currentBucket, t, 
area, lt);
+          if (area > maxArea) {
+            maxArea = area;
+            select_t = t;
+            select_v = v;
+          }
+        }
+      }
+      if (select_t < 0) {
+        throw new IOException("something is wrong");
+      }
+      
series.append(select_v).append("[").append(select_t).append("]").append(",");
+
+      // 全局尾点
+      series.append(pnv).append("[").append(pnt).append("]").append(",");
+
+      // MIN_MAX_INT64 this type for field.setBinaryV(new 
Binary(value.toString()))
+      record.addField(series, TSDataType.MIN_MAX_INT64);
+
+    } catch (QueryProcessException e) {
+      logger.error("GroupByWithoutValueFilterDataSet execute has error", e);
+      throw new IOException(e.getMessage(), e);
+    }
+
+    // in the end, make the next hasNextWithoutConstraint() false
+    // as we already fetch all here
+    curStartTime = endTime;
+    hasCachedTimeInterval = false;
+
+    return record;
+  }
+
   public RowRecord nextWithoutConstraintTri_MinMax() throws IOException {
     RowRecord record;
     try {
@@ -189,7 +342,10 @@ public class GroupByWithoutValueFilterDataSet extends 
GroupByEngineDataSet {
       StringBuilder series = new StringBuilder();
 
       for (long localCurStartTime = startTime;
-          localCurStartTime < endTime;
+          localCurStartTime + interval < endTime; // + interval to make the 
last bucket complete
+          // e.g, T=11,nout=3,interval=floor(11/3)=3,
+          // [0,3),[3,6),[6,9), no need incomplete [9,11)
+          // then the number of buckets must be 
Math.floor((endTime-startTime)/interval)
           localCurStartTime += interval) { // not change real 
curStartTime&curEndTime
         // attention the returned aggregations need deep copy if using directly
         List<AggregateResult> aggregations =
@@ -289,14 +445,9 @@ public class GroupByWithoutValueFilterDataSet extends 
GroupByEngineDataSet {
       TsFileFilter fileFilter,
       boolean ascending)
       throws StorageEngineException, QueryProcessException {
-    if (CONFIG.getEnableTri().equals("MinMax")) {
-      // TODO
+    if (CONFIG.getEnableTri().equals("MinMax") || 
CONFIG.getEnableTri().equals("MinMaxLTTB")) {
       return new LocalGroupByExecutorTri_MinMax(
           path, allSensors, dataType, context, timeFilter, fileFilter, 
ascending);
-    } else if (CONFIG.getEnableTri().equals("MinMaxLTTB")) {
-      // TODO
-      return new LocalGroupByExecutor(
-          path, allSensors, dataType, context, timeFilter, fileFilter, 
ascending);
     } else if (CONFIG.getEnableTri().equals("M4LTTB")) {
       // TODO
       return new LocalGroupByExecutor(
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_MinMax.java
 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_MinMax.java
index ed4ced412ef..ec91aa29671 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_MinMax.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_MinMax.java
@@ -333,9 +333,9 @@ public class LocalGroupByExecutorTri_MinMax implements 
GroupByExecutor {
             TSDataType dataType = chunkSuit4Tri.chunkMetadata.getDataType();
             Object v;
             switch (dataType) {
-              case INT64:
-                v = valueBuffer.getLong(pageReader.timeBufferLength + i * 8);
-                break;
+                //              case INT64:
+                //                v = 
valueBuffer.getLong(pageReader.timeBufferLength + i * 8);
+                //                break;
               case DOUBLE:
                 v = valueBuffer.getDouble(pageReader.timeBufferLength + i * 8);
                 break;
diff --git 
a/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMax.java 
b/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMax.java
index 8364c497ada..abb46b1b54d 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMax.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMax.java
@@ -48,14 +48,14 @@ public class MyTest_MinMax {
    * (1) Don't change the sequence of the above two aggregates
    * (2) Assume each chunk has only one page.
    * (3) Assume all chunks are sequential and no deletes.
-   * (4) Assume plain encoding, UNCOMPRESSED, Long or Double data type, no 
compaction
+   * (4) Assume plain encoding, UNCOMPRESSED, Double data type, no compaction
    */
   private static final String TIMESTAMP_STR = "Time";
 
   private static String[] creationSqls =
       new String[] {
         "SET STORAGE GROUP TO root.vehicle.d0",
-        "CREATE TIMESERIES root.vehicle.d0.s0 WITH DATATYPE=INT64, 
ENCODING=PLAIN",
+        "CREATE TIMESERIES root.vehicle.d0.s0 WITH DATATYPE=DOUBLE, 
ENCODING=PLAIN",
         // IoTDB int data type does not support plain encoding, so use long 
data type
       };
 
@@ -100,7 +100,7 @@ public class MyTest_MinMax {
     prepareData1();
     //    String[] res = new String[]{"0,1[20],15[2]", "25,8[25],8[25]", 
"50,3[54],3[54]",
     // "75,null,null"};
-    String res = "0,1[20],15[2],8[25],8[25],3[54],3[54],null,null,";
+    String res = 
"0,1.0[20],15.0[2],8.0[25],8.0[25],3.0[54],3.0[54],null,null,";
     // 0,BPv[t]ofBucket1,TPv[t]ofBucket1,BPv[t]ofBucket2,TPv[t]ofBucket2,...
     try (Connection connection =
             DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", 
"root", "root");
@@ -159,7 +159,7 @@ public class MyTest_MinMax {
 
     //    String[] res = new String[]{"0,1[10],10[2]", "25,2[40],8[30]", 
"50,4[72],20[62]",
     // "75,1[90],11[80]"};
-    String res = "0,1[10],10[2],2[40],8[30],4[72],20[62],1[90],11[80],";
+    String res = 
"0,1.0[10],10.0[2],2.0[40],8.0[30],4.0[72],20.0[62],1.0[90],11.0[80],";
     // 0,BPv[t]ofBucket1,TPv[t]ofBucket1,BPv[t]ofBucket2,TPv[t]ofBucket2,...
     try (Connection connection =
             DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", 
"root", "root");
@@ -231,7 +231,7 @@ public class MyTest_MinMax {
 
     //    String[] res = new String[]{"0,1[10],10[2]", "25,null,null", 
"50,4[72],20[62]",
     // "75,1[90],11[80]"};
-    String res = "0,1[10],10[2],null,null,4[72],20[62],1[90],11[80],";
+    String res = 
"0,1.0[10],10.0[2],null,null,4.0[72],20.0[62],1.0[90],11.0[80],";
     // 0,BPv[t]ofBucket1,TPv[t]ofBucket1,BPv[t]ofBucket2,TPv[t]ofBucket2,...
     try (Connection connection =
             DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", 
"root", "root");
diff --git 
a/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMax.java 
b/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMaxLTTB.java
similarity index 80%
copy from 
server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMax.java
copy to 
server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMaxLTTB.java
index 8364c497ada..e80a6c3f8cf 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMax.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_MinMaxLTTB.java
@@ -40,7 +40,7 @@ import java.util.Locale;
 
 import static org.junit.Assert.fail;
 
-public class MyTest_MinMax {
+public class MyTest_MinMaxLTTB {
 
   /*
    * Sql format: SELECT min_value(s0), max_value(s0) ROM root.xx group by 
([tqs,tqe),IntervalLength).
@@ -55,25 +55,24 @@ public class MyTest_MinMax {
   private static String[] creationSqls =
       new String[] {
         "SET STORAGE GROUP TO root.vehicle.d0",
-        "CREATE TIMESERIES root.vehicle.d0.s0 WITH DATATYPE=INT64, 
ENCODING=PLAIN",
+        "CREATE TIMESERIES root.vehicle.d0.s0 WITH DATATYPE=DOUBLE, 
ENCODING=PLAIN",
         // IoTDB int data type does not support plain encoding, so use long 
data type
       };
 
   private final String d0s0 = "root.vehicle.d0.s0";
 
   private static final String insertTemplate =
-      "INSERT INTO root.vehicle.d0(timestamp,s0)" + " VALUES(%d,%d)";
+      "INSERT INTO root.vehicle.d0(timestamp,s0)" + " VALUES(%d,%f)";
 
   private static final IoTDBConfig config = 
IoTDBDescriptor.getInstance().getConfig();
 
   @Before
   public void setUp() throws Exception {
     TSFileDescriptor.getInstance().getConfig().setTimeEncoder("PLAIN");
-    //    originalCompactionStrategy = config.getCompactionStrategy();
     config.setTimestampPrecision("ms");
     config.setCompactionStrategy(CompactionStrategy.NO_COMPACTION);
 
-    config.setEnableTri("MinMax");
+    config.setEnableTri("MinMaxLTTB");
 
     // 但是如果走的是unpackOneChunkMetaData(firstChunkMetadata)就没问题,
     // 因为它直接用chunk元数据去构造pageReader,
@@ -92,16 +91,12 @@ public class MyTest_MinMax {
   @After
   public void tearDown() throws Exception {
     EnvironmentUtils.cleanEnv();
-    //    config.setCompactionStrategy(originalCompactionStrategy);
   }
 
   @Test
   public void test1() throws Exception {
     prepareData1();
-    //    String[] res = new String[]{"0,1[20],15[2]", "25,8[25],8[25]", 
"50,3[54],3[54]",
-    // "75,null,null"};
     String res = "0,1[20],15[2],8[25],8[25],3[54],3[54],null,null,";
-    // 0,BPv[t]ofBucket1,TPv[t]ofBucket1,BPv[t]ofBucket2,TPv[t]ofBucket2,...
     try (Connection connection =
             DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", 
"root", "root");
         Statement statement = connection.createStatement()) {
@@ -140,12 +135,94 @@ public class MyTest_MinMax {
         statement.execute(sql);
       }
 
-      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 1, 5));
-      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 2, 15));
-      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 20, 1));
-      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 25, 8));
-      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 54, 3));
-      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 120, 8));
+      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 1, 5.0));
+      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 2, 
15.0));
+      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 20, 
1.0));
+      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 25, 
8.0));
+      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 54, 
3.0));
+      statement.execute(String.format(Locale.ENGLISH, insertTemplate, 120, 
8.0));
+      statement.execute("FLUSH");
+
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  @Test
+  public void test2() throws Exception {
+    prepareData2();
+    String res =
+        
"-1.2079272[0],1.101946[200],-1.014322[700],0.809559[1500],-0.785419[1600],-0.0211206[2100],";
+    try (Connection connection =
+            DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", 
"root", "root");
+        Statement statement = connection.createStatement()) {
+      boolean hasResultSet =
+          statement.execute(
+              "SELECT min_value(s0), max_value(s0)"
+                  + " FROM root.vehicle.d0 group by ([100,2100),250ms)");
+      // rps=4,nout=6,minmaxInterval=floor((tn-t2)/((nout-2)*rps/2))=250ms
+      Assert.assertTrue(hasResultSet);
+      try (ResultSet resultSet = statement.getResultSet()) {
+        int i = 0;
+        while (resultSet.next()) {
+          // 注意从1开始编号,所以第一列是无意义时间戳
+          String ans = resultSet.getString(2);
+          System.out.println(ans);
+          Assert.assertEquals(res, ans);
+        }
+      }
+      //      System.out.println(((IoTDBStatement) statement).executeFinish());
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
+  private static void prepareData2() {
+    // data:
+    // no overlap, no delete
+    try (Connection connection =
+            DriverManager.getConnection(
+                Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+        Statement statement = connection.createStatement()) {
+
+      for (String sql : creationSqls) {
+        statement.execute(sql);
+      }
+
+      int[] t =
+          new int[] {
+            0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 
1300, 1400, 1500,
+            1600, 1700, 1800, 1900, 2000, 2100
+          };
+      double[] v =
+          new double[] {
+            -1.2079272,
+            -0.01120245,
+            1.1019456,
+            -0.52320362,
+            -0.35970289,
+            0.1453591,
+            -0.45947892,
+            -1.0143219,
+            0.81760821,
+            0.5325646,
+            -0.29532424,
+            -0.1469335,
+            -0.12252526,
+            -0.67607713,
+            -0.16967308,
+            0.8095585,
+            -0.78541944,
+            0.03221141,
+            0.31586886,
+            -0.41353356,
+            -0.21019539,
+            -0.0211206
+          };
+      for (int i = 0; i < t.length; i++) {
+        statement.execute(String.format(Locale.ENGLISH, insertTemplate, t[i], 
v[i]));
+      }
       statement.execute("FLUSH");
 
     } catch (Exception e) {
diff --git 
a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/IOMonitor2.java 
b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/IOMonitor2.java
index c20a9de8994..c55ee561655 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/IOMonitor2.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/IOMonitor2.java
@@ -256,6 +256,11 @@ public class IOMonitor2 {
     //    M4_LSM_TP_SEARCH_ARRAY_c_genBPTP_cnt = 0;
   }
 
+  public static double calculateTri(
+      double t1, double v1, double t2, double v2, double t3, double v3) {
+    return Math.abs((t1 - t3) * (v2 - v3) - (t2 - t3) * (v1 - v3)) / 2;
+  }
+
   public static void addMeasure(Operation operation, long 
elapsedTimeInNanosecond) {
     switch (operation) {
       case DCP_Server_Query_Execute:

Reply via email to