This is an automated email from the ASF dual-hosted git repository.
CRZbulabula 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 522c31c7750 Display data partition repair progress by providing a new
SQL statement (#17637)
522c31c7750 is described below
commit 522c31c7750df43a83955f9d98cb76118d714342
Author: libo <[email protected]>
AuthorDate: Wed Jul 1 00:21:16 2026 +0800
Display data partition repair progress by providing a new SQL statement
(#17637)
---
...ataPartitionTableIntegrityCheckProcedureIT.java | 36 ++++++
.../org/apache/iotdb/db/qp/sql/IdentifierParser.g4 | 3 +-
.../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 7 +-
.../antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 | 6 +-
.../client/sync/CnToDnSyncRequestType.java | 1 +
.../client/sync/SyncDataNodeClientPool.java | 3 +
.../iotdb/confignode/manager/ConfigManager.java | 14 ++
.../apache/iotdb/confignode/manager/IManager.java | 3 +
.../iotdb/confignode/manager/ProcedureManager.java | 13 ++
.../manager/partition/PartitionManager.java | 16 +++
.../DataPartitionTableIntegrityCheckProcedure.java | 141 +++++++++++++++++++--
.../thrift/ConfigNodeRPCServiceProcessor.java | 6 +
...aPartitionTableIntegrityCheckProcedureTest.java | 13 ++
.../iotdb/db/protocol/client/ConfigNodeClient.java | 9 ++
.../impl/DataNodeInternalRPCServiceImpl.java | 103 +++++++++++----
.../common/header/DatasetHeaderFactory.java | 5 +
.../execution/config/TreeConfigTaskVisitor.java | 9 ++
.../config/executor/ClusterConfigTaskExecutor.java | 22 ++++
.../config/executor/IConfigTaskExecutor.java | 2 +
.../ShowRepairDataPartitionTableProgressTask.java | 72 +++++++++++
.../db/queryengine/plan/parser/ASTVisitor.java | 7 +
.../security/TreeAccessCheckVisitor.java | 11 ++
.../queryengine/plan/statement/StatementType.java | 1 +
.../plan/statement/StatementVisitor.java | 7 +
...wRepairDataPartitionTableProgressStatement.java | 53 ++++++++
.../plan/parser/StatementGeneratorTest.java | 21 +++
.../RepairDataPartitionTableProgressState.java} | 45 ++-----
.../schema/column/ColumnHeaderConstant.java | 11 ++
.../src/main/thrift/confignode.thrift | 9 ++
.../src/main/thrift/datanode.thrift | 13 ++
30 files changed, 588 insertions(+), 74 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/partition/DataPartitionTableIntegrityCheckProcedureIT.java
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/partition/DataPartitionTableIntegrityCheckProcedureIT.java
index e93856cacd1..da54c39479e 100644
---
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/partition/DataPartitionTableIntegrityCheckProcedureIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/partition/DataPartitionTableIntegrityCheckProcedureIT.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.confignode.it.partition;
+import org.apache.iotdb.commons.enums.RepairDataPartitionTableProgressState;
import org.apache.iotdb.it.env.EnvFactory;
import org.apache.iotdb.it.framework.IoTDBTestRunner;
import org.apache.iotdb.itbase.category.ClusterIT;
@@ -34,6 +35,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
@@ -128,4 +130,38 @@ public class DataPartitionTableIntegrityCheckProcedureIT {
Assert.assertEquals(
"The other concurrent submissions should be rejected", threadCount -
1, failCount.get());
}
+
+ @Test
+ public void testShowRepairDataPartitionTableProgress() throws Exception {
+ try (final Connection connection = EnvFactory.getEnv().getConnection();
+ final Statement statement = connection.createStatement()) {
+ assertRepairProgress(statement,
RepairDataPartitionTableProgressState.IDLE.name(), 0.0, 0.0);
+
+ statement.execute("REPAIR DATA PARTITION TABLE");
+ assertRepairProgress(statement, null, 0.0, 100.0);
+ }
+ }
+
+ private static void assertRepairProgress(
+ final Statement statement,
+ final String expectedStatus,
+ final double minProgress,
+ final double maxProgress)
+ throws SQLException {
+ try (final ResultSet resultSet =
+ statement.executeQuery("SHOW REPAIR DATA PARTITION TABLE PROGRESS")) {
+ Assert.assertTrue(resultSet.next());
+ if (expectedStatus != null) {
+ Assert.assertEquals(expectedStatus, resultSet.getString("Status"));
+ } else {
+ Assert.assertNotEquals(
+ RepairDataPartitionTableProgressState.UNKNOWN.name(),
resultSet.getString("Status"));
+ }
+ final double progress = resultSet.getDouble("Progress(%)");
+ Assert.assertTrue(progress >= minProgress);
+ Assert.assertTrue(progress <= maxProgress);
+ Assert.assertNotNull(resultSet.getString("Message"));
+ Assert.assertFalse(resultSet.next());
+ }
+ }
}
diff --git
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4
index e96d84e892c..135b674554b 100644
---
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4
+++
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4
@@ -189,6 +189,7 @@ keyWords
| PRIVILEGES
| PRIVILEGE_VALUE
| PROCESSLIST
+ | PROGRESS
| PROCESSOR
| PROPERTY
| PRUNE
@@ -298,4 +299,4 @@ keyWords
| OPTION
| INF
| CURRENT_TIMESTAMP
- ;
\ No newline at end of file
+ ;
diff --git
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 8a9e6d7d62f..5353535ad34 100644
---
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -96,7 +96,7 @@ utilityStatement
| showQueries | showDiskUsage | showCurrentTimestamp | killQuery |
grantWatermarkEmbedding
| revokeWatermarkEmbedding | loadConfiguration | loadTimeseries | loadFile
| removeFile | unloadFile | setSqlDialect | showCurrentSqlDialect |
showCurrentUser
- | repairDataPartitionTable
+ | repairDataPartitionTable | showRepairDataPartitionTableProgress
;
/**
@@ -1283,6 +1283,11 @@ repairDataPartitionTable
: REPAIR DATA PARTITION TABLE
;
+// Show Repair Data Partition Table Progress
+showRepairDataPartitionTableProgress
+ : SHOW REPAIR DATA PARTITION TABLE PROGRESS
+ ;
+
// Explain
explain
: EXPLAIN (ANALYZE VERBOSE?)? selectStatement?
diff --git
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
index 3950de50ea4..4d915459c39 100644
--- a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
+++ b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4
@@ -1215,6 +1215,10 @@ REPAIR
: R E P A I R
;
+PROGRESS
+ : P R O G R E S S
+ ;
+
SCHEMA_REPLICATION_FACTOR
: S C H E M A '_' R E P L I C A T I O N '_' F A C T O R
;
@@ -1411,4 +1415,4 @@ fragment V: [vV];
fragment W: [wW];
fragment X: [xX];
fragment Y: [yY];
-fragment Z: [zZ];
\ No newline at end of file
+fragment Z: [zZ];
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/CnToDnSyncRequestType.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/CnToDnSyncRequestType.java
index 790fd637d61..ca7fc7a37b2 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/CnToDnSyncRequestType.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/CnToDnSyncRequestType.java
@@ -41,6 +41,7 @@ public enum CnToDnSyncRequestType {
COLLECT_EARLIEST_TIMESLOTS,
GENERATE_DATA_PARTITION_TABLE,
GENERATE_DATA_PARTITION_TABLE_HEART_BEAT,
+ GET_DATA_PARTITION_TABLE_GENERATOR_PROGRESS,
// PartitionCache
INVALIDATE_PARTITION_CACHE,
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncDataNodeClientPool.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncDataNodeClientPool.java
index 14c833fb2fc..f35b6d906a5 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncDataNodeClientPool.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncDataNodeClientPool.java
@@ -151,6 +151,9 @@ public class SyncDataNodeClientPool {
CnToDnSyncRequestType.GENERATE_DATA_PARTITION_TABLE_HEART_BEAT,
(req, client) ->
client.generateDataPartitionTableHeartbeat((TGenerateDataPartitionTableReq)
req));
+ actionMapBuilder.put(
+ CnToDnSyncRequestType.GET_DATA_PARTITION_TABLE_GENERATOR_PROGRESS,
+ (req, client) -> client.getDataPartitionTableGeneratorProgress());
actionMap = actionMapBuilder.build();
}
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index e9647551a30..b11c83d5784 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -47,6 +47,7 @@ import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.conf.ConfigurationFileUtils;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.conf.TrimProperties;
+import org.apache.iotdb.commons.enums.RepairDataPartitionTableProgressState;
import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.path.MeasurementPath;
@@ -238,6 +239,7 @@ import
org.apache.iotdb.confignode.rpc.thrift.TShowDatabaseResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipePluginReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeResp;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowTable4InformationSchemaResp;
@@ -1180,6 +1182,18 @@ public class ConfigManager implements IManager {
return partitionManager.dataPartitionTableIntegrityCheck();
}
+ @Override
+ public TShowRepairDataPartitionTableProgressResp
showRepairDataPartitionTableProgress() {
+ TSStatus status = confirmLeader();
+ if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ return new TShowRepairDataPartitionTableProgressResp(
+ status, RepairDataPartitionTableProgressState.UNKNOWN.name(),
0.0)
+ .setMessage(status.getMessage());
+ }
+
+ return partitionManager.showRepairDataPartitionTableProgress();
+ }
+
private void printNewCreatedDataPartition(
GetOrCreateDataPartitionPlan getOrCreateDataPartitionPlan,
TDataPartitionTableResp resp) {
final String lineSeparator = System.lineSeparator();
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
index fa708dbaeca..1dc097b3444 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/IManager.java
@@ -153,6 +153,7 @@ import
org.apache.iotdb.confignode.rpc.thrift.TShowDatabaseResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipePluginReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeResp;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowTable4InformationSchemaResp;
@@ -480,6 +481,8 @@ public interface IManager {
TSStatus dataPartitionTableIntegrityCheck();
+ TShowRepairDataPartitionTableProgressResp
showRepairDataPartitionTableProgress();
+
/**
* Get AuditLogger.
*
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
index 3d1c860d678..855e9f4a4ed 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
@@ -70,6 +70,7 @@ import
org.apache.iotdb.confignode.procedure.impl.node.AddConfigNodeProcedure;
import org.apache.iotdb.confignode.procedure.impl.node.RemoveAINodeProcedure;
import
org.apache.iotdb.confignode.procedure.impl.node.RemoveConfigNodeProcedure;
import
org.apache.iotdb.confignode.procedure.impl.node.RemoveDataNodesProcedure;
+import
org.apache.iotdb.confignode.procedure.impl.partition.DataPartitionTableIntegrityCheckProcedure;
import
org.apache.iotdb.confignode.procedure.impl.pipe.plugin.CreatePipePluginProcedure;
import
org.apache.iotdb.confignode.procedure.impl.pipe.plugin.DropPipePluginProcedure;
import
org.apache.iotdb.confignode.procedure.impl.pipe.runtime.PipeHandleLeaderChangeProcedure;
@@ -2539,6 +2540,18 @@ public class ProcedureManager {
return false;
}
+ public Optional<DataPartitionTableIntegrityCheckProcedure>
+ getUnfinishedDataPartitionTableIntegrityCheckProcedure() {
+ for (Procedure<ConfigNodeProcedureEnv> procedure :
getExecutor().getProcedures().values()) {
+ if (!procedure.isFinished()
+ && procedure instanceof DataPartitionTableIntegrityCheckProcedure) {
+ return Optional.of((DataPartitionTableIntegrityCheckProcedure)
procedure);
+ }
+ }
+
+ return Optional.empty();
+ }
+
// ======================================================
/*
GET-SET Region
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
index 2bbd0d05381..bb3f288048c 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
@@ -32,6 +32,7 @@ import org.apache.iotdb.commons.concurrent.ThreadName;
import org.apache.iotdb.commons.concurrent.threadpool.ScheduledExecutorUtil;
import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.commons.enums.RepairDataPartitionTableProgressState;
import org.apache.iotdb.commons.partition.DataPartitionTable;
import org.apache.iotdb.commons.partition.SchemaPartitionTable;
import org.apache.iotdb.commons.partition.executor.SeriesPartitionExecutor;
@@ -88,6 +89,7 @@ import
org.apache.iotdb.confignode.rpc.thrift.TGetRegionGroupsByTimeReq;
import org.apache.iotdb.confignode.rpc.thrift.TGetRegionIdReq;
import org.apache.iotdb.confignode.rpc.thrift.TGetSeriesSlotListReq;
import org.apache.iotdb.confignode.rpc.thrift.TGetTimeSlotListReq;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.iotdb.confignode.rpc.thrift.TTimeSlotList;
import org.apache.iotdb.consensus.exception.ConsensusException;
import org.apache.iotdb.mpp.rpc.thrift.TCreateDataRegionReq;
@@ -538,6 +540,20 @@ public class PartitionManager {
dataPartitionTableIntegrityCheckProcedureRunning.set(false);
}
+ public TShowRepairDataPartitionTableProgressResp
showRepairDataPartitionTableProgress() {
+ return configManager
+ .getProcedureManager()
+ .getUnfinishedDataPartitionTableIntegrityCheckProcedure()
+ .map(DataPartitionTableIntegrityCheckProcedure::getProgress)
+ .orElseGet(
+ () ->
+ new TShowRepairDataPartitionTableProgressResp(
+ RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS),
+ RepairDataPartitionTableProgressState.IDLE.name(),
+ 0.0)
+ .setMessage("No running DataPartitionTable integrity check
procedure"));
+ }
+
private TSStatus consensusWritePartitionResult(ConfigPhysicalPlan plan) {
TSStatus status = getConsensusManager().confirmLeader();
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedure.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedure.java
index cc738669e41..50f13039cc6 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedure.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedure.java
@@ -26,6 +26,7 @@ import
org.apache.iotdb.common.rpc.thrift.TSeriesPartitionSlot;
import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
import org.apache.iotdb.commons.cluster.NodeStatus;
import org.apache.iotdb.commons.enums.DataPartitionTableGeneratorState;
+import org.apache.iotdb.commons.enums.RepairDataPartitionTableProgressState;
import org.apache.iotdb.commons.partition.DataPartitionTable;
import org.apache.iotdb.commons.partition.DatabaseScopedDataPartitionTable;
import org.apache.iotdb.commons.partition.SeriesPartitionTable;
@@ -42,11 +43,13 @@ import
org.apache.iotdb.confignode.procedure.exception.ProcedureException;
import org.apache.iotdb.confignode.procedure.impl.StateMachineProcedure;
import
org.apache.iotdb.confignode.procedure.state.DataPartitionTableIntegrityCheckProcedureState;
import org.apache.iotdb.confignode.procedure.store.ProcedureType;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.iotdb.confignode.rpc.thrift.TTimeSlotList;
import
org.apache.iotdb.mpp.rpc.thrift.TGenerateDataPartitionTableHeartbeatResp;
import org.apache.iotdb.mpp.rpc.thrift.TGenerateDataPartitionTableReq;
import org.apache.iotdb.mpp.rpc.thrift.TGenerateDataPartitionTableResp;
import org.apache.iotdb.mpp.rpc.thrift.TGetEarliestTimeslotsResp;
+import org.apache.iotdb.rpc.RpcUtils;
import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.thrift.TException;
@@ -128,6 +131,9 @@ public class DataPartitionTableIntegrityCheckProcedure
// ============Need serialize END=============/
+ private final Map<Integer, Double> dataNodeGeneratorProgress = new
ConcurrentHashMap<>();
+ private volatile Set<Integer> dataNodeGeneratorTargetDataNodeIds =
Collections.emptySet();
+
public DataPartitionTableIntegrityCheckProcedure() {
super();
}
@@ -149,7 +155,7 @@ public class DataPartitionTableIntegrityCheckProcedure
// Ensure to get the real-time DataNodes in the current cluster at every
step
dataNodeManager = env.getConfigManager().getNodeManager();
loadManager = env.getConfigManager().getLoadManager();
- allDataNodes = dataNodeManager.getRegisteredDataNodes();
+ allDataNodes = new ArrayList<>(dataNodeManager.getRegisteredDataNodes());
switch (state) {
case COLLECT_EARLIEST_TIMESLOTS:
@@ -253,8 +259,9 @@ public class DataPartitionTableIntegrityCheckProcedure
}
// Collect earliest timeslots from all DataNodes
- allDataNodes.removeAll(skipDataNodes);
- for (TDataNodeConfiguration dataNode : allDataNodes) {
+ final List<TDataNodeConfiguration> targetDataNodes = new
ArrayList<>(allDataNodes);
+ targetDataNodes.removeAll(skipDataNodes);
+ for (TDataNodeConfiguration dataNode : targetDataNodes) {
// Check if DataNode is alive before sending request
NodeStatus nodeStatus =
loadManager.getNodeStatus(dataNode.getLocation().getDataNodeId());
if (!NodeStatus.Running.equals(nodeStatus)) {
@@ -315,12 +322,12 @@ public class DataPartitionTableIntegrityCheckProcedure
if (LOG.isDebugEnabled()) {
LOG.debug(
"Collected earliest timeslots from {} DataNodes: {}, the number of
successful DataNodes is {}",
- allDataNodes.size(),
+ targetDataNodes.size(),
earliestTimeslots,
- allDataNodes.size() - failedDataNodes.size());
+ targetDataNodes.size() - failedDataNodes.size());
}
- if (failedDataNodes.size() == allDataNodes.size()) {
+ if (countFailedTargetDataNodes(targetDataNodes) == targetDataNodes.size())
{
delayRollbackNextState(
DataPartitionTableIntegrityCheckProcedureState.COLLECT_EARLIEST_TIMESLOTS);
} else {
@@ -454,18 +461,22 @@ public class DataPartitionTableIntegrityCheckProcedure
return Flow.HAS_MORE_STATE;
}
- allDataNodes.removeAll(skipDataNodes);
- allDataNodes.removeAll(failedDataNodes);
- for (TDataNodeConfiguration dataNode : allDataNodes) {
+ final List<TDataNodeConfiguration> targetDataNodes = new
ArrayList<>(allDataNodes);
+ targetDataNodes.removeAll(skipDataNodes);
+ targetDataNodes.removeAll(failedDataNodes);
+ refreshDataNodeGeneratorTarget(targetDataNodes);
+ for (TDataNodeConfiguration dataNode : targetDataNodes) {
int dataNodeId = dataNode.getLocation().getDataNodeId();
// Check if DataNode is alive before sending request
NodeStatus nodeStatus = loadManager.getNodeStatus(dataNodeId);
if (!NodeStatus.Running.equals(nodeStatus)) {
failedDataNodes.add(dataNode);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
continue;
}
if (!dataPartitionTables.containsKey(dataNodeId)) {
+ dataNodeGeneratorProgress.put(dataNodeId, 0.0);
try {
TGenerateDataPartitionTableReq req = new
TGenerateDataPartitionTableReq();
req.setDatabases(databasesWithLostDataPartition);
@@ -479,6 +490,7 @@ public class DataPartitionTableIntegrityCheckProcedure
if (response instanceof TSStatus) {
failedDataNodes.add(dataNode);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
LOG.error(
"[DataPartitionIntegrity] Failed to request DataPartitionTable
generation from the DataNode[id={}], already out of max retry time",
dataNode.getLocation().getDataNodeId());
@@ -488,6 +500,7 @@ public class DataPartitionTableIntegrityCheckProcedure
TGenerateDataPartitionTableResp resp =
(TGenerateDataPartitionTableResp) response;
if (resp.getStatus().getCode() !=
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
failedDataNodes.add(dataNode);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
LOG.error(
"[DataPartitionIntegrity] Failed to request DataPartitionTable
generation from the DataNode[id={}], response status is {}",
dataNode.getLocation().getDataNodeId(),
@@ -495,6 +508,7 @@ public class DataPartitionTableIntegrityCheckProcedure
}
} catch (Exception e) {
failedDataNodes.add(dataNode);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
LOG.error(
"[DataPartitionIntegrity] Failed to request DataPartitionTable
generation from DataNode[id={}]: {}",
dataNodeId,
@@ -504,7 +518,7 @@ public class DataPartitionTableIntegrityCheckProcedure
}
}
- if (failedDataNodes.size() == allDataNodes.size()) {
+ if (countFailedTargetDataNodes(targetDataNodes) == targetDataNodes.size())
{
delayRollbackNextState(
DataPartitionTableIntegrityCheckProcedureState.COLLECT_EARLIEST_TIMESLOTS);
return Flow.HAS_MORE_STATE;
@@ -520,13 +534,19 @@ public class DataPartitionTableIntegrityCheckProcedure
LOG.debug(ProcedureMessages.CHECKING_DATAPARTITIONTABLE_GENERATION_COMPLETION_STATUS);
}
+ final List<TDataNodeConfiguration> targetDataNodes = new
ArrayList<>(allDataNodes);
+ targetDataNodes.removeAll(skipDataNodes);
+ targetDataNodes.removeAll(failedDataNodes);
+ refreshDataNodeGeneratorTarget(targetDataNodes);
+
int completeCount = 0;
- for (TDataNodeConfiguration dataNode : allDataNodes) {
+ for (TDataNodeConfiguration dataNode : targetDataNodes) {
int dataNodeId = dataNode.getLocation().getDataNodeId();
// Check if DataNode is alive before sending request
NodeStatus nodeStatus = loadManager.getNodeStatus(dataNodeId);
if (!NodeStatus.Running.equals(nodeStatus)) {
failedDataNodes.add(dataNode);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
continue;
}
@@ -544,6 +564,7 @@ public class DataPartitionTableIntegrityCheckProcedure
if (response instanceof TSStatus) {
failedDataNodes.add(dataNode);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
LOG.error(
"[DataPartitionIntegrity] Failed to request DataPartitionTable
generation heart beat from the DataNode[id={}], already out of max retry time",
dataNode.getLocation().getDataNodeId());
@@ -570,18 +591,21 @@ public class DataPartitionTableIntegrityCheckProcedure
List<DatabaseScopedDataPartitionTable>
databaseScopedDataPartitionTableList =
deserializeDatabaseScopedTableList(byteBufferList);
dataPartitionTables.put(dataNodeId,
databaseScopedDataPartitionTableList);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
LOG.info(
"[DataPartitionIntegrity] DataNode {} completed
DataPartitionTable generation, terminating heart beat",
dataNodeId);
completeCount++;
break;
case IN_PROGRESS:
+ dataNodeGeneratorProgress.put(dataNodeId,
clampProgress(resp.getProgress()));
LOG.info(
"[DataPartitionIntegrity] DataNode {} still generating
DataPartitionTable",
dataNodeId);
break;
default:
failedDataNodes.add(dataNode);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
LOG.error(
"[DataPartitionIntegrity] DataNode {} returned unknown error
code: {}",
dataNodeId,
@@ -594,21 +618,23 @@ public class DataPartitionTableIntegrityCheckProcedure
dataNodeId,
e.getMessage(),
e);
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
completeCount++;
}
} else {
+ dataNodeGeneratorProgress.put(dataNodeId, 1.0);
completeCount++;
}
}
- if (completeCount >= allDataNodes.size()) {
+ if (completeCount >= targetDataNodes.size()) {
setNextState(DataPartitionTableIntegrityCheckProcedureState.MERGE_PARTITION_TABLES);
return Flow.HAS_MORE_STATE;
}
// Don't find any one data partition table generation task on all
registered DataNodes, go back
// to the REQUEST_PARTITION_TABLES step and re-execute
- if (failedDataNodes.size() == allDataNodes.size()) {
+ if (countFailedTargetDataNodes(targetDataNodes) == targetDataNodes.size())
{
delayRollbackNextState(
DataPartitionTableIntegrityCheckProcedureState.REQUEST_PARTITION_TABLES);
return Flow.HAS_MORE_STATE;
@@ -1114,4 +1140,93 @@ public class DataPartitionTableIntegrityCheckProcedure
public void setFailedDataNodes(Set<TDataNodeConfiguration> failedDataNodes) {
this.failedDataNodes = failedDataNodes;
}
+
+ public TShowRepairDataPartitionTableProgressResp getProgress() {
+ try {
+ final DataPartitionTableIntegrityCheckProcedureState currentState =
getCurrentState();
+ final String state = getProgressStateName(currentState);
+ final double progress =
+ currentState == null ? 0.0 : calculateProgressByState(currentState)
* 100;
+
+ return new TShowRepairDataPartitionTableProgressResp(
+ RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS), state, progress)
+ .setMessage(
+ String.format("DataPartitionTable integrity check progress:
%.1f%%", progress));
+ } catch (Exception e) {
+ LOG.warn("Failed to show DataPartitionTable integrity check progress",
e);
+ return new TShowRepairDataPartitionTableProgressResp(
+ RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS),
+ RepairDataPartitionTableProgressState.UNKNOWN.name(),
+ 0.0)
+ .setMessage("Failed to show DataPartitionTable integrity check
progress");
+ }
+ }
+
+ private double calculateProgressByState(
+ final DataPartitionTableIntegrityCheckProcedureState currentState) {
+ switch (currentState) {
+ case COLLECT_EARLIEST_TIMESLOTS:
+ return 0.0;
+ case ANALYZE_MISSING_PARTITIONS:
+ return 0.05;
+ case REQUEST_PARTITION_TABLES:
+ return 0.1;
+ case REQUEST_PARTITION_TABLES_HEART_BEAT:
+ return 0.1 + 0.8 * calculateDataNodeGeneratorProgress();
+ case MERGE_PARTITION_TABLES:
+ return 0.95;
+ case WRITE_PARTITION_TABLE_TO_CONSENSUS:
+ return 0.99;
+ default:
+ LOG.warn(
+ "Encountered unexpected
DataPartitionTableIntegrityCheckProcedureState {} when showing progress",
+ currentState);
+ return 0.0;
+ }
+ }
+
+ private String getProgressStateName(
+ final DataPartitionTableIntegrityCheckProcedureState currentState) {
+ if (currentState == null) {
+ return RepairDataPartitionTableProgressState.UNKNOWN.name();
+ }
+ try {
+ return
RepairDataPartitionTableProgressState.valueOf(currentState.name()).name();
+ } catch (IllegalArgumentException e) {
+ LOG.warn(
+ "Unexpected DataPartitionTableIntegrityCheckProcedureState {} when
showing progress",
+ currentState);
+ return RepairDataPartitionTableProgressState.UNKNOWN.name();
+ }
+ }
+
+ private double calculateDataNodeGeneratorProgress() {
+ final Set<Integer> currentTargetDataNodeIds =
dataNodeGeneratorTargetDataNodeIds;
+ if (currentTargetDataNodeIds.isEmpty()) {
+ return dataPartitionTables.isEmpty() ? 0.0 : 1.0;
+ }
+
+ double progressSum = 0.0;
+ for (int dataNodeId : currentTargetDataNodeIds) {
+ progressSum +=
clampProgress(dataNodeGeneratorProgress.getOrDefault(dataNodeId, 0.0));
+ }
+ return clampProgress(progressSum / currentTargetDataNodeIds.size());
+ }
+
+ private void refreshDataNodeGeneratorTarget(final
List<TDataNodeConfiguration> targetDataNodes) {
+ final Set<Integer> targetDataNodeIds = new HashSet<>();
+ for (TDataNodeConfiguration dataNode : targetDataNodes) {
+ targetDataNodeIds.add(dataNode.getLocation().getDataNodeId());
+ }
+ dataNodeGeneratorProgress.keySet().retainAll(targetDataNodeIds);
+ dataNodeGeneratorTargetDataNodeIds =
Collections.unmodifiableSet(targetDataNodeIds);
+ }
+
+ private long countFailedTargetDataNodes(final List<TDataNodeConfiguration>
targetDataNodes) {
+ return targetDataNodes.stream().filter(failedDataNodes::contains).count();
+ }
+
+ private double clampProgress(final double progress) {
+ return Math.max(0.0, Math.min(1.0, progress));
+ }
}
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index 5b26a6f7d6d..1d0b7612dbd 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -213,6 +213,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TShowPipeReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionResp;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowTTLResp;
@@ -639,6 +640,11 @@ public class ConfigNodeRPCServiceProcessor implements
IConfigNodeRPCService.Ifac
return configManager.dataPartitionTableIntegrityCheck();
}
+ @Override
+ public TShowRepairDataPartitionTableProgressResp
showRepairDataPartitionTableProgress() {
+ return configManager.showRepairDataPartitionTableProgress();
+ }
+
@Override
public TSStatus operatePermission(final TAuthorizerReq req) {
ConfigPhysicalPlanType configPhysicalPlanType =
diff --git
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedureTest.java
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedureTest.java
index a0cc76fe5c9..4f2fcfe2751 100644
---
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedureTest.java
+++
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/partition/DataPartitionTableIntegrityCheckProcedureTest.java
@@ -23,10 +23,12 @@ import
org.apache.iotdb.common.rpc.thrift.TDataNodeConfiguration;
import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation;
import org.apache.iotdb.common.rpc.thrift.TEndPoint;
import org.apache.iotdb.common.rpc.thrift.TNodeResource;
+import org.apache.iotdb.commons.enums.RepairDataPartitionTableProgressState;
import org.apache.iotdb.commons.partition.DataPartitionTable;
import org.apache.iotdb.commons.partition.DatabaseScopedDataPartitionTable;
import org.apache.iotdb.confignode.procedure.Procedure;
import org.apache.iotdb.confignode.procedure.store.ProcedureFactory;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.tsfile.utils.PublicBAOS;
import org.junit.Assert;
@@ -69,6 +71,17 @@ public class DataPartitionTableIntegrityCheckProcedureTest {
}
}
+ @Test
+ public void progressStateTest() {
+ DataPartitionTableIntegrityCheckProcedure procedure =
+ new DataPartitionTableIntegrityCheckProcedure();
+ TShowRepairDataPartitionTableProgressResp progress =
procedure.getProgress();
+ Assert.assertEquals(
+
RepairDataPartitionTableProgressState.COLLECT_EARLIEST_TIMESLOTS.name(),
+ progress.getState());
+ Assert.assertTrue(progress.getProgress() >= 0.0 && progress.getProgress()
<= 100.0);
+ }
+
private DataPartitionTableIntegrityCheckProcedure
createTestProcedureWithData() {
DataPartitionTableIntegrityCheckProcedure proc =
new DataPartitionTableIntegrityCheckProcedure();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
index ec55111a200..678056fb993 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
@@ -170,6 +170,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TShowPipeReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionResp;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowTTLResp;
@@ -747,6 +748,14 @@ public class ConfigNodeClient implements
IConfigNodeRPCService.Iface, ThriftClie
() -> client.dataPartitionTableIntegrityCheck(), status ->
!updateConfigNodeLeader(status));
}
+ @Override
+ public TShowRepairDataPartitionTableProgressResp
showRepairDataPartitionTableProgress()
+ throws TException {
+ return executeRemoteCallWithRetry(
+ () -> client.showRepairDataPartitionTableProgress(),
+ resp -> !updateConfigNodeLeader(resp.status));
+ }
+
@Override
public TSStatus operatePermission(TAuthorizerReq req) throws TException {
return executeRemoteCallWithRetry(
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
index c588c94c7b5..08fe54cf10d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
@@ -280,6 +280,7 @@ import
org.apache.iotdb.mpp.rpc.thrift.TFragmentInstanceInfoResp;
import
org.apache.iotdb.mpp.rpc.thrift.TGenerateDataPartitionTableHeartbeatResp;
import org.apache.iotdb.mpp.rpc.thrift.TGenerateDataPartitionTableReq;
import org.apache.iotdb.mpp.rpc.thrift.TGenerateDataPartitionTableResp;
+import
org.apache.iotdb.mpp.rpc.thrift.TGetDataPartitionTableGeneratorProgressResp;
import org.apache.iotdb.mpp.rpc.thrift.TGetEarliestTimeslotsResp;
import org.apache.iotdb.mpp.rpc.thrift.TInactiveTriggerInstanceReq;
import org.apache.iotdb.mpp.rpc.thrift.TInvalidateCacheReq;
@@ -3408,13 +3409,14 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
try {
// Check if there's already a task in the progress
- if (currentGenerator != null
- && currentGenerator.getStatus() ==
DataPartitionTableGenerator.TaskStatus.IN_PROGRESS) {
+ final DataPartitionTableGenerator runningGenerator = currentGenerator;
+ if (runningGenerator != null
+ && runningGenerator.getStatus() ==
DataPartitionTableGenerator.TaskStatus.IN_PROGRESS) {
resp.setErrorCode(DataPartitionTableGeneratorState.IN_PROGRESS.getCode());
resp.setMessage(
String.format(
"DataPartitionTable generation is already in the progress:
%.1f%%",
- currentGenerator.getProgress() * 100));
+ runningGenerator.getProgress() * 100));
resp.setStatus(RpcUtils.getStatus(TSStatusCode.INTERNAL_SERVER_ERROR));
return resp;
}
@@ -3436,17 +3438,18 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
ThreadName.DATA_PARTITION_RECOVER_PARALLEL_POOL.getName(),
new ThreadPoolExecutor.CallerRunsPolicy());
- currentGenerator =
+ final DataPartitionTableGenerator generator =
new DataPartitionTableGenerator(
partitionTableRecoverExecutor,
req.getDatabases(),
seriesSlotNum,
seriesPartitionExecutorClass);
+ currentGenerator = generator;
currentTaskId = System.currentTimeMillis();
// Start generation synchronously for now to return the data partition
table immediately
- currentGeneratorFuture = currentGenerator.startGeneration();
- parseGenerationStatus(resp);
+ currentGeneratorFuture = generator.startGeneration();
+ parseGenerationStatus(resp, generator);
} catch (Exception e) {
LOGGER.error(DataNodeMiscMessages.FAILED_GENERATE_DATA_PARTITION_TABLE,
e);
resp.setStatus(
@@ -3470,9 +3473,13 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
try {
// To resolve this situation that the DataNode is registered and didn't
request
// generateDataPartitionTable interface yet.
- if (currentGeneratorFuture == null || currentGenerator == null) {
+ CompletableFuture<Void> generatorFuture = currentGeneratorFuture;
+ DataPartitionTableGenerator generator = currentGenerator;
+ if (generatorFuture == null || generator == null) {
generateDataPartitionTable(req);
- if (currentGeneratorFuture == null || currentGenerator == null) {
+ generatorFuture = currentGeneratorFuture;
+ generator = currentGenerator;
+ if (generatorFuture == null || generator == null) {
resp.setErrorCode(DataPartitionTableGeneratorState.UNKNOWN.getCode());
resp.setMessage(DataNodeMiscMessages.NO_DATA_PARTITION_TABLE_GENERATION_TASK_FOUND);
resp.setStatus(RpcUtils.getStatus(TSStatusCode.INTERNAL_SERVER_ERROR));
@@ -3480,15 +3487,20 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
}
}
- currentGeneratorFuture.get(timeoutMs, TimeUnit.MILLISECONDS);
+ try {
+ generatorFuture.get(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ parseGenerationStatus(resp, generator);
+ return resp;
+ }
- parseGenerationStatus(resp);
- if
(currentGenerator.getStatus().equals(DataPartitionTableGenerator.TaskStatus.COMPLETED))
{
+ parseGenerationStatus(resp, generator);
+ if
(generator.getStatus().equals(DataPartitionTableGenerator.TaskStatus.COMPLETED))
{
boolean success = false;
List<DatabaseScopedDataPartitionTable>
databaseScopedDataPartitionTableList =
new ArrayList<>();
Map<String, DataPartitionTable> dataPartitionTableMap =
- currentGenerator.getDatabasePartitionTableMap();
+ generator.getDatabasePartitionTableMap();
if (!dataPartitionTableMap.isEmpty()) {
for (Map.Entry<String, DataPartitionTable> entry :
dataPartitionTableMap.entrySet()) {
String database = entry.getKey();
@@ -3522,30 +3534,73 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
return resp;
}
- private void parseGenerationStatus(Object resp) {
- if (currentGenerator == null) {
- return;
+ @Override
+ public TGetDataPartitionTableGeneratorProgressResp
getDataPartitionTableGeneratorProgress() {
+ TGetDataPartitionTableGeneratorProgressResp resp =
+ new TGetDataPartitionTableGeneratorProgressResp();
+ final DataPartitionTableGenerator generator = currentGenerator;
+
+ if (generator == null) {
+ resp.setErrorCode(DataPartitionTableGeneratorState.UNKNOWN.getCode());
+ resp.setProgress(0.0);
+ resp.setMessage("No DataPartitionTable generation task found");
+ resp.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
+ return resp;
+ }
+
+ switch (generator.getStatus()) {
+ case IN_PROGRESS:
+
resp.setErrorCode(DataPartitionTableGeneratorState.IN_PROGRESS.getCode());
+ resp.setProgress(generator.getProgress());
+ resp.setMessage(
+ String.format(
+ "DataPartitionTable generation in progress: %.1f%%",
+ generator.getProgress() * 100));
+ resp.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
+ break;
+ case COMPLETED:
+ resp.setErrorCode(DataPartitionTableGeneratorState.SUCCESS.getCode());
+ resp.setProgress(1.0);
+ resp.setMessage("DataPartitionTable generation completed
successfully");
+ resp.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
+ break;
+ case FAILED:
+ resp.setErrorCode(DataPartitionTableGeneratorState.FAILED.getCode());
+ resp.setProgress(generator.getProgress());
+ resp.setMessage("DataPartitionTable generation failed: " +
generator.getErrorMessage());
+ resp.setStatus(RpcUtils.getStatus(TSStatusCode.INTERNAL_SERVER_ERROR));
+ break;
+ default:
+ resp.setErrorCode(DataPartitionTableGeneratorState.UNKNOWN.getCode());
+ resp.setProgress(generator.getProgress());
+ resp.setMessage("Unknown task status: " + generator.getStatus());
+ resp.setStatus(RpcUtils.getStatus(TSStatusCode.INTERNAL_SERVER_ERROR));
+ break;
}
+ return resp;
+ }
- switch (currentGenerator.getStatus()) {
+ private void parseGenerationStatus(Object resp, DataPartitionTableGenerator
generator) {
+ switch (generator.getStatus()) {
case IN_PROGRESS:
setResponseFields(
resp,
DataPartitionTableGeneratorState.IN_PROGRESS.getCode(),
String.format(
- "DataPartitionTable generation in progress: %.1f%%",
- currentGenerator.getProgress() * 100),
+ "DataPartitionTable generation in progress: %.1f%%",
generator.getProgress() * 100),
+ generator.getProgress(),
RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
LOGGER.info(
String.format(
"DataPartitionTable generation with task ID: %s in progress:
%.1f%%",
- currentTaskId, currentGenerator.getProgress() * 100));
+ currentTaskId, generator.getProgress() * 100));
break;
case COMPLETED:
setResponseFields(
resp,
DataPartitionTableGeneratorState.SUCCESS.getCode(),
"DataPartitionTable generation completed successfully",
+ 1.0,
RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
LOGGER.info(DataNodeMiscMessages.DATA_PARTITION_TABLE_COMPLETED,
currentTaskId);
break;
@@ -3553,7 +3608,8 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
setResponseFields(
resp,
DataPartitionTableGeneratorState.FAILED.getCode(),
- "DataPartitionTable generation failed: " +
currentGenerator.getErrorMessage(),
+ "DataPartitionTable generation failed: " +
generator.getErrorMessage(),
+ generator.getProgress(),
RpcUtils.getStatus(TSStatusCode.INTERNAL_SERVER_ERROR));
LOGGER.info(DataNodeMiscMessages.DATA_PARTITION_TABLE_FAILED,
currentTaskId);
break;
@@ -3561,14 +3617,16 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
setResponseFields(
resp,
DataPartitionTableGeneratorState.UNKNOWN.getCode(),
- "Unknown task status: " + currentGenerator.getStatus(),
+ "Unknown task status: " + generator.getStatus(),
+ generator.getProgress(),
RpcUtils.getStatus(TSStatusCode.INTERNAL_SERVER_ERROR));
LOGGER.info(DataNodeMiscMessages.DATA_PARTITION_TABLE_FAILED,
currentTaskId);
break;
}
}
- private void setResponseFields(Object resp, int errorCode, String message,
TSStatus status) {
+ private void setResponseFields(
+ Object resp, int errorCode, String message, double progress, TSStatus
status) {
if (resp instanceof TGenerateDataPartitionTableResp) {
((TGenerateDataPartitionTableResp) resp).setErrorCode(errorCode);
((TGenerateDataPartitionTableResp) resp).setMessage(message);
@@ -3576,6 +3634,7 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
} else if (resp instanceof TGenerateDataPartitionTableHeartbeatResp) {
((TGenerateDataPartitionTableHeartbeatResp)
resp).setErrorCode(errorCode);
((TGenerateDataPartitionTableHeartbeatResp) resp).setMessage(message);
+ ((TGenerateDataPartitionTableHeartbeatResp) resp).setProgress(progress);
((TGenerateDataPartitionTableHeartbeatResp) resp).setStatus(status);
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
index c2a1a9f02d1..e674199df52 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/DatasetHeaderFactory.java
@@ -169,6 +169,11 @@ public class DatasetHeaderFactory {
return new DatasetHeader(ColumnHeaderConstant.showPipeColumnHeaders, true);
}
+ public static DatasetHeader getShowRepairDataPartitionTableProgressHeader() {
+ return new DatasetHeader(
+
ColumnHeaderConstant.showRepairDataPartitionTableProgressColumnHeaders, true);
+ }
+
public static DatasetHeader getShowTopicHeader() {
return new DatasetHeader(ColumnHeaderConstant.showTopicColumnHeaders,
true);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
index 78a0da4dfb5..ef8a5ffcaaa 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
@@ -110,6 +110,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.RepairDataParti
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.SetConfigurationTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.SetSystemStatusTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.ShowConfigurationTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.ShowRepairDataPartitionTableProgressTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.StartRepairDataTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.StopRepairDataTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.TestConnectionTask;
@@ -224,6 +225,7 @@ import
org.apache.iotdb.db.queryengine.plan.statement.sys.SetSystemStatusStateme
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowConfigurationStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentSqlDialectStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentUserStatement;
+import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowRepairDataPartitionTableProgressStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StartRepairDataStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StopRepairDataStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.TestConnectionStatement;
@@ -398,6 +400,13 @@ public class TreeConfigTaskVisitor extends
StatementVisitor<IConfigTask, MPPQuer
return new RepairDataPartitionTableTask();
}
+ @Override
+ public IConfigTask visitShowRepairDataPartitionTableProgress(
+ ShowRepairDataPartitionTableProgressStatement
showRepairDataPartitionTableProgressStatement,
+ MPPQueryContext context) {
+ return new ShowRepairDataPartitionTableProgressTask();
+ }
+
@Override
public IConfigTask visitStopRepairData(
StopRepairDataStatement stopRepairDataStatement, MPPQueryContext
context) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 7efbff455d6..9a31dae2bae 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -171,6 +171,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TShowPipeReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowPipeResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowRegionResp;
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionReq;
import org.apache.iotdb.confignode.rpc.thrift.TShowSubscriptionResp;
import org.apache.iotdb.confignode.rpc.thrift.TShowTTLResp;
@@ -258,6 +259,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.session.ShowCurrent
import
org.apache.iotdb.db.queryengine.plan.execution.config.session.ShowCurrentUserTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.session.ShowVersionTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.ShowConfigurationTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.ShowRepairDataPartitionTableProgressTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.TestConnectionTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.pipe.ShowPipeTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.quota.ShowSpaceQuotaTask;
@@ -1491,6 +1493,26 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
return future;
}
+ @Override
+ public SettableFuture<ConfigTaskResult>
showRepairDataPartitionTableProgress() {
+ SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+
+ try (ConfigNodeClient client =
+
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
+ TShowRepairDataPartitionTableProgressResp resp =
+ client.showRepairDataPartitionTableProgress();
+ if (resp.getStatus().getCode() ==
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ ShowRepairDataPartitionTableProgressTask.buildTsBlock(resp, future);
+ } else {
+ future.setException(new IoTDBException(resp.getStatus()));
+ }
+ } catch (ClientManagerException | TException e) {
+ future.setException(e);
+ }
+
+ return future;
+ }
+
@Override
public SettableFuture<ConfigTaskResult> loadConfiguration(boolean onCluster)
{
SettableFuture<ConfigTaskResult> future = SettableFuture.create();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
index 07f1a30fb19..46f82cefe28 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
@@ -160,6 +160,8 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> repairDataPartitionTable();
+ SettableFuture<ConfigTaskResult> showRepairDataPartitionTableProgress();
+
SettableFuture<ConfigTaskResult> flush(TFlushReq tFlushReq, boolean
onCluster);
SettableFuture<ConfigTaskResult> clearCache(boolean onCluster,
Set<CacheClearOptions> options);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/sys/ShowRepairDataPartitionTableProgressTask.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/sys/ShowRepairDataPartitionTableProgressTask.java
new file mode 100644
index 00000000000..d0ccbaa9f34
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/sys/ShowRepairDataPartitionTableProgressTask.java
@@ -0,0 +1,72 @@
+/*
+ * 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.queryengine.plan.execution.config.sys;
+
+import
org.apache.iotdb.confignode.rpc.thrift.TShowRepairDataPartitionTableProgressResp;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeaderFactory;
+import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult;
+import org.apache.iotdb.db.queryengine.plan.execution.config.IConfigTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.executor.IConfigTaskExecutor;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.apache.tsfile.common.conf.TSFileConfig;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.block.TsBlockBuilder;
+import org.apache.tsfile.utils.Binary;
+
+import java.util.Arrays;
+
+public class ShowRepairDataPartitionTableProgressTask implements IConfigTask {
+
+ public ShowRepairDataPartitionTableProgressTask() {
+ // Empty constructor
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(IConfigTaskExecutor
configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.showRepairDataPartitionTableProgress();
+ }
+
+ public static void buildTsBlock(
+ TShowRepairDataPartitionTableProgressResp resp,
SettableFuture<ConfigTaskResult> future) {
+ TsBlockBuilder builder =
+ new TsBlockBuilder(Arrays.asList(TSDataType.TEXT, TSDataType.DOUBLE,
TSDataType.TEXT));
+
+ builder.getTimeColumnBuilder().writeLong(0L);
+ builder
+ .getColumnBuilder(0)
+ .writeBinary(new Binary(resp.getState(), TSFileConfig.STRING_CHARSET));
+ builder.getColumnBuilder(1).writeDouble(resp.getProgress());
+ builder
+ .getColumnBuilder(2)
+ .writeBinary(
+ new Binary(resp.isSetMessage() ? resp.getMessage() : "",
TSFileConfig.STRING_CHARSET));
+ builder.declarePosition();
+
+ future.set(
+ new ConfigTaskResult(
+ TSStatusCode.SUCCESS_STATUS,
+ builder.build(),
+
DatasetHeaderFactory.getShowRepairDataPartitionTableProgressHeader()));
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
index 083144b0c4e..b8e0aa22b3f 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
@@ -251,6 +251,7 @@ import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentSqlDialectS
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentUserStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowDiskUsageStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement;
+import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowRepairDataPartitionTableProgressStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StartRepairDataStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StopRepairDataStatement;
@@ -3800,6 +3801,12 @@ public class ASTVisitor extends
IoTDBSqlParserBaseVisitor<Statement> {
return new RepairDataPartitionTable();
}
+ @Override
+ public Statement visitShowRepairDataPartitionTableProgress(
+ IoTDBSqlParser.ShowRepairDataPartitionTableProgressContext ctx) {
+ return new ShowRepairDataPartitionTableProgressStatement();
+ }
+
// Stop Repair Data
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
index 41f91bb4618..e3f376deba7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
@@ -160,6 +160,7 @@ import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentSqlDialectS
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentUserStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowDiskUsageStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement;
+import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowRepairDataPartitionTableProgressStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StartRepairDataStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StopRepairDataStatement;
@@ -1810,6 +1811,16 @@ public class TreeAccessCheckVisitor extends
StatementVisitor<TSStatus, TreeAcces
AuditEventType.INTEGRITY_CHECK);
}
+ @Override
+ public TSStatus visitShowRepairDataPartitionTableProgress(
+ ShowRepairDataPartitionTableProgressStatement
showRepairDataPartitionTableProgressStatement,
+ TreeAccessCheckContext context) {
+ return checkGlobalAuth(
+ context.setAuditLogOperation(AuditLogOperation.DDL),
+ PrivilegeType.SYSTEM,
+ AuditEventType.INTEGRITY_CHECK);
+ }
+
@Override
public TSStatus visitStopRepairData(
StopRepairDataStatement stopRepairDataStatement, TreeAccessCheckContext
context) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
index 88a2959f147..00d36a03e23 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementType.java
@@ -182,6 +182,7 @@ public enum StatementType {
START_REPAIR_DATA,
STOP_REPAIR_DATA,
REPAIR_DATA_PARTITION_TABLE,
+ SHOW_REPAIR_DATA_PARTITION_TABLE_PROGRESS,
CREATE_TOPIC,
ALTER_TOPIC,
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java
index 39af259928b..5f2f72f4313 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/StatementVisitor.java
@@ -148,6 +148,7 @@ import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentSqlDialectS
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowCurrentUserStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowDiskUsageStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement;
+import
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowRepairDataPartitionTableProgressStatement;
import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StartRepairDataStatement;
import
org.apache.iotdb.db.queryengine.plan.statement.sys.StopRepairDataStatement;
@@ -527,6 +528,12 @@ public abstract class StatementVisitor<R, C> {
return visitStatement(repairDataPartitionTable, context);
}
+ public R visitShowRepairDataPartitionTableProgress(
+ ShowRepairDataPartitionTableProgressStatement
showRepairDataPartitionTableProgressStatement,
+ C context) {
+ return visitStatement(showRepairDataPartitionTableProgressStatement,
context);
+ }
+
public R visitLoadConfiguration(
LoadConfigurationStatement loadConfigurationStatement, C context) {
return visitStatement(loadConfigurationStatement, context);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/sys/ShowRepairDataPartitionTableProgressStatement.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/sys/ShowRepairDataPartitionTableProgressStatement.java
new file mode 100644
index 00000000000..9de4d4ccca3
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/sys/ShowRepairDataPartitionTableProgressStatement.java
@@ -0,0 +1,53 @@
+/*
+ * 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.queryengine.plan.statement.sys;
+
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.queryengine.plan.analyze.QueryType;
+import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement;
+import org.apache.iotdb.db.queryengine.plan.statement.Statement;
+import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
+import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ShowRepairDataPartitionTableProgressStatement extends Statement
+ implements IConfigStatement {
+
+ public ShowRepairDataPartitionTableProgressStatement() {
+ this.statementType =
StatementType.SHOW_REPAIR_DATA_PARTITION_TABLE_PROGRESS;
+ }
+
+ @Override
+ public List<PartialPath> getPaths() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public QueryType getQueryType() {
+ return QueryType.READ;
+ }
+
+ @Override
+ public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
+ return visitor.visitShowRepairDataPartitionTableProgress(this, context);
+ }
+}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java
index febf29bea15..398797ffca6 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGeneratorTest.java
@@ -1055,6 +1055,27 @@ public class StatementGeneratorTest {
assertEquals(null, stmt.getQueryStatement());
}
+ @Test
+ public void testShowRepairDataPartitionTableProgress() {
+ Statement statement =
+ StatementGenerator.createStatement(
+ "SHOW REPAIR DATA PARTITION TABLE PROGRESS;",
ZonedDateTime.now().getOffset());
+ assertEquals(StatementType.SHOW_REPAIR_DATA_PARTITION_TABLE_PROGRESS,
statement.getType());
+
+ QueryStatement queryStatement =
+ (QueryStatement)
+ StatementGenerator.createStatement(
+ "SELECT progress FROM root.sg.d1;",
ZonedDateTime.now().getOffset());
+ assertEquals(
+ "progress",
+ queryStatement
+ .getSelectComponent()
+ .getResultColumns()
+ .get(0)
+ .getExpression()
+ .getExpressionString());
+ }
+
// TODO: add more tests
private void checkQueryStatement(
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/CnToDnSyncRequestType.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/enums/RepairDataPartitionTableProgressState.java
similarity index 52%
copy from
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/CnToDnSyncRequestType.java
copy to
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/enums/RepairDataPartitionTableProgressState.java
index 790fd637d61..7afa3cbbdc8 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/CnToDnSyncRequestType.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/enums/RepairDataPartitionTableProgressState.java
@@ -17,42 +17,15 @@
* under the License.
*/
-package org.apache.iotdb.confignode.client.sync;
+package org.apache.iotdb.commons.enums;
-public enum CnToDnSyncRequestType {
- // Node Maintenance
- CLEAN_DATA_NODE_CACHE,
- STOP_AND_CLEAR_DATA_NODE,
- SET_SYSTEM_STATUS,
- SHOW_CONFIGURATION,
- SHOW_APPLIED_CONFIGURATIONS,
-
- // Region Maintenance
- CREATE_DATA_REGION,
- CREATE_SCHEMA_REGION,
- DELETE_REGION,
- CREATE_NEW_REGION_PEER,
- ADD_REGION_PEER,
- REMOVE_REGION_PEER,
- DELETE_OLD_REGION_PEER,
- RESET_PEER_LIST,
-
- // Data Partition Table Maintenance
+public enum RepairDataPartitionTableProgressState {
+ UNKNOWN,
+ IDLE,
COLLECT_EARLIEST_TIMESLOTS,
- GENERATE_DATA_PARTITION_TABLE,
- GENERATE_DATA_PARTITION_TABLE_HEART_BEAT,
-
- // PartitionCache
- INVALIDATE_PARTITION_CACHE,
- INVALIDATE_PERMISSION_CACHE,
- INVALIDATE_SCHEMA_CACHE,
-
- // Template
- UPDATE_TEMPLATE,
-
- // Schema
- KILL_QUERY_INSTANCE,
-
- // Table
- UPDATE_TABLE,
+ ANALYZE_MISSING_PARTITIONS,
+ REQUEST_PARTITION_TABLES,
+ REQUEST_PARTITION_TABLES_HEART_BEAT,
+ MERGE_PARTITION_TABLES,
+ WRITE_PARTITION_TABLE_TO_CONSENSUS
}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
index a1c8b6ddd20..18653a52c57 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/column/ColumnHeaderConstant.java
@@ -198,6 +198,11 @@ public class ColumnHeaderConstant {
public static final String ESTIMATED_REMAINING_SECONDS =
"EstimatedRemainingSeconds";
public static final String IS_DEGRADED = "IsDegraded";
+ // column names for show repair data partition table progress
+ public static final String REPAIR_DATA_PARTITION_TABLE_STATUS = "Status";
+ public static final String REPAIR_DATA_PARTITION_TABLE_PROGRESS =
"Progress(%)";
+ public static final String REPAIR_DATA_PARTITION_TABLE_MESSAGE = "Message";
+
// column names for select into
public static final String SOURCE_DEVICE = "SourceDevice";
public static final String SOURCE_COLUMN = "SourceColumn";
@@ -613,6 +618,12 @@ public class ColumnHeaderConstant {
new ColumnHeader(ESTIMATED_REMAINING_SECONDS, TSDataType.TEXT),
new ColumnHeader(IS_DEGRADED, TSDataType.BOOLEAN));
+ public static final List<ColumnHeader>
showRepairDataPartitionTableProgressColumnHeaders =
+ ImmutableList.of(
+ new ColumnHeader(REPAIR_DATA_PARTITION_TABLE_STATUS,
TSDataType.TEXT),
+ new ColumnHeader(REPAIR_DATA_PARTITION_TABLE_PROGRESS,
TSDataType.DOUBLE),
+ new ColumnHeader(REPAIR_DATA_PARTITION_TABLE_MESSAGE,
TSDataType.TEXT));
+
public static final List<ColumnHeader> showTopicColumnHeaders =
ImmutableList.of(
new ColumnHeader(TOPIC_NAME, TSDataType.TEXT),
diff --git a/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift
b/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift
index 1d2241973f7..a414584f80e 100644
--- a/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift
@@ -280,6 +280,13 @@ struct TDataPartitionTableResp {
2: optional map<string, map<common.TSeriesPartitionSlot,
map<common.TTimePartitionSlot, list<common.TConsensusGroupId>>>>
dataPartitionTable
}
+struct TShowRepairDataPartitionTableProgressResp {
+ 1: required common.TSStatus status
+ 2: required string state
+ 3: required double progress
+ 4: optional string message
+}
+
struct TGetRegionIdReq {
1: required common.TConsensusGroupType type
2: optional string database
@@ -1517,6 +1524,8 @@ service IConfigNodeRPCService {
common.TSStatus dataPartitionTableIntegrityCheck()
+ TShowRepairDataPartitionTableProgressResp
showRepairDataPartitionTableProgress()
+
// ======================================================
// Authorize
// ======================================================
diff --git a/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift
b/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift
index b74895260fa..054b1628c6a 100644
--- a/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift
+++ b/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift
@@ -751,6 +751,14 @@ struct TGenerateDataPartitionTableHeartbeatResp {
2: required i32 errorCode
3: optional string message
4: optional list<binary> databaseScopedDataPartitionTables
+ 5: optional double progress
+}
+
+struct TGetDataPartitionTableGeneratorProgressResp {
+ 1: required common.TSStatus status
+ 2: required i32 errorCode
+ 3: required double progress
+ 4: optional string message
}
/**
@@ -1407,6 +1415,11 @@ service IDataNodeRPCService {
*/
TGenerateDataPartitionTableHeartbeatResp
generateDataPartitionTableHeartbeat(TGenerateDataPartitionTableReq req)
+ /**
+ * Get the progress of DataPartitionTable generation task without consuming
the generated table.
+ */
+ TGetDataPartitionTableGeneratorProgressResp
getDataPartitionTableGeneratorProgress()
+
/**
* END: Data Partition Table Integrity Check
**/