From 7cb14e62b59f701b83b0d2713dd5adeb665a389c Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Wed, 8 Jul 2026 17:58:42 +0800 Subject: [PATCH] Fix downgraded resource may not serialize normally --- .../pass/IoTDBRegionMigrateNormalIT.java | 34 +++++++++++++++++++ .../dataregion/tsfile/TsFileResource.java | 10 +++++- .../dataregion/tsfile/TsFileResourceTest.java | 18 ++++++++-- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java index e2d6a9db57ba2..1a0281888004a 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java @@ -21,13 +21,21 @@ import org.apache.iotdb.commons.utils.KillPoint.KillNode; import org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionOperationReliabilityITFramework; +import org.apache.iotdb.it.env.EnvFactory; import org.apache.iotdb.it.framework.IoTDBTestRunner; import org.apache.iotdb.itbase.category.ClusterIT; +import org.junit.Assert; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; + +import static org.apache.iotdb.util.MagicUtils.makeItCloseQuietly; + @Category({ClusterIT.class}) @RunWith(IoTDBTestRunner.class) public class IoTDBRegionMigrateNormalIT extends IoTDBRegionOperationReliabilityITFramework { @@ -40,4 +48,30 @@ public void normal1C2DTest() throws Exception { public void normal3C3DTest() throws Exception { successTest(2, 3, 3, 3, noKillPoints(), noKillPoints(), KillNode.ALL_NODES); } + + @Test + public void migrateRegionWithDegradedTimeIndexTest() throws Exception { + // set TsFileResource memory to 0 to trigger degrading + EnvFactory.getEnv().getConfig().getCommonConfig().setQueryMemoryProportion("1:1:1:1:1:1:0"); + + successTest(1, 1, 1, 2, noKillPoints(), noKillPoints(), KillNode.ALL_NODES); + + try (final Connection connection = makeItCloseQuietly(EnvFactory.getEnv().getConnection()); + final Statement statement = makeItCloseQuietly(connection.createStatement())) { + assertCounts(statement, 1, 1); + statement.execute("INSERT INTO root.sg.d1(timestamp,speed,temperature) values(101, 3, 4)"); + assertCounts(statement, 2, 2); + } + } + + private static void assertCounts( + final Statement statement, final long expectedSpeedCount, final long expectedTemperatureCount) + throws Exception { + try (final ResultSet resultSet = + statement.executeQuery("select count(speed), count(temperature) from root.sg.d1")) { + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(expectedSpeedCount, resultSet.getLong(1)); + Assert.assertEquals(expectedTemperatureCount, resultSet.getLong(2)); + } + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java index 9f344c1994bec..7505b3e406b02 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResource.java @@ -248,7 +248,7 @@ public synchronized void serialize() throws IOException { private void serializeTo(BufferedOutputStream outputStream) throws IOException { ReadWriteIOUtils.write(VERSION_NUMBER, outputStream); - timeIndex.serialize(outputStream); + getTimeIndexForSerialization().serialize(outputStream); ReadWriteIOUtils.write(maxPlanIndex, outputStream); ReadWriteIOUtils.write(minPlanIndex, outputStream); @@ -276,6 +276,14 @@ private void serializeTo(BufferedOutputStream outputStream) throws IOException { ReadWriteIOUtils.write(isGeneratedByPipe, outputStream); } + private ITimeIndex getTimeIndexForSerialization() throws IOException { + if (!(timeIndex instanceof FileTimeIndex) || !resourceFileExists()) { + return timeIndex; + } + + return buildDeviceTimeIndex(); + } + /** deserialize from disk */ public void deserialize() throws IOException { try (InputStream inputStream = fsFactory.getBufferedInputStream(file + RESOURCE_SUFFIX)) { diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResourceTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResourceTest.java index 68ed5ab6e7d99..17da996f6c664 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResourceTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/TsFileResourceTest.java @@ -69,7 +69,7 @@ public void tearDown() throws IOException { if (file.exists()) { FileUtils.delete(file); } - File resourceFile = new File(file.getName() + TsFileResource.RESOURCE_SUFFIX); + File resourceFile = new File(file.getPath() + TsFileResource.RESOURCE_SUFFIX); if (resourceFile.exists()) { FileUtils.delete(resourceFile); } @@ -84,7 +84,21 @@ public void testSerializeAndDeserialize() throws IOException { } @Test - public void testDegradeAndFileTimeIndex() { + public void testSerializeDegradedTimeIndex() throws IOException { + tsFileResource.serialize(); + tsFileResource.degradeTimeIndex(); + + tsFileResource.serialize(); + + TsFileResource derTsFileResource = new TsFileResource(file); + derTsFileResource.deserialize(); + Assert.assertEquals(ITimeIndex.DEVICE_TIME_INDEX_TYPE, derTsFileResource.getTimeIndexType()); + Assert.assertEquals(deviceToIndex.keySet(), derTsFileResource.getDevices()); + } + + @Test + public void testDegradeAndFileTimeIndex() throws IOException { + tsFileResource.serialize(); Assert.assertEquals(ITimeIndex.DEVICE_TIME_INDEX_TYPE, tsFileResource.getTimeIndexType()); tsFileResource.degradeTimeIndex(); Assert.assertEquals(ITimeIndex.FILE_TIME_INDEX_TYPE, tsFileResource.getTimeIndexType());