Skip to content

Commit ddb9c7c

Browse files
authored
[To dev/1.3] Fix pipe schema snapshot database creation (#17944)
* Fix pipe schema snapshot database creation (#17910) * Fix pipe schema snapshot database creation * Fix legacy pipe receiver database conflict handling * Fix pipe enriched config statement execution (cherry picked from commit 98c8234) * Skip unrelated pipe schema snapshot databases
1 parent 458b547 commit ddb9c7c

6 files changed

Lines changed: 131 additions & 10 deletions

File tree

‎iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/pipe/sink/PipeConfigNodeThriftRequestTest.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.iotdb.confignode.manager.pipe.sink.payload.PipeTransferConfigSnapshotPieceReq;
2626
import org.apache.iotdb.confignode.manager.pipe.sink.payload.PipeTransferConfigSnapshotSealReq;
2727
import org.apache.iotdb.confignode.persistence.schema.CNSnapshotFileType;
28+
import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
2829

2930
import org.junit.Assert;
3031
import org.junit.Test;
@@ -97,4 +98,21 @@ public void testPipeTransferConfigSnapshotSealReq() throws IOException {
9798
Assert.assertEquals(req.getFileLengths(), deserializeReq.getFileLengths());
9899
Assert.assertEquals(req.getParameters(), deserializeReq.getParameters());
99100
}
101+
102+
@Test
103+
public void testPipeTransferConfigSnapshotSealReqPreservesPathPattern() throws IOException {
104+
String snapshotName = "cluster_schema.bin";
105+
String templateInfoName = "template_info.bin";
106+
CNSnapshotFileType fileType = CNSnapshotFileType.SCHEMA;
107+
String typeString = "200";
108+
109+
PipeTransferConfigSnapshotSealReq req =
110+
PipeTransferConfigSnapshotSealReq.toTPipeTransferReq(
111+
"root.ln.**", snapshotName, 100, templateInfoName, 10, fileType, typeString);
112+
PipeTransferConfigSnapshotSealReq deserializeReq =
113+
PipeTransferConfigSnapshotSealReq.fromTPipeTransferReq(req);
114+
115+
Assert.assertEquals(
116+
"root.ln.**", deserializeReq.getParameters().get(ColumnHeaderConstant.PATH_PATTERN));
117+
}
100118
}

‎iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/pipe/source/PipeConfigPhysicalPlanPatternParseVisitorTest.java‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,28 @@ public void testCreateDatabase() {
9191
.orElseThrow(AssertionError::new));
9292
}
9393

94+
@Test
95+
public void testCreateDatabaseWithProcess() {
96+
final DatabaseSchemaPlan includedCreateDatabasePlan =
97+
new DatabaseSchemaPlan(
98+
ConfigPhysicalPlanType.CreateDatabase, new TDatabaseSchema("root.ln"));
99+
final DatabaseSchemaPlan excludedCreateDatabasePlan =
100+
new DatabaseSchemaPlan(
101+
ConfigPhysicalPlanType.CreateDatabase, new TDatabaseSchema("root.db"));
102+
final IoTDBPipePatternOperations rootLnPattern =
103+
new UnionIoTDBPipePattern(new IoTDBPipePattern("root.ln.**"));
104+
105+
Assert.assertEquals(
106+
includedCreateDatabasePlan,
107+
IoTDBConfigRegionSource.PATTERN_PARSE_VISITOR
108+
.process(includedCreateDatabasePlan, rootLnPattern)
109+
.orElseThrow(AssertionError::new));
110+
Assert.assertFalse(
111+
IoTDBConfigRegionSource.PATTERN_PARSE_VISITOR
112+
.process(excludedCreateDatabasePlan, rootLnPattern)
113+
.isPresent());
114+
}
115+
94116
@Test
95117
public void testAlterDatabase() {
96118
final DatabaseSchemaPlan alterDatabasePlan =
@@ -201,6 +223,26 @@ public void testCommitSetSchemaTemplate() {
201223
.orElseThrow(AssertionError::new));
202224
}
203225

226+
@Test
227+
public void testCommitSetSchemaTemplateWithRootLnPattern() {
228+
final IoTDBPipePatternOperations rootLnPattern =
229+
new UnionIoTDBPipePattern(new IoTDBPipePattern("root.ln.**"));
230+
final CommitSetSchemaTemplatePlan includedSetTemplatePlan =
231+
new CommitSetSchemaTemplatePlan("t1", "root.ln.wf01");
232+
final CommitSetSchemaTemplatePlan excludedSetTemplatePlan =
233+
new CommitSetSchemaTemplatePlan("t1", "root.db.wf01");
234+
235+
Assert.assertEquals(
236+
includedSetTemplatePlan,
237+
IoTDBConfigRegionSource.PATTERN_PARSE_VISITOR
238+
.process(includedSetTemplatePlan, rootLnPattern)
239+
.orElseThrow(AssertionError::new));
240+
Assert.assertFalse(
241+
IoTDBConfigRegionSource.PATTERN_PARSE_VISITOR
242+
.process(excludedSetTemplatePlan, rootLnPattern)
243+
.isPresent());
244+
}
245+
204246
@Test
205247
public void testPipeUnsetSchemaTemplate() {
206248
final PipeUnsetSchemaTemplatePlan pipeUnsetSchemaTemplatePlanOnPrefix =

‎iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/legacy/IoTDBLegacyPipeReceiverAgent.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ private boolean registerDatabase(
160160
IoTDBDescriptor.getInstance().getConfig().getQueryTimeoutThreshold(),
161161
false);
162162
if (result.status.code != TSStatusCode.SUCCESS_STATUS.getStatusCode()
163-
&& result.status.code != TSStatusCode.DATABASE_ALREADY_EXISTS.getStatusCode()
164-
&& result.status.code != TSStatusCode.DATABASE_CONFLICT.getStatusCode()) {
163+
&& result.status.code != TSStatusCode.DATABASE_ALREADY_EXISTS.getStatusCode()) {
165164
LOGGER.error(
166165
"Create Database error, statement: {}, result status : {}.", statement, result.status);
167166
return false;

‎iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java‎

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
8484
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
8585
import org.apache.iotdb.db.queryengine.plan.statement.crud.LoadTsFileStatement;
86+
import org.apache.iotdb.db.queryengine.plan.statement.metadata.DatabaseSchemaStatement;
8687
import org.apache.iotdb.db.queryengine.plan.statement.pipe.PipeEnrichedStatement;
8788
import org.apache.iotdb.db.storageengine.load.active.ActiveLoadPathHelper;
8889
import org.apache.iotdb.db.storageengine.load.active.ActiveLoadUtil;
@@ -536,17 +537,29 @@ static LoadTsFileStatement buildLoadTsFileStatementForSync(
536537
private TSStatus loadSchemaSnapShot(
537538
final Map<String, String> parameters, final List<String> fileAbsolutePaths)
538539
throws IllegalPathException, IOException {
540+
final String databaseName = parameters.get(ColumnHeaderConstant.DATABASE);
541+
final PartialPath databasePath = new PartialPath(databaseName);
542+
543+
final String pathPattern = parameters.get(ColumnHeaderConstant.PATH_PATTERN);
544+
if (!shouldLoadSchemaSnapshotDatabase(pathPattern, databaseName)) {
545+
return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
546+
}
547+
final PipePattern pipePattern =
548+
PipePattern.parsePatternFromString(pathPattern, IoTDBPipePattern::new);
549+
550+
final TSStatus createDatabaseStatus = createSchemaSnapshotDatabaseIfNecessary(databasePath);
551+
if (createDatabaseStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
552+
return createDatabaseStatus;
553+
}
554+
539555
final SRStatementGenerator generator =
540556
SchemaRegionSnapshotParser.translate2Statements(
541557
Paths.get(fileAbsolutePaths.get(0)),
542558
fileAbsolutePaths.size() > 1 ? Paths.get(fileAbsolutePaths.get(1)) : null,
543-
new PartialPath(parameters.get(ColumnHeaderConstant.DATABASE)));
559+
databasePath);
544560
final Set<StatementType> executionTypes =
545561
PipeSchemaRegionSnapshotEvent.getStatementTypeSet(
546562
parameters.get(ColumnHeaderConstant.TYPE));
547-
final PipePattern pipePattern =
548-
PipePattern.parsePatternFromString(
549-
parameters.get(ColumnHeaderConstant.PATH_PATTERN), IoTDBPipePattern::new);
550563

551564
// Clear to avoid previous exceptions
552565
batchVisitor.clear();
@@ -571,6 +584,39 @@ private TSStatus loadSchemaSnapShot(
571584
return PipeReceiverStatusHandler.getPriorStatus(results);
572585
}
573586

587+
static boolean shouldLoadSchemaSnapshotDatabase(
588+
final String pathPattern, final String databaseName) {
589+
return PipePattern.parsePatternFromString(pathPattern, IoTDBPipePattern::new)
590+
.mayOverlapWithDb(databaseName);
591+
}
592+
593+
private TSStatus createSchemaSnapshotDatabaseIfNecessary(final PartialPath databasePath) {
594+
final DatabaseSchemaStatement statement =
595+
new DatabaseSchemaStatement(DatabaseSchemaStatement.DatabaseSchemaStatementType.CREATE);
596+
statement.setDatabasePath(databasePath);
597+
598+
final TSStatus status = executeStatementAndClassifyExceptions(statement);
599+
if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
600+
return status;
601+
}
602+
603+
if (status.getCode() == TSStatusCode.DATABASE_ALREADY_EXISTS.getStatusCode()) {
604+
return Objects.equals(
605+
status.getMessage(),
606+
databasePath.getFullPath() + " has already been created as database")
607+
? RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS)
608+
: new TSStatus(TSStatusCode.PIPE_RECEIVER_USER_CONFLICT_EXCEPTION.getStatusCode())
609+
.setMessage(status.getMessage());
610+
}
611+
612+
if (status.getCode() == TSStatusCode.DATABASE_CONFLICT.getStatusCode()) {
613+
return new TSStatus(TSStatusCode.PIPE_RECEIVER_USER_CONFLICT_EXCEPTION.getStatusCode())
614+
.setMessage(status.getMessage());
615+
}
616+
617+
return status;
618+
}
619+
574620
private TPipeTransferResp handleTransferSchemaPlan(final PipeTransferPlanNodeReq req) {
575621
// We may be able to skip the alter logical view's exception parsing because
576622
// the "AlterLogicalViewNode" is itself idempotent

‎iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.iotdb.db.queryengine.plan.planner.TreeModelPlanner;
4949
import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement;
5050
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
51+
import org.apache.iotdb.db.queryengine.plan.statement.pipe.PipeEnrichedStatement;
5152
import org.apache.iotdb.db.utils.SetThreadName;
5253

5354
import org.slf4j.Logger;
@@ -208,13 +209,19 @@ private IQueryExecution createQueryExecutionForTreeModel(
208209
long startTime) {
209210
queryContext.setTimeOut(timeOut);
210211
queryContext.setStartTime(startTime);
211-
if (statement instanceof IConfigStatement) {
212-
queryContext.setQueryType(((IConfigStatement) statement).getQueryType());
212+
final Statement configStatement =
213+
statement instanceof PipeEnrichedStatement
214+
&& ((PipeEnrichedStatement) statement).getInnerStatement()
215+
instanceof IConfigStatement
216+
? ((PipeEnrichedStatement) statement).getInnerStatement()
217+
: statement;
218+
if (configStatement instanceof IConfigStatement) {
219+
queryContext.setQueryType(((IConfigStatement) configStatement).getQueryType());
213220
return new ConfigExecution(
214221
queryContext,
215-
statement.getType(),
222+
configStatement.getType(),
216223
executor,
217-
statement.accept(new ConfigTaskVisitor(), queryContext));
224+
configStatement.accept(new ConfigTaskVisitor(), queryContext));
218225
}
219226
TreeModelPlanner treeModelPlanner =
220227
new TreeModelPlanner(

‎iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiverTest.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ public void testRepeatedStatementExceptionLogIsReduced() throws Exception {
110110
}
111111
}
112112

113+
@Test
114+
public void testSchemaSnapshotDatabaseIsFilteredByPattern() {
115+
Assert.assertTrue(
116+
IoTDBDataNodeReceiver.shouldLoadSchemaSnapshotDatabase("root.ln.**", "root.ln"));
117+
Assert.assertTrue(IoTDBDataNodeReceiver.shouldLoadSchemaSnapshotDatabase("root.**", "root.db"));
118+
Assert.assertFalse(
119+
IoTDBDataNodeReceiver.shouldLoadSchemaSnapshotDatabase("root.ln.**", "root.db"));
120+
}
121+
113122
@Test
114123
public void testLoadTsFileSyncStatementVerifiesSchemaWhenConvertingType() throws Exception {
115124
final Path tsFile = Files.createTempFile("pipe-load-convert-verify-schema", ".tsfile");

0 commit comments

Comments
 (0)