This is an automated email from the ASF dual-hosted git repository.
haonan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 16c77d73273 fix index out of bounds with all empty value chunk in one
device (#11906)
16c77d73273 is described below
commit 16c77d732733daf48bb75297b64a51050f20408d
Author: 周沛辰 <[email protected]>
AuthorDate: Tue Jan 16 18:02:54 2024 +0800
fix index out of bounds with all empty value chunk in one device (#11906)
---
.../execute/utils/MultiTsFileDeviceIterator.java | 4 +
.../compaction/ReadChunkInnerCompactionTest.java | 144 +++++++++++++++++++++
.../file/metadata/AlignedTimeSeriesMetadata.java | 1 +
.../iotdb/tsfile/read/TsFileSequenceReader.java | 3 +-
4 files changed, 151 insertions(+), 1 deletion(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/MultiTsFileDeviceIterator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/MultiTsFileDeviceIterator.java
index 2aef8c8094c..0bbc4535adf 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/MultiTsFileDeviceIterator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/utils/MultiTsFileDeviceIterator.java
@@ -373,6 +373,10 @@ public class MultiTsFileDeviceIterator implements
AutoCloseable {
private void applyModificationForAlignedChunkMetadataList(
TsFileResource tsFileResource, List<AlignedChunkMetadata>
alignedChunkMetadataList)
throws IllegalPathException {
+ if (alignedChunkMetadataList.isEmpty()) {
+ // all the value chunks is empty chunk
+ return;
+ }
ModificationFile modificationFile =
ModificationFile.getNormalMods(tsFileResource);
if (!modificationFile.exists()) {
return;
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/ReadChunkInnerCompactionTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/ReadChunkInnerCompactionTest.java
index e87596c1c55..7978fc6bef9 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/ReadChunkInnerCompactionTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/ReadChunkInnerCompactionTest.java
@@ -32,6 +32,7 @@ import
org.apache.iotdb.db.storageengine.dataregion.compaction.utils.CompactionT
import org.apache.iotdb.db.storageengine.dataregion.modification.Deletion;
import
org.apache.iotdb.db.storageengine.dataregion.read.control.FileReaderManager;
import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
+import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
@@ -40,9 +41,13 @@ import
org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.read.TimeValuePair;
import org.apache.iotdb.tsfile.read.common.TimeRange;
+import org.apache.iotdb.tsfile.utils.Binary;
import org.apache.iotdb.tsfile.write.chunk.AlignedChunkWriterImpl;
import org.apache.iotdb.tsfile.write.chunk.ChunkWriterImpl;
import org.apache.iotdb.tsfile.write.chunk.IChunkWriter;
+import org.apache.iotdb.tsfile.write.chunk.ValueChunkWriter;
+import org.apache.iotdb.tsfile.write.page.TimePageWriter;
+import org.apache.iotdb.tsfile.write.page.ValuePageWriter;
import org.apache.iotdb.tsfile.write.writer.TsFileIOWriter;
import org.junit.After;
@@ -54,6 +59,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -709,4 +715,142 @@ public class ReadChunkInnerCompactionTest extends
AbstractCompactionTest {
Assert.assertEquals(
4,
Objects.requireNonNull(seqResource1.getTsFile().getParentFile().listFiles()).length);
}
+
+ @Test
+ public void testCompactionWithAllEmptyValueChunks() throws IOException,
IllegalPathException {
+ List<PartialPath> timeserisPathList = new ArrayList<>();
+ List<TSDataType> tsDataTypes = new ArrayList<>();
+ // seq file with empty aligned device
+ int deviceNum = 10;
+ int measurementNum = 10;
+ TsFileResource resource = createEmptyFileAndResource(true);
+ try (TsFileIOWriter tsFileIOWriter = new
TsFileIOWriter(resource.getTsFile())) {
+ // write the data in device
+ for (int deviceIndex = 0; deviceIndex < deviceNum; deviceIndex++) {
+ tsFileIOWriter.startChunkGroup(COMPACTION_TEST_SG + PATH_SEPARATOR +
"d" + deviceIndex);
+
+ List<TSDataType> dataTypes = createDataType(measurementNum);
+ List<TSEncoding> encodings = createEncodingType(measurementNum);
+ List<CompressionType> compressionTypes =
createCompressionType(measurementNum);
+ List<Integer> measurementIndexes = new ArrayList<>();
+ for (int i = 0; i < measurementNum; i++) {
+ measurementIndexes.add(i);
+ }
+ List<PartialPath> timeseriesPath =
+ createTimeseries(deviceIndex, measurementIndexes, dataTypes, true);
+
+ List<IChunkWriter> iChunkWriters =
+ createChunkWriter(timeseriesPath, dataTypes, encodings,
compressionTypes, true);
+
+ // write first chunk
+ List<TimeRange> pages = new ArrayList<>();
+ pages.add(new TimeRange(0L, 300L));
+ pages.add(new TimeRange(500L, 600L));
+
+ for (IChunkWriter iChunkWriter : iChunkWriters) {
+ if (deviceIndex == 0) {
+ writeEmptyAlignedChunk(
+ (AlignedChunkWriterImpl) iChunkWriter, tsFileIOWriter, pages,
true);
+ } else {
+ writeAlignedChunk((AlignedChunkWriterImpl) iChunkWriter,
tsFileIOWriter, pages, true);
+ }
+ }
+
+ tsFileIOWriter.endChunkGroup();
+ resource.updateStartTime(COMPACTION_TEST_SG + PATH_SEPARATOR + "d" +
deviceIndex, 0);
+ resource.updateEndTime(COMPACTION_TEST_SG + PATH_SEPARATOR + "d" +
deviceIndex, 1400);
+ timeserisPathList.addAll(timeseriesPath);
+ tsDataTypes.addAll(dataTypes);
+ if (deviceIndex == 0) {
+ generateModsFile(timeseriesPath, resource, Long.MIN_VALUE,
Long.MAX_VALUE);
+ }
+ }
+ tsFileIOWriter.endFile();
+ }
+ resource.serialize();
+ seqResources.add(resource);
+
+ // start compacting
+ tsFileManager.addAll(seqResources, true);
+ tsFileManager.addAll(unseqResources, false);
+
+ Map<PartialPath, List<TimeValuePair>> sourceDatas =
+ readSourceFiles(createTimeseries(maxDeviceNum, maxMeasurementNum,
true), tsDataTypes);
+
+ // execute inner compaction for each seq file to produce file with empty
value chunk
+ InnerSpaceCompactionTask task =
+ new InnerSpaceCompactionTask(
+ 0,
+ tsFileManager,
+ Collections.singletonList(seqResources.get(0)),
+ true,
+ new ReadChunkCompactionPerformer(),
+ 0);
+ Assert.assertTrue(task.start());
+
+ validateSeqFiles(true);
+
+ validateTargetDatas(sourceDatas, tsDataTypes);
+ }
+
+ private void writeEmptyAlignedChunk(
+ AlignedChunkWriterImpl alignedChunkWriter,
+ TsFileIOWriter tsFileIOWriter,
+ List<TimeRange> pages,
+ boolean isSeq)
+ throws IOException {
+ TimePageWriter timePageWriter =
alignedChunkWriter.getTimeChunkWriter().getPageWriter();
+ for (TimeRange page : pages) {
+ // write time page
+ for (long timestamp = page.getMin(); timestamp <= page.getMax();
timestamp++) {
+ timePageWriter.write(timestamp);
+ }
+ // seal time page
+ alignedChunkWriter.getTimeChunkWriter().sealCurrentPage();
+
+ // write value page
+ for (ValueChunkWriter valueChunkWriter :
alignedChunkWriter.getValueChunkWriterList()) {
+ ValuePageWriter valuePageWriter = valueChunkWriter.getPageWriter();
+ for (long timestamp = page.getMin(); timestamp <= page.getMax();
timestamp++) {
+ writeEmptyAlignedPoint(valuePageWriter, timestamp, isSeq);
+ }
+ // seal sub value page
+ valueChunkWriter.sealCurrentPage();
+ }
+ }
+ // seal time chunk and value chunks
+ alignedChunkWriter.writeToFileWriter(tsFileIOWriter);
+ }
+
+ private void writeEmptyAlignedPoint(
+ ValuePageWriter valuePageWriter, long timestamp, boolean isSeq) {
+ switch (valuePageWriter.getStatistics().getType()) {
+ case TEXT:
+ valuePageWriter.write(
+ timestamp,
+ new Binary(isSeq ? "seqText" : "unSeqText",
TSFileConfig.STRING_CHARSET),
+ true);
+ break;
+ case DOUBLE:
+ valuePageWriter.write(timestamp, isSeq ? timestamp + 0.01 : 100000.01
+ timestamp, true);
+ break;
+ case BOOLEAN:
+ valuePageWriter.write(timestamp, isSeq, true);
+ break;
+ case INT64:
+ valuePageWriter.write(timestamp, isSeq ? timestamp : 100000L +
timestamp, true);
+ break;
+ case INT32:
+ valuePageWriter.write(
+ timestamp, isSeq ? (int) timestamp : (int) (100000 + timestamp),
true);
+ break;
+ case FLOAT:
+ valuePageWriter.write(
+ timestamp, isSeq ? timestamp + (float) 0.1 : (float) (100000.1 +
timestamp), true);
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ "Unknown data type " + valuePageWriter.getStatistics().getType());
+ }
+ }
}
diff --git
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/AlignedTimeSeriesMetadata.java
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/AlignedTimeSeriesMetadata.java
index a512e5f3cfc..b72d2267f18 100644
---
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/AlignedTimeSeriesMetadata.java
+++
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/AlignedTimeSeriesMetadata.java
@@ -155,6 +155,7 @@ public class AlignedTimeSeriesMetadata implements
ITimeSeriesMetadata {
return getAlignedChunkMetadata(timeChunkMetadata, valueChunkMetadataList);
}
+ /** Notice: if all the value chunks is empty chunk, then return empty list.
*/
private List<AlignedChunkMetadata> getAlignedChunkMetadata(
List<IChunkMetadata> timeChunkMetadata, List<List<IChunkMetadata>>
valueChunkMetadataList) {
List<AlignedChunkMetadata> res = new ArrayList<>();
diff --git
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
index dfdbd81c744..396c0a9eead 100644
---
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
+++
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
@@ -2078,7 +2078,8 @@ public class TsFileSequenceReader implements
AutoCloseable {
}
/**
- * Get AlignedChunkMetadata of sensors under one device
+ * Get AlignedChunkMetadata of sensors under one device. Notice: if all the
value chunks is empty
+ * chunk, then return empty list.
*
* @param device device name
*/