You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ne...@apache.org on 2022/08/03 02:52:45 UTC
[iotdb] branch master updated: [IOTDB-3280] Can not set ttl to all sg in cli with one sql (#6842)
This is an automated email from the ASF dual-hosted git repository.
neuyilan 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 e84b1e3185 [IOTDB-3280] Can not set ttl to all sg in cli with one sql (#6842)
e84b1e3185 is described below
commit e84b1e318590ed51e4f2df9e5e92cb7cacebf171
Author: 23931017wu <71...@users.noreply.github.com>
AuthorDate: Wed Aug 3 10:52:39 2022 +0800
[IOTDB-3280] Can not set ttl to all sg in cli with one sql (#6842)
---
.../consensus/request/write/SetTTLPlan.java | 29 ++-
.../confignode/manager/ClusterSchemaManager.java | 52 ++--
.../persistence/schema/ClusterSchemaInfo.java | 34 ++-
.../thrift/ConfigNodeRPCServiceProcessor.java | 2 +-
.../request/ConfigPhysicalPlanSerDeTest.java | 2 +-
.../thrift/ConfigNodeRPCServiceProcessorTest.java | 6 +-
docs/UserGuide/Operate-Metadata/TTL.md | 21 +-
docs/zh/UserGuide/Operate-Metadata/TTL.md | 18 ++
.../java/org/apache/iotdb/db/it/IoTDBTtlIT.java | 269 +++++++++++++++++++++
.../apache/iotdb/db/integration/IoTDBTtlIT.java | 130 ++++++++++
.../apache/iotdb/db/engine/StorageEngineV2.java | 17 +-
.../config/executor/ClusterConfigTaskExecutor.java | 8 +-
thrift-commons/src/main/thrift/common.thrift | 10 +-
thrift/src/main/thrift/datanode.thrift | 3 +-
14 files changed, 553 insertions(+), 48 deletions(-)
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/SetTTLPlan.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/SetTTLPlan.java
index e49b3403a7..10c4bc3f1e 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/SetTTLPlan.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/SetTTLPlan.java
@@ -25,11 +25,13 @@ import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
public class SetTTLPlan extends ConfigPhysicalPlan {
- private String storageGroup;
+ private String[] storageGroupPathPattern;
private long TTL;
@@ -37,14 +39,14 @@ public class SetTTLPlan extends ConfigPhysicalPlan {
super(ConfigPhysicalPlanType.SetTTL);
}
- public SetTTLPlan(String storageGroup, long TTL) {
+ public SetTTLPlan(List<String> storageGroupPathPattern, long TTL) {
this();
- this.storageGroup = storageGroup;
+ this.storageGroupPathPattern = storageGroupPathPattern.toArray(new String[0]);
this.TTL = TTL;
}
- public String getStorageGroup() {
- return storageGroup;
+ public String[] getStorageGroupPathPattern() {
+ return storageGroupPathPattern;
}
public long getTTL() {
@@ -55,13 +57,21 @@ public class SetTTLPlan extends ConfigPhysicalPlan {
protected void serializeImpl(DataOutputStream stream) throws IOException {
stream.writeInt(getType().ordinal());
- BasicStructureSerDeUtil.write(storageGroup, stream);
+ stream.writeInt(storageGroupPathPattern.length);
+ for (String node : storageGroupPathPattern) {
+ BasicStructureSerDeUtil.write(node, stream);
+ }
stream.writeLong(TTL);
}
@Override
protected void deserializeImpl(ByteBuffer buffer) throws IOException {
- storageGroup = BasicStructureSerDeUtil.readString(buffer);
+
+ int length = buffer.getInt();
+ storageGroupPathPattern = new String[length];
+ for (int i = 0; i < length; i++) {
+ storageGroupPathPattern[i] = BasicStructureSerDeUtil.readString(buffer);
+ }
TTL = buffer.getLong();
}
@@ -70,11 +80,12 @@ public class SetTTLPlan extends ConfigPhysicalPlan {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SetTTLPlan setTTLPlan = (SetTTLPlan) o;
- return TTL == setTTLPlan.TTL && storageGroup.equals(setTTLPlan.storageGroup);
+ return TTL == setTTLPlan.TTL
+ && Arrays.equals(this.storageGroupPathPattern, setTTLPlan.storageGroupPathPattern);
}
@Override
public int hashCode() {
- return Objects.hash(storageGroup, TTL);
+ return Objects.hash(storageGroupPathPattern, TTL);
}
}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java
index 8312b72835..608b9b735b 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterSchemaManager.java
@@ -25,6 +25,7 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
import org.apache.iotdb.common.rpc.thrift.TSetTTLReq;
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.confignode.client.DataNodeRequestType;
import org.apache.iotdb.confignode.client.async.datanode.AsyncDataNodeClientPool;
import org.apache.iotdb.confignode.client.sync.datanode.SyncDataNodeClientPool;
@@ -153,37 +154,54 @@ public class ClusterSchemaManager {
}
/**
- * Update TTL for the specific StorageGroup
+ * Update TTL for the specific StorageGroup or all storage groups in a path
*
* @param setTTLPlan setTTLPlan
- * @return SUCCESS_STATUS if successfully update the TTL, STORAGE_GROUP_NOT_EXIST if the specific
- * StorageGroup doesn't exist
+ * @return SUCCESS_STATUS if successfully update the TTL, STORAGE_GROUP_NOT_EXIST if the path
+ * doesn't exist
*/
public TSStatus setTTL(SetTTLPlan setTTLPlan) {
- if (!getStorageGroupNames().contains(setTTLPlan.getStorageGroup())) {
+ Map<String, TStorageGroupSchema> storageSchemaMap =
+ clusterSchemaInfo.getMatchedStorageGroupSchemasByOneName(
+ setTTLPlan.getStorageGroupPathPattern());
+
+ if (storageSchemaMap.isEmpty()) {
return RpcUtils.getStatus(
TSStatusCode.STORAGE_GROUP_NOT_EXIST,
- "storageGroup " + setTTLPlan.getStorageGroup() + " does not exist");
+ "Path [" + new PartialPath(setTTLPlan.getStorageGroupPathPattern()) + "] does not exist");
+ }
+ Map<Integer, TDataNodeLocation> dataNodeLocationMaps = new ConcurrentHashMap<>();
+ Map<Integer, List<String>> dnlToSgMap = new ConcurrentHashMap<>();
+ for (String storageGroup : storageSchemaMap.keySet()) {
+
+ Set<TDataNodeLocation> dataNodeLocations =
+ getPartitionManager()
+ .getStorageGroupRelatedDataNodes(storageGroup, TConsensusGroupType.DataRegion);
+ for (TDataNodeLocation dataNodeLocation : dataNodeLocations) {
+ if (!dataNodeLocationMaps.containsKey(dataNodeLocation.getDataNodeId())) {
+ dataNodeLocationMaps.put(dataNodeLocation.getDataNodeId(), dataNodeLocation);
+ List<String> storageGroups = new ArrayList<>();
+ storageGroups.add(storageGroup);
+ dnlToSgMap.put(dataNodeLocation.getDataNodeId(), storageGroups);
+ } else {
+ List<String> storagegroups = dnlToSgMap.get(dataNodeLocation.getDataNodeId());
+ storagegroups.add(storageGroup);
+ dnlToSgMap.put(dataNodeLocation.getDataNodeId(), storagegroups);
+ }
+ }
}
- Map<Integer, TDataNodeLocation> dataNodeLocationMap = new ConcurrentHashMap<>();
- Set<TDataNodeLocation> dataNodeLocations =
- getPartitionManager()
- .getStorageGroupRelatedDataNodes(
- setTTLPlan.getStorageGroup(), TConsensusGroupType.DataRegion);
- dataNodeLocations.forEach(
- dataNodeLocation ->
- dataNodeLocationMap.put(dataNodeLocation.getDataNodeId(), dataNodeLocation));
- if (dataNodeLocations.size() > 0) {
- // TODO: Use procedure to protect SetTTL on DataNodes
+
+ for (Map.Entry<Integer, List<String>> entry : dnlToSgMap.entrySet()) {
+ Map<Integer, TDataNodeLocation> dataNodeLocationMap = new ConcurrentHashMap<>();
+ dataNodeLocationMap.put(entry.getKey(), dataNodeLocationMaps.get(entry.getKey()));
AsyncDataNodeClientPool.getInstance()
.sendAsyncRequestToDataNodeWithRetry(
- new TSetTTLReq(setTTLPlan.getStorageGroup(), setTTLPlan.getTTL()),
+ new TSetTTLReq(entry.getValue(), setTTLPlan.getTTL()),
dataNodeLocationMap,
DataNodeRequestType.SET_TTL,
null);
}
-
return getConsensusManager().write(setTTLPlan).getStatus();
}
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
index 3407fd199c..624b2d5bf4 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java
@@ -213,12 +213,15 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
TSStatus result = new TSStatus();
storageGroupReadWriteLock.writeLock().lock();
try {
- PartialPath path = new PartialPath(plan.getStorageGroup());
- if (mTree.isStorageGroupAlreadySet(path)) {
- mTree
- .getStorageGroupNodeByStorageGroupPath(path)
- .getStorageGroupSchema()
- .setTTL(plan.getTTL());
+ PartialPath patternPath = new PartialPath(plan.getStorageGroupPathPattern());
+ List<PartialPath> matchedPaths = mTree.getBelongedStorageGroups(patternPath);
+ if (matchedPaths.size() != 0) {
+ for (PartialPath path : matchedPaths) {
+ mTree
+ .getStorageGroupNodeByStorageGroupPath(path)
+ .getStorageGroupSchema()
+ .setTTL(plan.getTTL());
+ }
result.setCode(TSStatusCode.SUCCESS_STATUS.getStatusCode());
} else {
result.setCode(TSStatusCode.STORAGE_GROUP_NOT_EXIST.getStatusCode());
@@ -691,6 +694,25 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
return new AllTemplateSetInfoResp(outputStream.toByteArray());
}
+ public Map<String, TStorageGroupSchema> getMatchedStorageGroupSchemasByOneName(
+ String[] storageGroupPathPattern) {
+ Map<String, TStorageGroupSchema> schemaMap = new HashMap<>();
+ storageGroupReadWriteLock.readLock().lock();
+ try {
+ PartialPath patternPath = new PartialPath(storageGroupPathPattern);
+ List<PartialPath> matchedPaths = mTree.getBelongedStorageGroups(patternPath);
+ for (PartialPath path : matchedPaths) {
+ schemaMap.put(
+ path.getFullPath(), mTree.getStorageGroupNodeByPath(path).getStorageGroupSchema());
+ }
+ } catch (MetadataException e) {
+ LOGGER.warn("Error StorageGroup name", e);
+ } finally {
+ storageGroupReadWriteLock.readLock().unlock();
+ }
+ return schemaMap;
+ }
+
@TestOnly
public void clear() {
mTree.clear();
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index e0cfbfbd79..6c5aa24a89 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -236,7 +236,7 @@ public class ConfigNodeRPCServiceProcessor implements IConfigNodeRPCService.Ifac
@Override
public TSStatus setTTL(TSetTTLReq req) throws TException {
- return configManager.setTTL(new SetTTLPlan(req.getStorageGroup(), req.getTTL()));
+ return configManager.setTTL(new SetTTLPlan(req.getStorageGroupPathPattern(), req.getTTL()));
}
@Override
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
index 71cf569c19..64a2ec3472 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
@@ -146,7 +146,7 @@ public class ConfigPhysicalPlanSerDeTest {
@Test
public void SetTTLPlanTest() throws IOException {
- SetTTLPlan req0 = new SetTTLPlan("root.sg0", Long.MAX_VALUE);
+ SetTTLPlan req0 = new SetTTLPlan(Arrays.asList("root", "sg0"), Long.MAX_VALUE);
SetTTLPlan req1 = (SetTTLPlan) ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
}
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
index 88b537c218..1506a6ea00 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
@@ -251,7 +251,7 @@ public class ConfigNodeRPCServiceProcessorTest {
}
@Test
- public void testSetAndQueryStorageGroup() throws TException {
+ public void testSetAndQueryStorageGroup() throws IllegalPathException, TException {
TSStatus status;
final String sg0 = "root.sg0";
final String sg1 = "root.sg1";
@@ -315,7 +315,9 @@ public class ConfigNodeRPCServiceProcessorTest {
TSStatusCode.STORAGE_GROUP_ALREADY_EXISTS.getStatusCode(), status.getCode());
// test StorageGroup setter interfaces
- status = processor.setTTL(new TSetTTLReq(sg1, Long.MAX_VALUE));
+ PartialPath patternPath = new PartialPath(sg1);
+ status =
+ processor.setTTL(new TSetTTLReq(Arrays.asList(patternPath.getNodes()), Long.MAX_VALUE));
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
status = processor.setSchemaReplicationFactor(new TSetSchemaReplicationFactorReq(sg1, 1));
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), status.getCode());
diff --git a/docs/UserGuide/Operate-Metadata/TTL.md b/docs/UserGuide/Operate-Metadata/TTL.md
index 5e41403ee4..52d16072f6 100644
--- a/docs/UserGuide/Operate-Metadata/TTL.md
+++ b/docs/UserGuide/Operate-Metadata/TTL.md
@@ -33,6 +33,15 @@ IoTDB> set ttl to root.ln 3600000
This example means that for data in `root.ln`, only that of the latest 1 hour will remain, the older one is removed or made invisible.
+```
+IoTDB> set ttl to root.sgcc.** 3600000
+```
+It supports setting TTL for storage groups in a path. This example represents setting TTL for all storage groups in the `root.sgcc` path.
+```
+IoTDB> set ttl to root.** 3600000
+```
+This example represents setting TTL for all storage groups.
+
## Unset TTL
To unset TTL, we can use follwing SQL statement:
@@ -41,7 +50,17 @@ To unset TTL, we can use follwing SQL statement:
IoTDB> unset ttl to root.ln
```
-After unset TTL, all data will be accepted in `root.ln`
+After unset TTL, all data will be accepted in `root.ln`.
+```
+IoTDB> unset ttl to root.sgcc.**
+```
+
+Unset the TTL setting for all storage groups in the `root.sgcc` path.
+```
+IoTDB> unset ttl to root.**
+```
+
+Unset the TTL setting for all storage groups.
## Show TTL
diff --git a/docs/zh/UserGuide/Operate-Metadata/TTL.md b/docs/zh/UserGuide/Operate-Metadata/TTL.md
index 49888db8a1..4f76e0b153 100644
--- a/docs/zh/UserGuide/Operate-Metadata/TTL.md
+++ b/docs/zh/UserGuide/Operate-Metadata/TTL.md
@@ -32,6 +32,14 @@ IoTDB 支持对存储组级别设置数据存活时间(TTL),这使得 IoTD
IoTDB> set ttl to root.ln 3600000
```
这个例子表示在`root.ln`存储组中,只有最近一个小时的数据将会保存,旧数据会被移除或不可见。
+```
+IoTDB> set ttl to root.sgcc.** 3600000
+```
+支持给某一路径下的存储组设置TTL,这个例子表示`root.sgcc`路径下的所有存储组设置TTL。
+```
+IoTDB> set ttl to root.** 3600000
+```
+表示给所有存储组设置TTL。
## 取消 TTL
@@ -42,6 +50,16 @@ IoTDB> unset ttl to root.ln
```
取消设置 TTL 后,存储组`root.ln`中所有的数据都会被保存。
+```
+IoTDB> unset ttl to root.sgcc.**
+```
+
+取消设置`root.sgcc`路径下的所有存储组的 TTL 。
+```
+IoTDB> unset ttl to root.**
+```
+
+取消设置所有存储组的 TTL 。
## 显示 TTL
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBTtlIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBTtlIT.java
new file mode 100644
index 0000000000..7a82539d13
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBTtlIT.java
@@ -0,0 +1,269 @@
+/*
+ * 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.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+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.SQLException;
+import java.sql.Statement;
+
+import static org.junit.Assert.*;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({ClusterIT.class})
+public class IoTDBTtlIT {
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv().initBeforeClass();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanAfterClass();
+ }
+
+ @Test
+ public void testTTL() throws SQLException, InterruptedException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ try {
+ statement.execute("SET TTL TO root.TTL_SG1 1000");
+ } catch (SQLException e) {
+ assertEquals(322, e.getErrorCode());
+ }
+ try {
+ statement.execute("UNSET TTL TO root.TTL_SG1");
+ } catch (SQLException e) {
+ assertEquals(322, e.getErrorCode());
+ }
+
+ statement.execute("SET STORAGE GROUP TO root.TTL_SG1");
+ statement.execute("CREATE TIMESERIES root.TTL_SG1.s1 WITH DATATYPE=INT64,ENCODING=PLAIN");
+ try {
+ statement.execute("SET TTL TO root.TTL_SG1.s1 1000");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+
+ statement.execute("SET STORAGE GROUP TO root.TTL_SG2");
+ statement.execute("CREATE TIMESERIES root.TTL_SG2.s1 WITH DATATYPE=INT64,ENCODING=PLAIN");
+ try {
+ statement.execute("SET TTL TO root.TTL_SG2.s1 1000");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+
+ try {
+ statement.execute("SET TTL TO root.** 1000");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ try {
+ statement.execute("UNSET TTL TO root.**");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+
+ long now = System.currentTimeMillis();
+ for (int i = 0; i < 100; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.TTL_SG1(timestamp, s1) VALUES (%d, %d)", now - 100 + i, i));
+ }
+ for (int i = 0; i < 100; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.TTL_SG1(timestamp, s1) VALUES (%d, %d)", now - 100000 + i, i));
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.TTL_SG1")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+
+ statement.execute("SET TTL TO root.TTL_SG1 10000");
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.TTL_SG1")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(100, cnt);
+ }
+
+ for (int i = 0; i < 100; i++) {
+ boolean caught = false;
+ try {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.TTL_SG1(timestamp, s1) VALUES (%d, %d)", now - 500000 + i, i));
+ } catch (SQLException e) {
+ assertEquals(400, e.getErrorCode());
+ }
+ }
+
+ Thread.sleep(1000);
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.TTL_SG1")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(100, cnt);
+ }
+
+ statement.execute("UNSET TTL TO root.TTL_SG1");
+ // make sure other nodes have applied UNSET TTL
+ Thread.sleep(1000);
+ for (int i = 0; i < 100; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.TTL_SG1(timestamp, s1) VALUES (%d, %d)", now - 30000 + i, i));
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.TTL_SG1")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertTrue(cnt >= 200);
+ }
+ statement.execute("SET STORAGE GROUP TO root.sg.TTL_SG3");
+ statement.execute("SET STORAGE GROUP TO root.sg.TTL_SG4");
+ // SG3
+ for (int i = 0; i < 100; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)", now - 100 + i, i));
+ }
+ for (int i = 100; i < 200; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)",
+ now - 10000000 + i, i));
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.TTL_SG3")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+ // SG4
+ for (int i = 200; i < 300; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)", now - 100 + i, i));
+ }
+ for (int i = 300; i < 400; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)",
+ now - 10000000 + i, i));
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.TTL_SG4")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+
+ statement.execute("SET TTL TO root.sg.** 100000");
+ try (ResultSet resultSet = statement.executeQuery("SELECT * FROM root.sg.**")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+ for (int i = 0; i < 100; i++) {
+ boolean caught = false;
+ try {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)",
+ now - 5000000 + i, i));
+ } catch (SQLException e) {
+ assertEquals(400, e.getErrorCode());
+ }
+ }
+ for (int i = 100; i < 200; i++) {
+ boolean caught = false;
+ try {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)",
+ now - 5000000 + i, i));
+ } catch (SQLException e) {
+ assertEquals(400, e.getErrorCode());
+ }
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.**")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+
+ statement.execute("UNSET TTL TO root.sg.**");
+ // make sure other nodes have applied UNSET TTL
+ Thread.sleep(1000);
+ for (int i = 0; i < 100; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)", now - 30000 + i, i));
+ }
+ for (int i = 100; i < 200; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)", now - 30000 + i, i));
+ }
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.**")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertTrue(cnt >= 400);
+ }
+ }
+ }
+}
diff --git a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java
index bbfd40277e..b935dd4081 100644
--- a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java
+++ b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java
@@ -77,6 +77,31 @@ public class IoTDBTtlIT {
assertEquals(TSStatusCode.STORAGE_GROUP_NOT_EXIST.getStatusCode(), e.getErrorCode());
}
+ statement.execute("SET STORAGE GROUP TO root.TTL_SG2");
+ statement.execute("CREATE TIMESERIES root.TTL_SG2.s1 WITH DATATYPE=INT64,ENCODING=PLAIN");
+ try {
+ statement.execute("SET TTL TO root.TTL_SG2.s1 1000");
+ } catch (SQLException e) {
+ assertEquals(TSStatusCode.STORAGE_GROUP_NOT_EXIST.getStatusCode(), e.getErrorCode());
+ }
+
+ try {
+ statement.execute("SET TTL TO root.** 1000");
+ } catch (SQLException e) {
+ assertEquals(TSStatusCode.TIMESERIES_NOT_EXIST.getStatusCode(), e.getErrorCode());
+ }
+ try {
+ statement.execute("UNSET TTL TO root.**");
+ } catch (SQLException e) {
+ assertEquals(TSStatusCode.TIMESERIES_NOT_EXIST.getStatusCode(), e.getErrorCode());
+ }
+
+ try {
+ statement.execute("SET TTL TO root.**.s1 1000");
+ } catch (SQLException e) {
+ assertEquals(TSStatusCode.STORAGE_GROUP_NOT_EXIST.getStatusCode(), e.getErrorCode());
+ }
+
long now = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
statement.execute(
@@ -141,6 +166,111 @@ public class IoTDBTtlIT {
}
assertTrue(cnt >= 200);
}
+ statement.execute("SET STORAGE GROUP TO root.sg.TTL_SG3");
+ statement.execute("SET STORAGE GROUP TO root.sg.TTL_SG4");
+ // SG2
+ for (int i = 0; i < 100; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)", now - 100 + i, i));
+ }
+ for (int i = 100; i < 200; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)", now - 100000 + i, i));
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.TTL_SG3")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+ // SG1
+ for (int i = 200; i < 300; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)", now - 100 + i, i));
+ }
+ for (int i = 300; i < 400; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)", now - 100000 + i, i));
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.TTL_SG4")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+
+ statement.execute("SET TTL TO root.sg.** 10000");
+ try (ResultSet resultSet = statement.executeQuery("SELECT * FROM root.sg.**")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+ for (int i = 0; i < 100; i++) {
+ boolean caught = false;
+ try {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)",
+ now - 500000 + i, i));
+ } catch (SQLException e) {
+ if (TSStatusCode.OUT_OF_TTL_ERROR.getStatusCode() == e.getErrorCode()) {
+ caught = true;
+ }
+ }
+ assertTrue(caught);
+ }
+ for (int i = 100; i < 200; i++) {
+ boolean caught = false;
+ try {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)",
+ now - 500000 + i, i));
+ } catch (SQLException e) {
+ if (TSStatusCode.OUT_OF_TTL_ERROR.getStatusCode() == e.getErrorCode()) {
+ caught = true;
+ }
+ }
+ assertTrue(caught);
+ }
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.**")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertEquals(200, cnt);
+ }
+
+ statement.execute("UNSET TTL TO root.sg.**");
+ // make sure other nodes have applied UNSET TTL
+ Thread.sleep(1000);
+ for (int i = 0; i < 100; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG3(timestamp, s1) VALUES (%d, %d)", now - 30000 + i, i));
+ }
+ for (int i = 100; i < 200; i++) {
+ statement.execute(
+ String.format(
+ "INSERT INTO root.sg.TTL_SG4(timestamp, s1) VALUES (%d, %d)", now - 30000 + i, i));
+ }
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.sg.**")) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ assertTrue(cnt >= 400);
+ }
}
}
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/StorageEngineV2.java b/server/src/main/java/org/apache/iotdb/db/engine/StorageEngineV2.java
index 72406ea7f9..efb859e1ba 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/StorageEngineV2.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/StorageEngineV2.java
@@ -678,10 +678,25 @@ public class StorageEngineV2 implements IService {
dataRegionMap.put(regionId, newRegion);
}
+ // public TSStatus setTTL(TSetTTLReq req) {
+ // Map<String, List<DataRegionId>> localDataRegionInfo =
+ // StorageEngineV2.getInstance().getLocalDataRegionInfo();
+ // List<DataRegionId> dataRegionIdList = localDataRegionInfo.get(req.storageGroup);
+ // for (DataRegionId dataRegionId : dataRegionIdList) {
+ // DataRegion dataRegion = dataRegionMap.get(dataRegionId);
+ // if (dataRegion != null) {
+ // dataRegion.setDataTTL(req.TTL);
+ // }
+ // }
+ // return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
+ // }
+
public TSStatus setTTL(TSetTTLReq req) {
Map<String, List<DataRegionId>> localDataRegionInfo =
StorageEngineV2.getInstance().getLocalDataRegionInfo();
- List<DataRegionId> dataRegionIdList = localDataRegionInfo.get(req.storageGroup);
+ List<DataRegionId> dataRegionIdList = new ArrayList<>();
+ req.storageGroupPathPattern.forEach(
+ storageGroup -> dataRegionIdList.addAll(localDataRegionInfo.get(storageGroup)));
for (DataRegionId dataRegionId : dataRegionIdList) {
DataRegion dataRegion = dataRegionMap.get(dataRegionId);
if (dataRegion != null) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 104241e811..ee22753c99 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -244,9 +244,9 @@ public class ClusterConfigTaskExecutor implements IConfigTaskExecutor {
@Override
public SettableFuture<ConfigTaskResult> setTTL(SetTTLStatement setTTLStatement, String taskName) {
SettableFuture<ConfigTaskResult> future = SettableFuture.create();
- TSetTTLReq setTTLReq =
- new TSetTTLReq(
- setTTLStatement.getStorageGroupPath().getFullPath(), setTTLStatement.getTTL());
+ List<String> storageGroupPathPattern =
+ Arrays.asList(setTTLStatement.getStorageGroupPath().getNodes());
+ TSetTTLReq setTTLReq = new TSetTTLReq(storageGroupPathPattern, setTTLStatement.getTTL());
try (ConfigNodeClient configNodeClient =
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.partitionRegionId)) {
// Send request to some API server
@@ -258,7 +258,7 @@ public class ClusterConfigTaskExecutor implements IConfigTaskExecutor {
taskName,
setTTLStatement.getStorageGroupPath(),
tsStatus);
- future.setException(new StatementExecutionException(tsStatus));
+ future.setException(new IoTDBException(tsStatus.getMessage(), tsStatus.getCode()));
} else {
future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS));
}
diff --git a/thrift-commons/src/main/thrift/common.thrift b/thrift-commons/src/main/thrift/common.thrift
index fe38f6bd32..5098d9f9ee 100644
--- a/thrift-commons/src/main/thrift/common.thrift
+++ b/thrift-commons/src/main/thrift/common.thrift
@@ -106,13 +106,13 @@ struct TClearCacheReq {
1: optional i32 dataNodeId
}
-struct TSetTTLReq {
- 1: required string storageGroup
- 2: required i64 TTL
-}
-
// for node management
struct TSchemaNode {
1: required string nodeName
2: required byte nodeType
}
+
+struct TSetTTLReq {
+ 1: required list<string> storageGroupPathPattern
+ 2: required i64 TTL
+}
diff --git a/thrift/src/main/thrift/datanode.thrift b/thrift/src/main/thrift/datanode.thrift
index e7941e4e1e..8e62898e25 100644
--- a/thrift/src/main/thrift/datanode.thrift
+++ b/thrift/src/main/thrift/datanode.thrift
@@ -332,9 +332,10 @@ service IDataNodeRPCService {
common.TSStatus flush(common.TFlushReq req)
+ common.TSStatus setTTL(common.TSetTTLReq req)
+
common.TSStatus clearCache(common.TClearCacheReq req)
- common.TSStatus setTTL(common.TSetTTLReq req)
/**
* configNode will notify all DataNodes when the capacity of the ConfigNodeGroup is expanded or reduced
*