You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by zy...@apache.org on 2022/07/19 02:10:16 UTC
[iotdb] branch rel/0.13 updated: [To rel/0.13][IOTDB-3826]Fix duplicate success when concurrent creating same timeseries (#6702)
This is an automated email from the ASF dual-hosted git repository.
zyk pushed a commit to branch rel/0.13
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/rel/0.13 by this push:
new 698d550f51 [To rel/0.13][IOTDB-3826]Fix duplicate success when concurrent creating same timeseries (#6702)
698d550f51 is described below
commit 698d550f517e95171c001bd8f59c7b567d3d21ca
Author: Marcos_Zyk <38...@users.noreply.github.com>
AuthorDate: Tue Jul 19 10:10:09 2022 +0800
[To rel/0.13][IOTDB-3826]Fix duplicate success when concurrent creating same timeseries (#6702)
[To rel/0.13][IOTDB-3826]Fix duplicate success when concurrent creating same timeseries (#6702)
---
.../org/apache/iotdb/db/metadata/mtree/MTree.java | 87 +++++++++++-----------
.../iotdb/db/metadata/MManagerBasicTest.java | 2 +-
.../org/apache/iotdb/db/metadata/MTreeTest.java | 2 +-
3 files changed, 44 insertions(+), 47 deletions(-)
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTree.java b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTree.java
index 3b986e2924..f0501e8048 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTree.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTree.java
@@ -340,55 +340,23 @@ public class MTree implements Serializable {
Map<String, String> props,
String alias)
throws MetadataException {
- String[] nodeNames = path.getNodes();
- if (nodeNames.length <= 2 || !nodeNames[0].equals(root.getName())) {
- throw new IllegalPathException(path.getFullPath());
- }
MetaFormatUtils.checkTimeseries(path);
- IMNode cur = root;
- boolean hasSetStorageGroup = false;
- Template upperTemplate = cur.getSchemaTemplate();
- // e.g, path = root.sg.d1.s1, create internal nodes and set cur to d1 node
- for (int i = 1; i < nodeNames.length - 1; i++) {
- if (cur.isMeasurement()) {
- throw new PathAlreadyExistException(cur.getFullPath());
- }
- if (cur.isStorageGroup()) {
- hasSetStorageGroup = true;
- }
- String childName = nodeNames[i];
-
- // even template not in use, measurement path shall not be conflict with MTree
- if (upperTemplate != null && upperTemplate.getDirectNode(childName) != null) {
- throw new TemplateImcompatibeException(
- path.getFullPath(), upperTemplate.getName(), childName);
- }
-
- if (!cur.hasChild(childName)) {
- if (!hasSetStorageGroup) {
- throw new StorageGroupNotSetException("Storage group should be created first");
- }
-
- cur.addChild(childName, new InternalMNode(cur, childName));
- }
- cur = cur.getChild(childName);
-
- if (cur.getSchemaTemplate() != null) {
- upperTemplate = cur.getSchemaTemplate();
- }
- }
-
- if (cur.isMeasurement()) {
- throw new PathAlreadyExistException(cur.getFullPath());
- }
-
- MetaFormatUtils.checkTimeseriesProps(path.getFullPath(), props);
-
- String leafName = path.getMeasurement();
+ PartialPath devicePath = path.getDevicePath();
+ Pair<IMNode, Template> pair = checkAndAutoCreateInternalPath(devicePath);
+ IMNode cur = pair.left;
+ Template upperTemplate = pair.right;
// synchronize check and add, we need addChild and add Alias become atomic operation
// only write on mtree will be synchronized
synchronized (this) {
+ pair = checkAndAutoCreateDeviceNode(devicePath.getTailNode(), cur, upperTemplate);
+ cur = pair.left;
+ upperTemplate = pair.right;
+
+ MetaFormatUtils.checkTimeseriesProps(path.getFullPath(), props);
+
+ String leafName = path.getMeasurement();
+
if (cur.hasChild(leafName)) {
throw new PathAlreadyExistException(path.getFullPath());
}
@@ -451,6 +419,10 @@ public class MTree implements Serializable {
// synchronize check and add, we need addChild and add Alias become atomic operation
// only write on mtree will be synchronized
synchronized (this) {
+ pair = checkAndAutoCreateDeviceNode(devicePath.getTailNode(), cur, upperTemplate);
+ cur = pair.left;
+ upperTemplate = pair.right;
+
for (String measurement : measurements) {
if (cur.hasChild(measurement)) {
throw new PathAlreadyExistException(devicePath.getFullPath() + "." + measurement);
@@ -499,7 +471,7 @@ public class MTree implements Serializable {
boolean hasSetStorageGroup = false;
Template upperTemplate = cur.getSchemaTemplate();
// e.g, path = root.sg.d1.s1, create internal nodes and set cur to d1 node
- for (int i = 1; i < nodeNames.length; i++) {
+ for (int i = 1; i < nodeNames.length - 1; i++) {
String childName = nodeNames[i];
if (!cur.hasChild(childName)) {
if (!hasSetStorageGroup) {
@@ -528,6 +500,31 @@ public class MTree implements Serializable {
return new Pair<>(cur, upperTemplate);
}
+ private Pair<IMNode, Template> checkAndAutoCreateDeviceNode(
+ String deviceName, IMNode deviceParent, Template upperTemplate)
+ throws PathAlreadyExistException, TemplateImcompatibeException {
+ if (!deviceParent.hasChild(deviceName)) {
+ if (upperTemplate != null && upperTemplate.getDirectNode(deviceName) != null) {
+ throw new TemplateImcompatibeException(
+ deviceParent.getPartialPath().concatNode(deviceName).getFullPath(),
+ upperTemplate.getName(),
+ deviceName);
+ }
+ deviceParent.addChild(deviceName, new InternalMNode(deviceParent, deviceName));
+ }
+ IMNode device = deviceParent.getChild(deviceName);
+
+ if (device.isMeasurement()) {
+ throw new PathAlreadyExistException(device.getFullPath());
+ }
+
+ if (device.getSchemaTemplate() != null) {
+ upperTemplate = device.getSchemaTemplate();
+ }
+
+ return new Pair<>(device, upperTemplate);
+ }
+
/**
* Delete path. The path should be a full path from root to leaf node
*
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
index d167de0f16..64015b72df 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
@@ -1277,7 +1277,7 @@ public class MManagerBasicTest {
fail();
} catch (Exception e) {
assertEquals(
- "Path [root.tree.sg0.GPS.s9] overlaps with [treeTemplate] on [GPS]", e.getMessage());
+ "Path [root.tree.sg0.GPS] overlaps with [treeTemplate] on [GPS]", e.getMessage());
}
CreateTimeSeriesPlan createTimeSeriesPlan4 =
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
index 2842f9ee1f..d6de9bfcda 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
@@ -151,7 +151,7 @@ public class MTreeTest {
Collections.emptyMap(),
null);
} catch (MetadataException e) {
- Assert.assertEquals(String.format("%s is not a legal path", "aa.bb.cc"), e.getMessage());
+ Assert.assertEquals(String.format("%s is not a legal path", "aa.bb"), e.getMessage());
}
}