This is an automated email from the ASF dual-hosted git repository.
xingtanzjr pushed a commit to branch rel/1.2
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/rel/1.2 by this push:
new b85f7c76318 [To rel/1.2] Fix point priority reader index out of bound
(#10932)
b85f7c76318 is described below
commit b85f7c76318fa1c58db7a859ccb63bef68c94ab1
Author: shuwenwei <[email protected]>
AuthorDate: Tue Aug 29 11:49:46 2023 +0800
[To rel/1.2] Fix point priority reader index out of bound (#10932)
---
.../executor/fast/SeriesCompactionExecutor.java | 11 +-
.../utils/executor/fast/element/PointElement.java | 3 +
.../execute/utils/reader/PointPriorityReader.java | 14 ++-
.../FastCompactionPerformerWithEmptyPageTest.java | 137 +++++++++++++++++++++
.../compaction/utils/CompactionTestFileWriter.java | 99 ++++++++++++++-
5 files changed, 257 insertions(+), 7 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/SeriesCompactionExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/SeriesCompactionExecutor.java
index 33a401c67ef..a879a85ed66 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/SeriesCompactionExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/SeriesCompactionExecutor.java
@@ -244,8 +244,9 @@ public abstract class SeriesCompactionExecutor {
|| firstPageElement.needForceDecoding) {
// has overlap or modified pages, then deserialize it
summary.pageOverlapOrModified += 1;
- pointPriorityReader.addNewPage(firstPageElement);
- compactWithOverlapPages();
+ if (pointPriorityReader.addNewPageIfPageNotEmpty(firstPageElement)) {
+ compactWithOverlapPages();
+ }
} else {
// has none overlap or modified pages, flush it to chunk writer
directly
summary.pageNoneOverlap += 1;
@@ -276,7 +277,9 @@ public abstract class SeriesCompactionExecutor {
} else {
// unsealed page is not large enough or page.endTime > file.endTime,
then deserialze it
summary.pageNoneOverlapButDeserialize += 1;
- pointPriorityReader.addNewPage(pageElement);
+ if (!pointPriorityReader.addNewPageIfPageNotEmpty(pageElement)) {
+ return;
+ }
// write data points of the current page into chunk writer
TimeValuePair point;
@@ -352,7 +355,7 @@ public abstract class SeriesCompactionExecutor {
|| nextPageElement.needForceDecoding) {
// next page is overlapped or modified, then deserialize it
summary.pageOverlapOrModified++;
- pointPriorityReader.addNewPage(nextPageElement);
+ pointPriorityReader.addNewPageIfPageNotEmpty(nextPageElement);
} else {
// has none overlap or modified pages, flush it to chunk writer
directly
summary.pageFakeOverlap += 1;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/element/PointElement.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/element/PointElement.java
index 94f9bb0d031..eadae73d012 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/element/PointElement.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/executor/fast/element/PointElement.java
@@ -41,6 +41,9 @@ public class PointElement {
} else {
this.pointReader = pageElement.batchData.getTsBlockAlignedRowIterator();
}
+ if (!pointReader.hasNextTimeValuePair()) {
+ return;
+ }
this.timeValuePair = pointReader.nextTimeValuePair();
this.timestamp = timeValuePair.getTimestamp();
this.priority = pageElement.priority;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/reader/PointPriorityReader.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/reader/PointPriorityReader.java
index 5b66d66d70a..392b5141f13 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/reader/PointPriorityReader.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/reader/PointPriorityReader.java
@@ -170,8 +170,10 @@ public class PointPriorityReader {
* Add a new overlapped page.
*
* @throws IOException if io errors occurred
+ * @return whether page is added into the queue
*/
- public void addNewPage(PageElement pageElement) throws IOException {
+ public boolean addNewPageIfPageNotEmpty(PageElement pageElement)
+ throws IOException, IllegalPathException, WriteProcessException {
if (currentPointElement != null) {
nextPointInOtherPage = Math.min(nextPointInOtherPage,
pageElement.startTime);
if (currentPoint.getTimestamp() >= nextPointInOtherPage) {
@@ -179,6 +181,14 @@ public class PointPriorityReader {
currentPointElement = null;
}
}
- pointQueue.add(new PointElement(pageElement));
+ PointElement pointElement = new PointElement(pageElement);
+ boolean pageIsNotEmpty = pointElement.timeValuePair != null;
+ if (pageIsNotEmpty) {
+ pointQueue.add(pointElement);
+ } else {
+ removePage.call(pageElement);
+ }
+
+ return pageIsNotEmpty;
}
}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/FastCompactionPerformerWithEmptyPageTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/FastCompactionPerformerWithEmptyPageTest.java
new file mode 100644
index 00000000000..815105aff1a
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/FastCompactionPerformerWithEmptyPageTest.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.db.storageengine.dataregion.compaction;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.exception.MetadataException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.performer.impl.FastCompactionPerformer;
+import
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.task.CrossSpaceCompactionTask;
+import
org.apache.iotdb.db.storageengine.dataregion.compaction.utils.CompactionTestFileWriter;
+import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
+import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
+import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class FastCompactionPerformerWithEmptyPageTest extends
AbstractCompactionTest {
+
+ @Before
+ public void setUp()
+ throws IOException, WriteProcessException, MetadataException,
InterruptedException {
+ super.setUp();
+ }
+
+ @After
+ public void tearDown() throws IOException, StorageEngineException {
+ super.tearDown();
+ }
+
+ @Test
+ public void test1() throws IOException, IllegalPathException {
+ String device = "root.testsg.d1";
+ TsFileResource seqFile1 = createEmptyFileAndResource(true);
+ try (CompactionTestFileWriter writer = new
CompactionTestFileWriter(seqFile1)) {
+ writer.startChunkGroup("d1");
+ writer.generateSimpleAlignedSeriesToCurrentDeviceWithNullValue(
+ Arrays.asList("s1", "s2", "s3"),
+ new TimeRange[][] {new TimeRange[] {new TimeRange(10, 30)}},
+ TSEncoding.RLE,
+ CompressionType.UNCOMPRESSED,
+ Arrays.asList(false, true, true));
+ writer.generateSimpleAlignedSeriesToCurrentDeviceWithNullValue(
+ Arrays.asList("s1", "s2", "s3"),
+ new TimeRange[][] {new TimeRange[] {new TimeRange(40, 50)}},
+ TSEncoding.RLE,
+ CompressionType.UNCOMPRESSED,
+ Arrays.asList(false, false, false));
+ writer.endChunkGroup();
+ writer.endFile();
+ }
+ seqFile1.updateStartTime(device, 10);
+ seqFile1.updateEndTime(device, 50);
+ seqFile1.serialize();
+ generateModsFile(Arrays.asList(new PartialPath("root.testsg.d1.s1")),
seqFile1, 0, 31);
+
+ TsFileResource unseqFile1 = createEmptyFileAndResource(false);
+ try (CompactionTestFileWriter writer = new
CompactionTestFileWriter(unseqFile1)) {
+ writer.startChunkGroup("d1");
+ writer.generateSimpleAlignedSeriesToCurrentDevice(
+ Arrays.asList("s1", "s2", "s3"),
+ new TimeRange[][] {new TimeRange[] {new TimeRange(20, 34)}},
+ TSEncoding.RLE,
+ CompressionType.UNCOMPRESSED);
+ writer.endChunkGroup();
+ writer.endFile();
+ }
+ unseqFile1.updateStartTime(device, 20);
+ unseqFile1.updateEndTime(device, 34);
+ unseqFile1.serialize();
+
+ CrossSpaceCompactionTask task =
+ new CrossSpaceCompactionTask(
+ 0,
+ tsFileManager,
+ Arrays.asList(seqFile1),
+ Arrays.asList(unseqFile1),
+ new FastCompactionPerformer(true),
+ new AtomicInteger(0),
+ 0,
+ 0);
+ try {
+ Assert.assertTrue(task.start());
+ } catch (Exception e) {
+ Assert.fail();
+ }
+ TsFileResource result = tsFileManager.getTsFileList(true).get(0);
+ result.buildDeviceTimeIndex();
+ Assert.assertEquals(20, result.getStartTime(device));
+ Assert.assertEquals(50, result.getEndTime(device));
+
+ validateSeqFiles(true);
+
+ try (TsFileSequenceReader reader = new
TsFileSequenceReader(result.getTsFilePath())) {
+ Map<String, List<ChunkMetadata>> chunkMetadataInDevice =
+ reader.readChunkMetadataInDevice(device);
+ long startTime = Long.MAX_VALUE, endTime = Long.MIN_VALUE;
+ List<ChunkMetadata> chunkMetadataList = chunkMetadataInDevice.get("s1");
+ for (ChunkMetadata chunkMetadata : chunkMetadataList) {
+ startTime = Math.min(startTime, chunkMetadata.getStartTime());
+ endTime = Math.max(endTime, chunkMetadata.getEndTime());
+ }
+ Assert.assertEquals(20, startTime);
+ Assert.assertEquals(50, endTime);
+ }
+ }
+}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/utils/CompactionTestFileWriter.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/utils/CompactionTestFileWriter.java
index 8e447892107..fd02862199b 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/utils/CompactionTestFileWriter.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/utils/CompactionTestFileWriter.java
@@ -31,12 +31,13 @@ import
org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
import org.apache.iotdb.tsfile.write.writer.TsFileIOWriter;
+import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
-public class CompactionTestFileWriter {
+public class CompactionTestFileWriter implements Closeable {
private TsFileResource resource;
private TsFileIOWriter fileWriter;
@@ -170,6 +171,34 @@ public class CompactionTestFileWriter {
}
}
+ public void generateSimpleAlignedSeriesToCurrentDeviceWithNullValue(
+ List<String> measurementNames,
+ TimeRange[] toGenerateChunkTimeRanges,
+ TSEncoding encoding,
+ CompressionType compressionType,
+ List<Boolean> nullMeasurements)
+ throws IOException {
+ List<IMeasurementSchema> measurementSchemas = new ArrayList<>();
+ for (String measurementName : measurementNames) {
+ measurementSchemas.add(
+ new MeasurementSchema(measurementName, TSDataType.INT32, encoding,
compressionType));
+ }
+ for (TimeRange toGenerateChunk : toGenerateChunkTimeRanges) {
+ AlignedChunkWriterImpl alignedChunkWriter = new
AlignedChunkWriterImpl(measurementSchemas);
+ currentDeviceStartTime = Math.min(toGenerateChunk.getMin(),
currentDeviceStartTime);
+ currentDeviceEndTime = Math.max(toGenerateChunk.getMax(),
currentDeviceEndTime);
+ for (long time = toGenerateChunk.getMin(); time <=
toGenerateChunk.getMax(); time++) {
+ alignedChunkWriter.getTimeChunkWriter().write(time);
+ for (int i = 0; i < measurementNames.size(); i++) {
+ alignedChunkWriter
+ .getValueChunkWriterByIndex(i)
+ .write(time, new Random().nextInt(), nullMeasurements.get(i));
+ }
+ }
+ alignedChunkWriter.writeToFileWriter(fileWriter);
+ }
+ }
+
public void generateSimpleAlignedSeriesToCurrentDevice(
List<String> measurementNames,
TimeRange[][] toGenerateChunkPageTimeRanges,
@@ -203,6 +232,40 @@ public class CompactionTestFileWriter {
}
}
+ public void generateSimpleAlignedSeriesToCurrentDeviceWithNullValue(
+ List<String> measurementNames,
+ TimeRange[][] toGenerateChunkPageTimeRanges,
+ TSEncoding encoding,
+ CompressionType compressionType,
+ List<Boolean> nullMeasurement)
+ throws IOException {
+ List<IMeasurementSchema> measurementSchemas = new ArrayList<>();
+ for (String measurementName : measurementNames) {
+ measurementSchemas.add(
+ new MeasurementSchema(measurementName, TSDataType.INT32, encoding,
compressionType));
+ }
+ for (TimeRange[] toGenerateChunk : toGenerateChunkPageTimeRanges) {
+ AlignedChunkWriterImpl alignedChunkWriter = new
AlignedChunkWriterImpl(measurementSchemas);
+ for (TimeRange toGeneratePageTimeRange : toGenerateChunk) {
+ currentDeviceStartTime = Math.min(toGeneratePageTimeRange.getMin(),
currentDeviceStartTime);
+ currentDeviceEndTime = Math.max(toGeneratePageTimeRange.getMax(),
currentDeviceEndTime);
+ for (long time = toGeneratePageTimeRange.getMin();
+ time <= toGeneratePageTimeRange.getMax();
+ time++) {
+ alignedChunkWriter.write(time);
+ for (int i = 0; i < measurementNames.size(); i++) {
+ alignedChunkWriter
+ .getValueChunkWriterByIndex(i)
+ .getPageWriter()
+ .write(time, new Random().nextInt(), nullMeasurement.get(i));
+ }
+ }
+ alignedChunkWriter.sealCurrentPage();
+ }
+ alignedChunkWriter.writeToFileWriter(fileWriter);
+ }
+ }
+
public void generateSimpleAlignedSeriesToCurrentDevice(
List<String> measurementNames,
TimeRange[][][] toGenerateChunkPageTimeRanges,
@@ -235,4 +298,38 @@ public class CompactionTestFileWriter {
alignedChunkWriter.writeToFileWriter(fileWriter);
}
}
+
+ public void generateSimpleAlignedSeriesToCurrentDeviceWithNullValue(
+ List<String> measurementNames,
+ TimeRange[][][] toGenerateChunkPageTimeRanges,
+ TSEncoding encoding,
+ CompressionType compressionType,
+ List<Boolean> nullMeasurements)
+ throws IOException {
+ List<IMeasurementSchema> measurementSchemas = new ArrayList<>();
+ for (String measurementName : measurementNames) {
+ measurementSchemas.add(
+ new MeasurementSchema(measurementName, TSDataType.INT32, encoding,
compressionType));
+ }
+ for (TimeRange[][] toGenerateChunk : toGenerateChunkPageTimeRanges) {
+ AlignedChunkWriterImpl alignedChunkWriter = new
AlignedChunkWriterImpl(measurementSchemas);
+ for (TimeRange[] toGeneratePageTimeRanges : toGenerateChunk) {
+ for (TimeRange pointsTimeRange : toGeneratePageTimeRanges) {
+ currentDeviceStartTime = Math.min(pointsTimeRange.getMin(),
currentDeviceStartTime);
+ currentDeviceEndTime = Math.max(pointsTimeRange.getMax(),
currentDeviceEndTime);
+ for (long time = pointsTimeRange.getMin(); time <=
pointsTimeRange.getMax(); time++) {
+ alignedChunkWriter.write(time);
+ for (int i = 0; i < measurementNames.size(); i++) {
+ alignedChunkWriter
+ .getValueChunkWriterByIndex(i)
+ .getPageWriter()
+ .write(time, new Random().nextInt(),
nullMeasurements.get(i));
+ }
+ }
+ }
+ alignedChunkWriter.sealCurrentPage();
+ }
+ alignedChunkWriter.writeToFileWriter(fileWriter);
+ }
+ }
}