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 b1188bd2f4a6b29cd942cac5e0d1c74fc95be165 Author: Lei Rui <[email protected]> AuthorDate: Sat Feb 3 01:52:29 2024 +0800 add convex hull metadata --- .../groupby/GroupByWithoutValueFilterDataSet.java | 89 ++++++----- .../apache/iotdb/db/integration/tri/MyTest_ch.java | 116 ++++++++++++++ .../tsfile/file/metadata/statistics/QuickHull.java | 137 +++++++++++++++++ .../file/metadata/statistics/QuickHullPoint.java | 16 ++ .../file/metadata/statistics/Statistics.java | 169 +++++++++++++++++---- 5 files changed, 453 insertions(+), 74 deletions(-) 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 a51924bb9d8..e71bc91f6c6 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 @@ -31,11 +31,9 @@ import org.apache.iotdb.db.query.aggregation.AggregateResult; import org.apache.iotdb.db.query.context.QueryContext; 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; import org.apache.iotdb.tsfile.read.common.RowRecord; import org.apache.iotdb.tsfile.read.expression.IExpression; @@ -653,10 +651,10 @@ public class GroupByWithoutValueFilterDataSet extends GroupByEngineDataSet { boolean ascending) throws StorageEngineException, QueryProcessException { if (CONFIG.getEnableTri().equals("MinMax")) { - return new LocalGroupByExecutorTri_MinMax( // TODO + return new LocalGroupByExecutorTri_MinMax( path, allSensors, dataType, context, timeFilter, fileFilter, ascending); } else if (CONFIG.getEnableTri().equals("MinMaxLTTB")) { - return new LocalGroupByExecutorTri_MinMaxPreselection( // TODO + return new LocalGroupByExecutorTri_MinMaxPreselection( path, allSensors, dataType, context, timeFilter, fileFilter, ascending); } else if (CONFIG.getEnableTri().equals("M4")) { return new LocalGroupByExecutorTri_M4( @@ -667,45 +665,54 @@ public class GroupByWithoutValueFilterDataSet extends GroupByEngineDataSet { } else if (CONFIG.getEnableTri().equals("ILTS")) { return new LocalGroupByExecutorTri_ILTS( path, allSensors, dataType, context, timeFilter, fileFilter, ascending); - } - // deprecated below - else if (CONFIG.isEnableCPV()) { - if (TSFileDescriptor.getInstance().getConfig().isEnableMinMaxLSM()) { // MinMax-LSM - IOMonitor2.dataSetType = - DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_EnableMinMaxLSM; - return new LocalGroupByExecutor4MinMax( - path, allSensors, dataType, context, timeFilter, fileFilter, ascending); - } else { // M4-LSM - if (TSFileDescriptor.getInstance().getConfig().isUseTimeIndex() - && TSFileDescriptor.getInstance().getConfig().isUseValueIndex()) { - IOMonitor2.dataSetType = - DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_UseIndex; - } else if (!TSFileDescriptor.getInstance().getConfig().isUseTimeIndex() - && TSFileDescriptor.getInstance().getConfig().isUseValueIndex()) { - IOMonitor2.dataSetType = - DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_NoTimeIndex; - } else if (TSFileDescriptor.getInstance().getConfig().isUseTimeIndex() - && !TSFileDescriptor.getInstance().getConfig().isUseValueIndex()) { - IOMonitor2.dataSetType = - DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_NoValueIndex; - } else { - IOMonitor2.dataSetType = - DataSetType - .GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_NoTimeValueIndex; - } - return new LocalGroupByExecutor4CPV( - path, allSensors, dataType, context, timeFilter, fileFilter, ascending); - } - } else { // enableCPV=false - if (TSFileDescriptor.getInstance().getConfig().isUseStatistics()) { - IOMonitor2.dataSetType = - DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor_UseStatistics; - } else { - IOMonitor2.dataSetType = - DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor_NotUseStatistics; - } + } else { + logger.info("No matched enable_tri!"); return new LocalGroupByExecutor( path, allSensors, dataType, context, timeFilter, fileFilter, ascending); } + + // // deprecated below, note that time&value index are also deprecated in Statistics + // else if (CONFIG.isEnableCPV()) { + // if (TSFileDescriptor.getInstance().getConfig().isEnableMinMaxLSM()) { // MinMax-LSM + // IOMonitor2.dataSetType = + // + // DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_EnableMinMaxLSM; + // return new LocalGroupByExecutor4MinMax( + // path, allSensors, dataType, context, timeFilter, fileFilter, ascending); + // } else { // M4-LSM + // if (TSFileDescriptor.getInstance().getConfig().isUseTimeIndex() + // && TSFileDescriptor.getInstance().getConfig().isUseValueIndex()) { + // IOMonitor2.dataSetType = + // DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_UseIndex; + // } else if (!TSFileDescriptor.getInstance().getConfig().isUseTimeIndex() + // && TSFileDescriptor.getInstance().getConfig().isUseValueIndex()) { + // IOMonitor2.dataSetType = + // + // DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_NoTimeIndex; + // } else if (TSFileDescriptor.getInstance().getConfig().isUseTimeIndex() + // && !TSFileDescriptor.getInstance().getConfig().isUseValueIndex()) { + // IOMonitor2.dataSetType = + // + // DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_NoValueIndex; + // } else { + // IOMonitor2.dataSetType = + // DataSetType + // .GroupByWithoutValueFilterDataSet_LocalGroupByExecutor4CPV_NoTimeValueIndex; + // } + // return new LocalGroupByExecutor4CPV( + // path, allSensors, dataType, context, timeFilter, fileFilter, ascending); + // } + // } else { // enableCPV=false + // if (TSFileDescriptor.getInstance().getConfig().isUseStatistics()) { + // IOMonitor2.dataSetType = + // DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor_UseStatistics; + // } else { + // IOMonitor2.dataSetType = + // + // DataSetType.GroupByWithoutValueFilterDataSet_LocalGroupByExecutor_NotUseStatistics; + // } + // return new LocalGroupByExecutor( + // path, allSensors, dataType, context, timeFilter, fileFilter, ascending); + // } } } diff --git a/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_ch.java b/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_ch.java new file mode 100644 index 00000000000..f2cd1dd08c0 --- /dev/null +++ b/server/src/test/java/org/apache/iotdb/db/integration/tri/MyTest_ch.java @@ -0,0 +1,116 @@ +package org.apache.iotdb.db.integration.tri; + +import org.apache.iotdb.db.utils.EnvironmentUtils; +import org.apache.iotdb.jdbc.Config; +import org.apache.iotdb.tsfile.file.metadata.statistics.QuickHull; +import org.apache.iotdb.tsfile.file.metadata.statistics.QuickHullPoint; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.BitSet; + +public class MyTest_ch { + + @Before + public void setUp() throws Exception { + EnvironmentUtils.envSetUp(); + Class.forName(Config.JDBC_DRIVER_NAME); + } + + @After + public void tearDown() throws Exception { + EnvironmentUtils.cleanEnv(); + } + + @Test + public void test1() throws Exception { + System.out.println("Quick Hull Test"); + ArrayList<QuickHullPoint> points = new ArrayList<>(); + points.add(new QuickHullPoint(0, 0, 0)); + points.add(new QuickHullPoint(1, 3, 1)); + points.add(new QuickHullPoint(2, 2, 2)); + points.add(new QuickHullPoint(3, 2, 3)); + points.add(new QuickHullPoint(4, 0, 4)); + points.add(new QuickHullPoint(5, 2, 5)); + points.add(new QuickHullPoint(100, 2, 6)); + + BitSet bitSet1 = QuickHull.quickHull(points); + System.out.println(bitSet1); + // System.out.println(bitSet1.size()); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(bitSet1); + oos.flush(); + byte[] bytes = baos.toByteArray(); + // byte[] bytes = bitSet1.toByteArray(); + System.out.println(bytes.length); + + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais); + BitSet bitSet = (BitSet) ois.readObject(); + System.out.println(bitSet); + // System.out.println(bitSet.size()); + Assert.assertTrue(bitSet.get(1)); + Assert.assertFalse(bitSet.get(3)); + } + + // public static void main(String args[]) throws Exception { + // + // System.out.println("Quick Hull Test"); + //// Scanner sc = new Scanner(System.in); + //// System.out.println("Enter the number of points"); + //// int N = sc.nextInt(); + // + // ArrayList<QuickHullPoint> points = new ArrayList<>(); + //// System.out.println("Enter the coordinates of each points: <x> <y>"); + //// for (int i = 0; i < N; i++) { + //// int x = sc.nextInt(); + //// int y = sc.nextInt(); + //// Point e = new Point(x, y); + //// points.add(i, new QuickHullPoint(x,y,i)); + //// } + // points.add(new QuickHullPoint(0,0,0)); + // points.add(new QuickHullPoint(1,3,1)); + // points.add(new QuickHullPoint(2,2,2)); + // points.add(new QuickHullPoint(3,2,3)); + // points.add(new QuickHullPoint(4,0,4)); + // points.add(new QuickHullPoint(5,2,5)); + // + //// QuickHull qh = new QuickHull(); + // BitSet bitSet1 = QuickHull.quickHull(points); + //// System.out + //// .println("The points in the Convex hull using Quick Hull are: "); + //// for (int i = 0; i < p.size(); i++) { + //// System.out.println("(" + p.get(i).x + ", " + p.get(i).y + ")"); + //// } + // System.out.println(bitSet1.toString()); + // System.out.println(bitSet1.size()); + //// sc.close(); + // + //// BitSet bits = new BitSet(100000); + //// System.out.println(bits.size()); + //// bits.set(2); + // ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // ObjectOutputStream oos = new ObjectOutputStream(baos); + // oos.writeObject(bitSet1); + // oos.close(); + // byte[] bytes = baos.toByteArray(); + // System.out.println(bytes.length); + // ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + // ObjectInputStream ois = new ObjectInputStream(bais); + // BitSet bitSet = (BitSet) ois.readObject(); + // System.out.println(bitSet); + // System.out.println(bitSet.get(1)); + // System.out.println(bitSet.get(3)); + // System.out.println(bitSet.size()); + // } +} diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/QuickHull.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/QuickHull.java new file mode 100644 index 00000000000..49425fc346d --- /dev/null +++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/QuickHull.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.iotdb.tsfile.file.metadata.statistics; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.List; + +public class QuickHull { + + public static BitSet quickHull( + List<QuickHullPoint> points) { // TODO check this input points deep clone? + BitSet bitSet = new BitSet(points.size()); + + // List<Point> convexHull = new ArrayList<>(); + + if (points.size() < 3) { + bitSet.set(0); + bitSet.set(1); + bitSet.set(2); + return bitSet; + } + + // assume point.x i.e., t is monotonically increasing + int minPoint = 0; + int maxPoint = points.size() - 1; + // bitSet.set(0); + // bitSet.set(points.size() - 1); // TODO check this has not remove any + QuickHullPoint A = points.get(minPoint); + QuickHullPoint B = points.get(maxPoint); + // convexHull.add(A); + // convexHull.add(B); + // points.remove(A); // TODO check this input data deep clone? + // points.remove(B); + points.remove(A); + points.remove(B); // TODO check this + bitSet.set(A.idx); + bitSet.set(B.idx); + + ArrayList<QuickHullPoint> leftSet = new ArrayList<>(); + ArrayList<QuickHullPoint> rightSet = new ArrayList<>(); + + for (QuickHullPoint p : points) { + if (pointLocation(A, B, p) == -1) { + leftSet.add(p); + } else if (pointLocation(A, B, p) == 1) { + rightSet.add(p); + } + } + hullSet(A, B, rightSet, bitSet); + hullSet(B, A, leftSet, bitSet); + + return bitSet; + } + + public static double distance(QuickHullPoint A, QuickHullPoint B, QuickHullPoint C) { + double ABx = B.t - A.t; + double ABy = B.v - A.v; + double num = ABx * (A.v - C.v) - ABy * (A.t - C.t); + if (num < 0) { + num = -num; + } + return num; + // 返回的是ABC三角形面积的二倍数 + } + + public static void hullSet( + QuickHullPoint A, QuickHullPoint B, List<QuickHullPoint> set, BitSet bitSet) { + // int insertPosition = hull.indexOf(B); + if (set.size() == 0) { + return; + } + if (set.size() == 1) { + QuickHullPoint p = set.get(0); + set.remove(p); + // hull.add(insertPosition, p); + bitSet.set(p.idx); + return; + } + double dist = -Double.MAX_VALUE; + // int furthestPoint = -1; + QuickHullPoint furthestPoint = null; + for (QuickHullPoint p : set) { + double distance = distance(A, B, p); + if (distance > dist) { + dist = distance; + furthestPoint = p; + } + } + // QuickHullPoint P = set.get(furthestPoint); + set.remove(furthestPoint); + // hull.add(insertPosition, P); + bitSet.set(furthestPoint.idx); + + // Determine who's to the left of AP + ArrayList<QuickHullPoint> leftSetAP = new ArrayList<>(); + for (QuickHullPoint M : set) { + if (pointLocation(A, furthestPoint, M) == 1) { + leftSetAP.add(M); + } + } + + // Determine who's to the left of PB + ArrayList<QuickHullPoint> leftSetPB = new ArrayList<>(); + for (QuickHullPoint M : set) { + if (pointLocation(furthestPoint, B, M) == 1) { + leftSetPB.add(M); + } + } + hullSet(A, furthestPoint, leftSetAP, bitSet); + hullSet(furthestPoint, B, leftSetPB, bitSet); + } + + public static int pointLocation(QuickHullPoint A, QuickHullPoint B, QuickHullPoint P) { + double cp1 = (B.t - A.t) * (P.v - A.v) - (B.v - A.v) * (P.t - A.t); + return Double.compare(cp1, 0); + // return 1 means P is above the line connecting A and B + // return -1 means P is below the line connecting A and B + // return 0 means P is on the line connecting A and B + } +} diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/QuickHullPoint.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/QuickHullPoint.java new file mode 100644 index 00000000000..8709d14ea01 --- /dev/null +++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/QuickHullPoint.java @@ -0,0 +1,16 @@ +package org.apache.iotdb.tsfile.file.metadata.statistics; + +public class QuickHullPoint { + + public int idx; // pos in the input array, start from 0 + + public long t; + + public double v; + + public QuickHullPoint(long t, double v, int idx) { + this.t = t; + this.v = v; + this.idx = idx; + } +} diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java index da2b27e9233..89a9ffe8c41 100644 --- a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java +++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java @@ -32,11 +32,18 @@ import org.eclipse.collections.impl.list.mutable.primitive.DoubleArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.OutputStream; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.BitSet; import java.util.Collections; +import java.util.List; import java.util.Objects; /** @@ -64,6 +71,12 @@ public abstract class Statistics<T> { private StepRegress stepRegress = new StepRegress(); + private List<QuickHullPoint> quickHullPoints = new ArrayList<>(); + private int quickHullIdx = 0; + private boolean quickHullLearned = false; + + private BitSet quickHullBitSet = null; + public ValueIndex valueIndex = new ValueIndex(); /** @author Yuyuan Kang */ @@ -133,10 +146,12 @@ public abstract class Statistics<T> { byteLen += ReadWriteIOUtils.write(endTime, outputStream); // value statistics of different data type byteLen += serializeStats(outputStream); - // serialize stepRegress - byteLen += serializeStepRegress(outputStream, true); - // serialize value index - byteLen += serializeValueIndex(outputStream, true); + // // serialize stepRegress + // byteLen += serializeStepRegress(outputStream, true); + // // serialize value index + // byteLen += serializeValueIndex(outputStream, true); + // serialize convex hull + byteLen += serializeConvexHull(outputStream, true); return byteLen; } @@ -147,10 +162,12 @@ public abstract class Statistics<T> { byteLen += ReadWriteIOUtils.write(endTime, outputStream); // value statistics of different data type byteLen += serializeStats(outputStream); - // serialize stepRegress - byteLen += serializeStepRegress(outputStream, log); - // serialize value index - byteLen += serializeValueIndex(outputStream, log); + // // serialize stepRegress + // byteLen += serializeStepRegress(outputStream, log); + // // serialize value index + // byteLen += serializeValueIndex(outputStream, log); + // serialize convex hull + byteLen += serializeConvexHull(outputStream, log); return byteLen; } @@ -200,6 +217,34 @@ public abstract class Statistics<T> { return byteLen; } + int serializeConvexHull(OutputStream outputStream, boolean log) throws IOException { + if (!quickHullLearned) { + // this is necessary, otherwise serialized twice by timeseriesMetadata and chunkMetadata + // causing learn() executed more than once!! + quickHullBitSet = QuickHull.quickHull(quickHullPoints); + quickHullLearned = true; + quickHullPoints = null; + } + // System.out.println("debug:::::" + quickHullBitSet); + + // write bitset + int byteLen = 0; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(quickHullBitSet); + oos.flush(); + byte[] bytes = baos.toByteArray(); + // 参考serializeBloomFilter + byteLen += ReadWriteForEncodingUtils.writeUnsignedVarInt(bytes.length, outputStream); + outputStream.write(bytes); + byteLen += bytes.length; + + if (log) { + LOG.info("convex hull,{}", bytes.length); + } + return byteLen; + } + abstract int serializeStats(OutputStream outputStream) throws IOException; /** read data from the inputStream. */ @@ -273,12 +318,17 @@ public abstract class Statistics<T> { // must be sure no overlap between two statistics this.count += stats.count; mergeStatisticsValue(stats); - // TODO M4-LSM assumes that there is always only one page in a chunk - // TODO M4-LSM if there are more than one chunk in a time series, then access each - // chunkMetadata anyway - this.stepRegress = stats.stepRegress; - // TODO - this.valueIndex = stats.valueIndex; + // TODO assumes that there is always only one page in a chunk + // TODO if there are more than one chunk in a time series, then access each + // chunkMetadata anyway + // this.stepRegress = stats.stepRegress; + // this.valueIndex = stats.valueIndex; + + // 注意这里要把points也一并赋值,因为当chunk里只有一个page的时候只serialize chunk的metadata + this.quickHullPoints = stats.quickHullPoints; + this.quickHullBitSet = stats.quickHullBitSet; + this.quickHullIdx = stats.quickHullIdx; + this.quickHullLearned = stats.quickHullLearned; isEmpty = false; } else { @@ -311,10 +361,11 @@ public abstract class Statistics<T> { if (time > this.endTime) { endTime = time; } + updateStats(value, time); // TP,BP,sum,lastValue,firstValue // update time index - updateStepRegress(time); - updateValueIndex(value); - updateStats(value, time); + // updateStepRegress(time); + // updateValueIndex(value); + updateConvexHull(time, value); } /** @author Yuyuan Kang */ @@ -326,9 +377,10 @@ public abstract class Statistics<T> { if (time > this.endTime) { endTime = time; } - updateStepRegress(time); - updateValueIndex(value); updateStats(value, time); + // updateStepRegress(time); + // updateValueIndex(value); + updateConvexHull(time, value); } /** @author Yuyuan Kang */ @@ -340,9 +392,10 @@ public abstract class Statistics<T> { if (time > this.endTime) { endTime = time; } - updateStepRegress(time); - updateValueIndex(value); updateStats(value, time); + // updateStepRegress(time); + // updateValueIndex(value); + updateConvexHull(time, value); } /** @author Yuyuan Kang */ @@ -354,9 +407,10 @@ public abstract class Statistics<T> { if (time > this.endTime) { endTime = time; } - updateStepRegress(time); - updateValueIndex(value); updateStats(value, time); + // updateStepRegress(time); + // updateValueIndex(value); + updateConvexHull(time, value); } @Deprecated @@ -392,9 +446,10 @@ public abstract class Statistics<T> { if (time[batchSize - 1] > this.endTime) { endTime = time[batchSize - 1]; } - updateStepRegress(time, batchSize); - updateValueIndex(values, batchSize); updateStats(values, time, batchSize); + // updateStepRegress(time, batchSize); + // updateValueIndex(values, batchSize); + updateConvexHull(time, values, batchSize); } /** @author Yuyuan Kang */ @@ -406,9 +461,10 @@ public abstract class Statistics<T> { if (time[batchSize - 1] > this.endTime) { endTime = time[batchSize - 1]; } - updateStepRegress(time, batchSize); - updateValueIndex(values, batchSize); updateStats(values, time, batchSize); + // updateStepRegress(time, batchSize); + // updateValueIndex(values, batchSize); + updateConvexHull(time, values, batchSize); } /** @author Yuyuan Kang */ @@ -420,9 +476,10 @@ public abstract class Statistics<T> { if (time[batchSize - 1] > this.endTime) { endTime = time[batchSize - 1]; } - updateStepRegress(time, batchSize); - updateValueIndex(values, batchSize); updateStats(values, time, batchSize); + // updateStepRegress(time, batchSize); + // updateValueIndex(values, batchSize); + updateConvexHull(time, values, batchSize); } /** @author Yuyuan Kang */ @@ -434,9 +491,10 @@ public abstract class Statistics<T> { if (time[batchSize - 1] > this.endTime) { endTime = time[batchSize - 1]; } - updateStepRegress(time, batchSize); - updateValueIndex(values, batchSize); updateStats(values, time, batchSize); + // updateStepRegress(time, batchSize); + // updateValueIndex(values, batchSize); + updateConvexHull(time, values, batchSize); } @Deprecated @@ -475,12 +533,40 @@ public abstract class Statistics<T> { stepRegress.insert(timestamp); } + void updateConvexHull(long timestamp, Object value) { + quickHullPoints.add(new QuickHullPoint(timestamp, (double) value, quickHullIdx++)); + } + void updateStepRegress(long[] timestamps, int batchSize) { for (int i = 0; i < batchSize; i++) { updateStepRegress(timestamps[i]); } } + void updateConvexHull(long[] timestamps, int[] values, int batchSize) { + for (int i = 0; i < batchSize; i++) { + updateConvexHull(timestamps[i], values[i]); + } + } + + void updateConvexHull(long[] timestamps, long[] values, int batchSize) { + for (int i = 0; i < batchSize; i++) { + updateConvexHull(timestamps[i], values[i]); + } + } + + void updateConvexHull(long[] timestamps, float[] values, int batchSize) { + for (int i = 0; i < batchSize; i++) { + updateConvexHull(timestamps[i], values[i]); + } + } + + void updateConvexHull(long[] timestamps, double[] values, int batchSize) { + for (int i = 0; i < batchSize; i++) { + updateConvexHull(timestamps[i], values[i]); + } + } + void updateValueIndex(int value) { valueIndex.insert(value); } @@ -601,8 +687,9 @@ public abstract class Statistics<T> { statistics.setStartTime(ReadWriteIOUtils.readLong(buffer)); statistics.setEndTime(ReadWriteIOUtils.readLong(buffer)); statistics.deserialize(buffer); - statistics.deserializeStepRegress(buffer); - statistics.deserializeValueIndex(buffer); + // statistics.deserializeStepRegress(buffer); + // statistics.deserializeValueIndex(buffer); + statistics.deserializeConvexHull(buffer); statistics.isEmpty = false; return statistics; } @@ -722,6 +809,18 @@ public abstract class Statistics<T> { } } + void deserializeConvexHull(ByteBuffer byteBuffer) throws IOException { + try { + byte[] bytes = ReadWriteIOUtils.readByteBufferWithSelfDescriptionLength(byteBuffer); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais); + quickHullBitSet = (BitSet) ois.readObject(); + // System.out.println("debug:::::" + quickHullBitSet); + } catch (ClassNotFoundException e) { + System.out.println("deserializeConvexHull: " + e); + } + } + public long getStartTime() { return startTime; } @@ -734,6 +833,10 @@ public abstract class Statistics<T> { return stepRegress; } + public BitSet getQuickHullBitSet() { + return quickHullBitSet; + } + public int getCount() { return count; }
