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());
     }
   }