This is an automated email from the ASF dual-hosted git repository.

rong 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 56e21e4fee1 support config snapshot parser (#12211)
56e21e4fee1 is described below

commit 56e21e4fee1ff85ba27db904957be3bb742f4cef
Author: Colin Li <[email protected]>
AuthorDate: Fri Mar 22 21:01:11 2024 +0800

    support config snapshot parser (#12211)
---
 .../consensus/request/auth/AuthorPlan.java         |   2 +-
 .../schema/CNPhysicalPlanGenerator.java            | 393 ++++++++++++++++++
 .../persistence/schema/CNSnapshotFileType.java     |  28 ++
 .../schema/ConfignodeSnapshotParser.java           | 168 ++++++++
 .../persistence/CNPhysicalPlanGeneratorTest.java   | 446 +++++++++++++++++++++
 .../db/tools/schema/SRStatementGenerator.java      |  13 +-
 .../db/utils/SchemaRegionSnapshotParserTest.java   |   2 +-
 .../iotdb/commons/auth/entity/PathPrivilege.java   |  41 +-
 .../org/apache/iotdb/commons/auth/entity/Role.java |  63 +--
 .../org/apache/iotdb/commons/utils/AuthUtils.java  |  85 ++++
 10 files changed, 1143 insertions(+), 98 deletions(-)

diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
index fb624ff03ff..61c76320007 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
@@ -290,6 +290,6 @@ public class AuthorPlan extends ConfigPhysicalPlan {
   @Override
   public int hashCode() {
     return Objects.hash(
-        authorType, userName, roleName, password, newPassword, permissions, 
nodeNameList);
+        authorType, userName, roleName, password, newPassword, permissions, 
nodeNameList, grantOpt);
   }
 }
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java
new file mode 100644
index 00000000000..742ad457ed4
--- /dev/null
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java
@@ -0,0 +1,393 @@
+/*
+ * 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.confignode.persistence.schema;
+
+import org.apache.iotdb.commons.auth.entity.PrivilegeType;
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
+import org.apache.iotdb.commons.schema.node.utils.IMNodeFactory;
+import org.apache.iotdb.commons.utils.AuthUtils;
+import org.apache.iotdb.commons.utils.ThriftConfigNodeSerDeUtils;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+import org.apache.iotdb.confignode.consensus.request.auth.AuthorPlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.database.DatabaseSchemaPlan;
+import org.apache.iotdb.confignode.consensus.request.write.database.SetTTLPlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.template.CommitSetSchemaTemplatePlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.template.CreateSchemaTemplatePlan;
+import org.apache.iotdb.confignode.persistence.schema.mnode.IConfigMNode;
+import 
org.apache.iotdb.confignode.persistence.schema.mnode.factory.ConfigMNodeFactory;
+import org.apache.iotdb.db.schemaengine.template.Template;
+import org.apache.iotdb.tsfile.utils.Pair;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_ROOT;
+import static 
org.apache.iotdb.commons.schema.SchemaConstant.INTERNAL_MNODE_TYPE;
+import static 
org.apache.iotdb.commons.schema.SchemaConstant.STORAGE_GROUP_MNODE_TYPE;
+import static org.apache.iotdb.commons.utils.IOUtils.readAuthString;
+import static org.apache.iotdb.commons.utils.IOUtils.readString;
+
+public class CNPhysicalPlanGenerator
+    implements Iterator<ConfigPhysicalPlan>, Iterable<ConfigPhysicalPlan> {
+
+  private final Logger logger = 
LoggerFactory.getLogger(CNPhysicalPlanGenerator.class);
+  private final IMNodeFactory<IConfigMNode> nodeFactory = 
ConfigMNodeFactory.getInstance();
+
+  // File input stream.
+  private InputStream inputStream = null;
+  private InputStream templateInputStream = null;
+
+  private static final String STRING_ENCODING = "utf-8";
+
+  // For default password
+  private static final String DEFAULT_PASSWORD = "password";
+  private final ThreadLocal<byte[]> strBufferLocal = new ThreadLocal<>();
+
+  private final HashMap<Integer, String> templateTable = new HashMap<>();
+
+  // All plan will be stored at this deque
+  private final Deque<ConfigPhysicalPlan> planDeque = new ArrayDeque<>();
+
+  private CNSnapshotFileType snapshotFileType = CNSnapshotFileType.INVALID;
+
+  private Exception latestException = null;
+  private String userName;
+
+  public CNPhysicalPlanGenerator(Path snapshotFilePath, CNSnapshotFileType 
fileType)
+      throws IOException {
+    if (fileType == CNSnapshotFileType.SCHEMA_TEMPLATE) {
+      logger.warn("schema_template need two files");
+      return;
+    }
+    if (fileType == CNSnapshotFileType.USER_ROLE) {
+      userName = 
snapshotFilePath.getFileName().toString().split("_role.profile")[0];
+    }
+    snapshotFileType = fileType;
+    inputStream = Files.newInputStream(snapshotFilePath);
+  }
+
+  public CNPhysicalPlanGenerator(Path schemaInfoFile, Path templateFile) 
throws IOException {
+    inputStream = Files.newInputStream(schemaInfoFile);
+    templateInputStream = Files.newInputStream(templateFile);
+    snapshotFileType = CNSnapshotFileType.SCHEMA_TEMPLATE;
+  }
+
+  @Override
+  public Iterator<ConfigPhysicalPlan> iterator() {
+    return this;
+  }
+
+  @Override
+  public boolean hasNext() {
+    if (!planDeque.isEmpty()) {
+      return true;
+    }
+
+    if (snapshotFileType == CNSnapshotFileType.USER) {
+      generateUserRolePhysicalPlan(true);
+    } else if (snapshotFileType == CNSnapshotFileType.ROLE) {
+      generateUserRolePhysicalPlan(false);
+    } else if (snapshotFileType == CNSnapshotFileType.USER_ROLE) {
+      generateGrantRolePhysicalPlan();
+    } else if (snapshotFileType == CNSnapshotFileType.SCHEMA_TEMPLATE) {
+      generateTemplatePlan();
+      if (latestException != null) {
+        return false;
+      }
+      generateDatabasePhysicalPlan();
+    }
+    snapshotFileType = CNSnapshotFileType.INVALID;
+    try {
+      if (inputStream != null) {
+        inputStream.close();
+        inputStream = null;
+      }
+      if (templateInputStream != null) {
+        templateInputStream.close();
+        templateInputStream = null;
+      }
+    } catch (IOException ioException) {
+      latestException = ioException;
+    }
+
+    if (latestException != null) {
+      return false;
+    }
+    return !planDeque.isEmpty();
+  }
+
+  @Override
+  public ConfigPhysicalPlan next() {
+    if (!hasNext()) {
+      throw new NoSuchElementException();
+    }
+    return planDeque.pop();
+  }
+
+  public void checkException() throws Exception {
+    if (latestException != null) {
+      throw new Exception(latestException.getMessage());
+    }
+  }
+
+  private void generateUserRolePhysicalPlan(boolean isUser) {
+    try (DataInputStream dataInputStream =
+        new DataInputStream(new BufferedInputStream(inputStream))) {
+      Pair<String, Boolean> versionAndName =
+          readAuthString(dataInputStream, STRING_ENCODING, strBufferLocal);
+      if (versionAndName == null) {
+        return;
+      }
+      String user = versionAndName.left;
+      if (isUser) {
+        // skip password
+        readString(dataInputStream, STRING_ENCODING, strBufferLocal);
+        AuthorPlan createUser = new 
AuthorPlan(ConfigPhysicalPlanType.CreateUser);
+        createUser.setUserName(user);
+        createUser.setPassword(DEFAULT_PASSWORD);
+        planDeque.add(createUser);
+      } else {
+        AuthorPlan createRole = new 
AuthorPlan(ConfigPhysicalPlanType.CreateRole);
+        createRole.setRoleName(user);
+        planDeque.add(createRole);
+      }
+
+      int privilegeMask = dataInputStream.readInt();
+      // translate sys privileges
+      generateGrantSysPlan(user, isUser, privilegeMask);
+      // translate path privileges
+      while (dataInputStream.available() != 0) {
+        String path = readString(dataInputStream, STRING_ENCODING, 
strBufferLocal);
+        PartialPath priPath;
+        try {
+          priPath = new PartialPath(path);
+        } catch (IllegalPathException exception) {
+          latestException = exception;
+          return;
+        }
+        int privileges = dataInputStream.readInt();
+        generateGrantPathPlan(user, isUser, priPath, privileges);
+      }
+    } catch (IOException ioException) {
+      logger.error(
+          "Got IOException when deserialize userole file, type:{}", 
snapshotFileType, ioException);
+      latestException = ioException;
+    } finally {
+      strBufferLocal.remove();
+    }
+  }
+
+  private void generateGrantRolePhysicalPlan() {
+    try (DataInputStream roleInputStream =
+        new DataInputStream(new BufferedInputStream((inputStream)))) {
+      while (roleInputStream.available() != 0) {
+        String roleName = readString(roleInputStream, STRING_ENCODING, 
strBufferLocal);
+        AuthorPlan plan = new 
AuthorPlan(ConfigPhysicalPlanType.GrantRoleToUser);
+        plan.setUserName(userName);
+        plan.setRoleName(roleName);
+        planDeque.add(plan);
+      }
+    } catch (IOException ioException) {
+      logger.error("Got IOException when deserialize roleList", ioException);
+      latestException = ioException;
+    } finally {
+      strBufferLocal.remove();
+    }
+  }
+
+  private void generateGrantSysPlan(String userName, boolean isUser, int 
sysMask) {
+    for (int i = 0; i < PrivilegeType.getSysPriCount(); i++) {
+      if ((sysMask & (1 << i)) != 0) {
+        AuthorPlan plan =
+            new AuthorPlan(
+                isUser ? ConfigPhysicalPlanType.GrantUser : 
ConfigPhysicalPlanType.GrantRole);
+        if (isUser) {
+          plan.setUserName(userName);
+        } else {
+          plan.setRoleName(userName);
+        }
+        plan.setPermissions(Collections.singleton(AuthUtils.posToSysPri(i)));
+        if ((sysMask & (1 << (i + 16))) != 0) {
+          plan.setGrantOpt(true);
+        }
+        plan.setNodeNameList(new ArrayList<>());
+        planDeque.add(plan);
+      }
+    }
+  }
+
+  private void generateGrantPathPlan(
+      String userName, boolean isUser, PartialPath path, int priMask) {
+    for (int pos = 0; pos < PrivilegeType.getPathPriCount(); pos++) {
+      if (((1 << pos) & priMask) != 0) {
+        AuthorPlan plan =
+            new AuthorPlan(
+                isUser ? ConfigPhysicalPlanType.GrantUser : 
ConfigPhysicalPlanType.GrantRole);
+        if (isUser) {
+          plan.setUserName(userName);
+        } else {
+          plan.setRoleName(userName);
+        }
+        
plan.setPermissions(Collections.singleton(AuthUtils.pathPosToPri(pos)));
+        plan.setNodeNameList(Collections.singletonList(path));
+        if ((1 << (pos + 16) & priMask) != 0) {
+          plan.setGrantOpt(true);
+        }
+        planDeque.add(plan);
+      }
+    }
+  }
+
+  private void generateDatabasePhysicalPlan() {
+    try (BufferedInputStream bufferedInputStream = new 
BufferedInputStream(inputStream)) {
+      byte type = ReadWriteIOUtils.readByte(bufferedInputStream);
+      String name = null;
+      int childNum = 0;
+      Stack<Pair<IConfigMNode, Boolean>> stack = new Stack<>();
+      IConfigMNode databaseMNode;
+      IConfigMNode internalMNode;
+
+      if (type == STORAGE_GROUP_MNODE_TYPE) {
+        databaseMNode = deserializeDatabaseMNode(bufferedInputStream);
+        name = databaseMNode.getName();
+        stack.push(new Pair<>(databaseMNode, true));
+      } else {
+        internalMNode = deserializeInternalMNode(bufferedInputStream);
+        childNum = ReadWriteIOUtils.readInt(bufferedInputStream);
+        name = internalMNode.getName();
+        stack.push(new Pair<>(internalMNode, false));
+      }
+
+      while (!PATH_ROOT.equals(name)) {
+        type = ReadWriteIOUtils.readByte(bufferedInputStream);
+        switch (type) {
+          case INTERNAL_MNODE_TYPE:
+            internalMNode = deserializeInternalMNode(bufferedInputStream);
+            childNum = ReadWriteIOUtils.readInt(bufferedInputStream);
+            boolean hasDB = false;
+            while (childNum > 0) {
+              hasDB = stack.peek().right;
+              internalMNode.addChild(stack.pop().left);
+              childNum--;
+            }
+            stack.push(new Pair<>(internalMNode, hasDB));
+            name = internalMNode.getName();
+            break;
+          case STORAGE_GROUP_MNODE_TYPE:
+            databaseMNode = 
deserializeDatabaseMNode(bufferedInputStream).getAsMNode();
+            while (!stack.isEmpty() && !stack.peek().right) {
+              databaseMNode.addChild(stack.pop().left);
+            }
+            stack.push(new Pair<>(databaseMNode, true));
+            name = databaseMNode.getName();
+            break;
+          default:
+            logger.error("Unrecognized node type. Cannot deserialize MTree 
from given buffer");
+            return;
+        }
+      }
+    } catch (IOException ioException) {
+      logger.error("Got IOException when construct database Tree", 
ioException);
+      latestException = ioException;
+    }
+  }
+
+  private void generateTemplatePlan() {
+    try (BufferedInputStream bufferedInputStream = new 
BufferedInputStream(templateInputStream)) {
+      ByteBuffer byteBuffer = 
ByteBuffer.wrap(IOUtils.toByteArray(bufferedInputStream));
+      // skip id
+      ReadWriteIOUtils.readInt(byteBuffer);
+      int size = ReadWriteIOUtils.readInt(byteBuffer);
+      while (size > 0) {
+        Template template = new Template();
+        template.deserialize(byteBuffer);
+        template.setId(0);
+        templateTable.put(template.getId(), template.getName());
+        CreateSchemaTemplatePlan plan = new 
CreateSchemaTemplatePlan(template.serialize().array());
+        planDeque.add(plan);
+        size--;
+      }
+    } catch (IOException ioException) {
+      logger.error("Got IOException when deserialize template info", 
ioException);
+      latestException = ioException;
+    }
+  }
+
+  private IConfigMNode deserializeDatabaseMNode(InputStream inputStream) 
throws IOException {
+    IDatabaseMNode<IConfigMNode> databaseMNode =
+        nodeFactory.createDatabaseMNode(null, 
ReadWriteIOUtils.readString(inputStream));
+    
databaseMNode.getAsMNode().setSchemaTemplateId(ReadWriteIOUtils.readInt(inputStream));
+    databaseMNode
+        .getAsMNode()
+        
.setDatabaseSchema(ThriftConfigNodeSerDeUtils.deserializeTDatabaseSchema(inputStream));
+    if (databaseMNode.getAsMNode().getDatabaseSchema().isSetTTL()) {
+      SetTTLPlan plan =
+          new SetTTLPlan(
+              
Collections.singletonList(databaseMNode.getAsMNode().getDatabaseSchema().getName()),
+              databaseMNode.getAsMNode().getDatabaseSchema().getTTL());
+      planDeque.add(plan);
+      databaseMNode.getAsMNode().getDatabaseSchema().unsetTTL();
+    }
+
+    DatabaseSchemaPlan createDBPlan =
+        new DatabaseSchemaPlan(
+            ConfigPhysicalPlanType.CreateDatabase, 
databaseMNode.getAsMNode().getDatabaseSchema());
+    planDeque.add(createDBPlan);
+
+    return databaseMNode.getAsMNode();
+  }
+
+  private IConfigMNode deserializeInternalMNode(InputStream inputStream) 
throws IOException {
+    IConfigMNode basicMNode =
+        nodeFactory.createInternalMNode(null, 
ReadWriteIOUtils.readString(inputStream));
+    basicMNode.setSchemaTemplateId(ReadWriteIOUtils.readInt(inputStream));
+    if (basicMNode.getSchemaTemplateId() >= 0) {
+      if (!templateTable.isEmpty()) {
+        String templateName = 
templateTable.get(basicMNode.getSchemaTemplateId());
+        // ignore preset plan.
+        CommitSetSchemaTemplatePlan plan =
+            new CommitSetSchemaTemplatePlan(templateName, 
basicMNode.getFullPath());
+        planDeque.add(plan);
+      }
+    }
+    return basicMNode;
+  }
+}
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNSnapshotFileType.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNSnapshotFileType.java
new file mode 100644
index 00000000000..ee8f6f9bb79
--- /dev/null
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNSnapshotFileType.java
@@ -0,0 +1,28 @@
+/*
+ * 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.confignode.persistence.schema;
+
+public enum CNSnapshotFileType {
+  INVALID,
+  USER,
+  ROLE,
+  USER_ROLE,
+  SCHEMA_TEMPLATE
+}
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfignodeSnapshotParser.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfignodeSnapshotParser.java
new file mode 100644
index 00000000000..1f6aea04cfe
--- /dev/null
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfignodeSnapshotParser.java
@@ -0,0 +1,168 @@
+/*
+ * 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.confignode.persistence.schema;
+
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.file.SystemFileFactory;
+import org.apache.iotdb.confignode.conf.ConfigNodeConfig;
+import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
+import org.apache.iotdb.tsfile.utils.Pair;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ConfignodeSnapshotParser {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(ConfignodeSnapshotParser.class);
+  private static final ConfigNodeConfig CONF = 
ConfigNodeDescriptor.getInstance().getConf();
+
+  private static final String SNAPSHOT_CLUSTER_SCHEMA_FILENAME = 
"cluster_schema.bin";
+
+  private static final String SNAPSHOT_TEMPLATE_FILENAME = "template_info.bin";
+
+  private ConfignodeSnapshotParser() {
+    // Empty constructor
+  }
+
+  private static Path getLatestSnapshotPath(List<Path> snapshotPathList) {
+    if (snapshotPathList.isEmpty()) {
+      return null;
+    }
+    Path[] pathArray = snapshotPathList.toArray(new Path[0]);
+    Arrays.sort(
+        pathArray,
+        (o1, o2) -> {
+          String index1 = o1.toFile().getName().split("_")[1];
+          String index2 = o2.toFile().getName().split("_")[1];
+          return Long.compare(Long.parseLong(index2), Long.parseLong(index1));
+        });
+    return pathArray[0];
+  }
+
+  public static List<Pair<Pair<Path, Path>, CNSnapshotFileType>> 
getSnapshots() throws IOException {
+    List<Pair<Pair<Path, Path>, CNSnapshotFileType>> snapshotPairList = new 
ArrayList<>();
+    String snapshotPath = CONF.getConsensusDir();
+    try (DirectoryStream<Path> stream =
+        Files.newDirectoryStream(Paths.get(snapshotPath), 
"[0-9]*-[0-9]*-[0-9]*-[0-9]*-[0-9]*")) {
+      // In confignode there is only one consensus dir.
+      // Get into confignode consensus dir
+      for (Path path : stream) {
+        try (DirectoryStream<Path> filestream =
+            Files.newDirectoryStream(Paths.get(path.toString() + 
File.separator + "sm"))) {
+          // find the latest snapshots
+          ArrayList<Path> snapshotList = new ArrayList<>();
+          for (Path snapshotFolder : filestream) {
+            if (snapshotFolder.toFile().isDirectory()) {
+              snapshotList.add(snapshotFolder);
+            }
+          }
+          Path latestSnapshotPath = getLatestSnapshotPath(snapshotList);
+
+          if (latestSnapshotPath != null) {
+            // Get role files.
+            String rolePath =
+                latestSnapshotPath
+                    + File.separator
+                    + IoTDBConstant.SYSTEM_FOLDER_NAME
+                    + File.separator
+                    + "roles";
+            try (DirectoryStream<Path> roleStream = 
Files.newDirectoryStream(Paths.get(rolePath))) {
+              for (Path role : roleStream) {
+                Pair<Path, Path> roleFile = new Pair<>(role, null);
+                snapshotPairList.add(new Pair<>(roleFile, 
CNSnapshotFileType.ROLE));
+              }
+            }
+            // Get user files.
+            String userPath =
+                latestSnapshotPath
+                    + File.separator
+                    + IoTDBConstant.SYSTEM_FOLDER_NAME
+                    + File.separator
+                    + "users";
+            try (DirectoryStream<Path> userStream = 
Files.newDirectoryStream(Paths.get(userPath))) {
+              List<Path> userFilePath = new ArrayList<>();
+              List<Path> userRoleFilePath = new ArrayList<>();
+              for (Path user : userStream) {
+                if (user.getFileName().toString().contains("_role.profile")) {
+                  userRoleFilePath.add(user);
+                } else {
+                  userFilePath.add(user);
+                }
+              }
+              // We should add user file firstly.
+              for (Path user : userFilePath) {
+                snapshotPairList.add(new Pair<>(new Pair<>(user, null), 
CNSnapshotFileType.USER));
+              }
+              for (Path roleList : userRoleFilePath) {
+                snapshotPairList.add(
+                    new Pair<>(new Pair<>(roleList, null), 
CNSnapshotFileType.USER_ROLE));
+              }
+            }
+
+            // Get cluster schema info file and template file.
+            File schemaInfoFile =
+                SystemFileFactory.INSTANCE.getFile(
+                    latestSnapshotPath + File.separator + 
SNAPSHOT_CLUSTER_SCHEMA_FILENAME);
+            File templateInfoFile =
+                SystemFileFactory.INSTANCE.getFile(
+                    latestSnapshotPath + File.separator + 
SNAPSHOT_TEMPLATE_FILENAME);
+            if (schemaInfoFile.exists() && templateInfoFile.exists()) {
+              snapshotPairList.add(
+                  new Pair<>(
+                      new Pair<>(schemaInfoFile.toPath(), 
templateInfoFile.toPath()),
+                      CNSnapshotFileType.SCHEMA_TEMPLATE));
+            }
+          }
+        }
+      }
+    }
+    return snapshotPairList;
+  }
+
+  public static CNPhysicalPlanGenerator translate2PhysicalPlan(
+      Path path1, Path path2, CNSnapshotFileType type) throws IOException {
+    if (type == CNSnapshotFileType.SCHEMA_TEMPLATE && (path1 == null || path2 
== null)) {
+      LOGGER.warn("schema_template require schemainfo file and template file");
+      return null;
+    } else if (path1 == null) {
+      LOGGER.warn("path1 should not be null");
+      return null;
+    }
+
+    if (path1.toFile().exists()) {
+      LOGGER.warn("file {}  not exists", path1.toFile().getName());
+      return null;
+    }
+
+    if (type == CNSnapshotFileType.SCHEMA_TEMPLATE) {
+      return new CNPhysicalPlanGenerator(path1, path2);
+    } else {
+      return new CNPhysicalPlanGenerator(path1, type);
+    }
+  }
+}
diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/CNPhysicalPlanGeneratorTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/CNPhysicalPlanGeneratorTest.java
new file mode 100644
index 00000000000..f7b7700c244
--- /dev/null
+++ 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/CNPhysicalPlanGeneratorTest.java
@@ -0,0 +1,446 @@
+/*
+ * 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.confignode.persistence;
+
+import org.apache.iotdb.commons.auth.AuthException;
+import org.apache.iotdb.commons.auth.entity.PrivilegeType;
+import org.apache.iotdb.commons.file.SystemFileFactory;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.utils.FileUtils;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+import org.apache.iotdb.confignode.consensus.request.auth.AuthorPlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.database.DatabaseSchemaPlan;
+import org.apache.iotdb.confignode.consensus.request.write.database.SetTTLPlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.template.CommitSetSchemaTemplatePlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.template.CreateSchemaTemplatePlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.template.PreSetSchemaTemplatePlan;
+import org.apache.iotdb.confignode.persistence.schema.CNPhysicalPlanGenerator;
+import org.apache.iotdb.confignode.persistence.schema.CNSnapshotFileType;
+import org.apache.iotdb.confignode.persistence.schema.ClusterSchemaInfo;
+import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
+import org.apache.iotdb.db.schemaengine.template.Template;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static org.apache.iotdb.db.utils.constant.TestConstant.BASE_OUTPUT_PATH;
+
+public class CNPhysicalPlanGeneratorTest {
+  private static AuthorInfo authorInfo;
+  private static ClusterSchemaInfo clusterSchemaInfo;
+
+  private static final File snapshotDir = new File(BASE_OUTPUT_PATH, 
"authorInfo-snapshot");
+  private static final String USER_SNAPSHOT_FILE_NAME = "system" + 
File.separator + "users";
+  private static final String ROLE_SNAPSHOT_FILE_NAME = "system" + 
File.separator + "roles";
+
+  private static final String SCHEMA_INFO_FILE_NAME = "cluster_schema.bin";
+  private static final String TEMPLATE_INFO_FILE_NAME = "template_info.bin";
+
+  private static void setupAuthorInfo() {
+    authorInfo = new AuthorInfo();
+    if (!snapshotDir.exists()) {
+      snapshotDir.mkdir();
+    }
+  }
+
+  private static void setupClusterSchemaInfo() throws IOException {
+    clusterSchemaInfo = new ClusterSchemaInfo();
+    if (!snapshotDir.exists()) {
+      snapshotDir.mkdir();
+    }
+  }
+
+  @After
+  public void cleanUpInfo() throws AuthException {
+    if (authorInfo != null) {
+      authorInfo.clear();
+    }
+    if (clusterSchemaInfo != null) {
+      clusterSchemaInfo.clear();
+    }
+    FileUtils.deleteDirectory(snapshotDir);
+  }
+
+  @Test
+  public void roleGeneratorTest() throws Exception {
+    HashSet<Integer> answerSet = new HashSet<>();
+    String roleName = "test1";
+    setupAuthorInfo();
+    AuthorPlan plan = new AuthorPlan(ConfigPhysicalPlanType.CreateRole);
+    plan.setRoleName(roleName);
+    answerSet.add(plan.hashCode());
+    // step 1: create role - plan1
+    authorInfo.authorNonQuery(plan);
+
+    // step 2: grant role path privileges - plan2
+    plan = new AuthorPlan(ConfigPhysicalPlanType.GrantRole);
+    plan.setRoleName(roleName);
+    plan.setNodeNameList(Collections.singletonList(new 
PartialPath("root.db.t1")));
+    Set<Integer> pathPris = new HashSet<>();
+    pathPris.add(PrivilegeType.WRITE_DATA.ordinal());
+    pathPris.add(PrivilegeType.WRITE_SCHEMA.ordinal());
+    plan.setPermissions(pathPris);
+    authorInfo.authorNonQuery(plan);
+
+    // answer set
+    plan.getPermissions().clear();
+    plan.getPermissions().add(PrivilegeType.WRITE_DATA.ordinal());
+    answerSet.add(plan.hashCode());
+    plan.getPermissions().clear();
+    plan.getPermissions().add(PrivilegeType.WRITE_SCHEMA.ordinal());
+    answerSet.add(plan.hashCode());
+
+    // step 3: grant role sys privileges - plan3
+    plan = new AuthorPlan(ConfigPhysicalPlanType.GrantRole);
+    plan.setRoleName(roleName);
+    plan.setNodeNameList(Collections.emptyList());
+    Set<Integer> sysPris = new HashSet<>();
+    sysPris.add(PrivilegeType.MANAGE_DATABASE.ordinal());
+    sysPris.add(PrivilegeType.MANAGE_ROLE.ordinal());
+    plan.setPermissions(sysPris);
+    plan.setGrantOpt(true);
+    authorInfo.authorNonQuery(plan);
+
+    // answer set
+    plan.getPermissions().clear();
+    plan.getPermissions().add(PrivilegeType.MANAGE_ROLE.ordinal());
+    answerSet.add(plan.hashCode());
+    plan.getPermissions().clear();
+    plan.getPermissions().add(PrivilegeType.MANAGE_DATABASE.ordinal());
+    answerSet.add(plan.hashCode());
+
+    // PhysicalPlan gnerator will return five plans:
+    // 1. create role plan
+    // 2. grant path privileges plan * 2
+    // 3. grant system privileges plan * 2
+    boolean success = authorInfo.processTakeSnapshot(snapshotDir);
+
+    File roleProfile =
+        SystemFileFactory.INSTANCE.getFile(
+            snapshotDir
+                + File.separator
+                + ROLE_SNAPSHOT_FILE_NAME
+                + File.separator
+                + roleName
+                + ".profile");
+
+    CNPhysicalPlanGenerator planGenerator =
+        new CNPhysicalPlanGenerator(roleProfile.toPath(), 
CNSnapshotFileType.ROLE);
+    int count = 0;
+    for (ConfigPhysicalPlan authPlan : planGenerator) {
+      Assert.assertTrue(answerSet.contains(authPlan.hashCode()));
+      count++;
+    }
+    Assert.assertEquals(5, count);
+  }
+
+  @Test
+  public void userGeneratorTest() throws Exception {
+    String userName = "test1";
+    Set<Integer> answerSet = new HashSet<>();
+    setupAuthorInfo();
+    AuthorPlan plan = new AuthorPlan(ConfigPhysicalPlanType.CreateUser);
+    plan.setPassword("password");
+    plan.setUserName(userName);
+    // create user plan 1
+    authorInfo.authorNonQuery(plan);
+    answerSet.add(plan.hashCode());
+
+    plan = new AuthorPlan(ConfigPhysicalPlanType.CreateRole);
+    plan.setRoleName("role1");
+    authorInfo.authorNonQuery(plan);
+
+    // grant path privileges, plan 2 , plan 3
+    plan = new AuthorPlan(ConfigPhysicalPlanType.GrantUser);
+    plan.setUserName(userName);
+    plan.setNodeNameList(Collections.singletonList(new 
PartialPath("root.db1.t2")));
+    Set<Integer> priSet = new HashSet<>();
+    priSet.add(PrivilegeType.WRITE_SCHEMA.ordinal());
+    priSet.add(PrivilegeType.READ_DATA.ordinal());
+    plan.setPermissions(priSet);
+    plan.setGrantOpt(true);
+    authorInfo.authorNonQuery(plan);
+
+    plan.getPermissions().clear();
+    plan.getPermissions().add(PrivilegeType.WRITE_SCHEMA.ordinal());
+    answerSet.add(plan.hashCode());
+
+    plan.getPermissions().clear();
+    plan.getPermissions().add(PrivilegeType.READ_DATA.ordinal());
+    answerSet.add(plan.hashCode());
+
+    // grant system privileges, plan 4
+    plan = new AuthorPlan(ConfigPhysicalPlanType.GrantUser);
+    plan.setUserName(userName);
+    plan.setNodeNameList(Collections.emptyList());
+    
plan.setPermissions(Collections.singleton(PrivilegeType.MANAGE_DATABASE.ordinal()));
+    plan.setGrantOpt(false);
+    authorInfo.authorNonQuery(plan);
+    answerSet.add(plan.hashCode());
+
+    // grant role to user, plan 5
+    plan = new AuthorPlan(ConfigPhysicalPlanType.GrantRoleToUser);
+    plan.setRoleName("role1");
+    plan.setUserName(userName);
+    authorInfo.authorNonQuery(plan);
+    answerSet.add(plan.hashCode());
+
+    boolean success = authorInfo.processTakeSnapshot(snapshotDir);
+
+    File userProfile =
+        SystemFileFactory.INSTANCE.getFile(
+            snapshotDir
+                + File.separator
+                + USER_SNAPSHOT_FILE_NAME
+                + File.separator
+                + userName
+                + ".profile");
+
+    CNPhysicalPlanGenerator planGenerator =
+        new CNPhysicalPlanGenerator(userProfile.toPath(), 
CNSnapshotFileType.USER);
+    int count = 0;
+    // plan 1-4
+    for (ConfigPhysicalPlan authPlan : planGenerator) {
+      Assert.assertTrue(answerSet.contains(authPlan.hashCode()));
+      count++;
+    }
+    Assert.assertEquals(4, count);
+    File roleListProfile =
+        SystemFileFactory.INSTANCE.getFile(
+            snapshotDir
+                + File.separator
+                + USER_SNAPSHOT_FILE_NAME
+                + File.separator
+                + userName
+                + "_role.profile");
+    planGenerator =
+        new CNPhysicalPlanGenerator(roleListProfile.toPath(), 
CNSnapshotFileType.USER_ROLE);
+    count = 0;
+    // plan 5
+    for (ConfigPhysicalPlan authPlan : planGenerator) {
+      Assert.assertTrue(answerSet.contains(authPlan.hashCode()));
+      count++;
+    }
+    Assert.assertEquals(1, count);
+  }
+
+  @Test
+  public void databaseWithoutTemplateGeneratorTest() throws Exception {
+    setupClusterSchemaInfo();
+    Set<Integer> answerSet = new HashSet<>();
+    Set<String> storageGroupPathList = new TreeSet<>();
+    storageGroupPathList.add("root.sg");
+    storageGroupPathList.add("root.a.sg");
+    storageGroupPathList.add("root.a.b.sg");
+    storageGroupPathList.add("root.a.a.a.b.sg");
+
+    int i = 0;
+    for (String path : storageGroupPathList) {
+      TDatabaseSchema tDatabaseSchema = new TDatabaseSchema();
+      tDatabaseSchema.setName(path);
+      tDatabaseSchema.setTTL(i);
+      tDatabaseSchema.setDataReplicationFactor(i);
+      tDatabaseSchema.setSchemaReplicationFactor(i);
+      tDatabaseSchema.setTimePartitionInterval(i);
+      clusterSchemaInfo.createDatabase(
+          new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, 
tDatabaseSchema));
+      SetTTLPlan plan = new SetTTLPlan(Collections.singletonList(path), 
tDatabaseSchema.getTTL());
+      answerSet.add(plan.hashCode());
+      TDatabaseSchema tDatabaseSchemaBak = new 
TDatabaseSchema(tDatabaseSchema);
+      tDatabaseSchemaBak.unsetTTL();
+      DatabaseSchemaPlan databaseSchemaPlan =
+          new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, 
tDatabaseSchemaBak);
+      answerSet.add(databaseSchemaPlan.hashCode());
+      i++;
+    }
+
+    boolean success = clusterSchemaInfo.processTakeSnapshot(snapshotDir);
+    Assert.assertTrue(success);
+    File schemaInfo =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + 
SCHEMA_INFO_FILE_NAME);
+    File templateInfo =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + 
TEMPLATE_INFO_FILE_NAME);
+
+    CNPhysicalPlanGenerator planGenerator =
+        new CNPhysicalPlanGenerator(schemaInfo.toPath(), 
templateInfo.toPath());
+    int count = 0;
+    for (ConfigPhysicalPlan plan : planGenerator) {
+      if (plan.getType() == ConfigPhysicalPlanType.CreateDatabase) {
+        Assert.assertTrue(answerSet.contains(((DatabaseSchemaPlan) 
plan).hashCode()));
+      } else if (plan.getType() == ConfigPhysicalPlanType.SetTTL) {
+        Assert.assertTrue(answerSet.contains(((SetTTLPlan) plan).hashCode()));
+      }
+      count++;
+    }
+    planGenerator.checkException();
+    Assert.assertEquals(8, count);
+  }
+
+  @Test
+  public void templateGneratorTest() throws Exception {
+    setupClusterSchemaInfo();
+    Template t1 =
+        new Template(
+            "t1",
+            Arrays.asList("s1", "s2"),
+            Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN),
+            Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN),
+            Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY));
+    Template t2 =
+        new Template(
+            "t2",
+            Arrays.asList("s1", "s2", "s3"),
+            Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN, 
TSDataType.TEXT),
+            Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN, 
TSEncoding.DIFF),
+            Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY, 
CompressionType.LZ4));
+    Map<String, CreateSchemaTemplatePlan> answerPlan = new HashMap<>();
+
+    CreateSchemaTemplatePlan plan1 = new 
CreateSchemaTemplatePlan(t1.serialize().array());
+    clusterSchemaInfo.createSchemaTemplate(plan1);
+    answerPlan.put(t1.getName(), plan1);
+
+    CreateSchemaTemplatePlan plan2 = new 
CreateSchemaTemplatePlan(t2.serialize().array());
+    clusterSchemaInfo.createSchemaTemplate(plan2);
+    answerPlan.put(t2.getName(), plan2);
+
+    boolean success = clusterSchemaInfo.processTakeSnapshot(snapshotDir);
+    Assert.assertTrue(success);
+    File schemaInfo =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + 
SCHEMA_INFO_FILE_NAME);
+    File templateInfo =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + 
TEMPLATE_INFO_FILE_NAME);
+    CNPhysicalPlanGenerator planGenerator =
+        new CNPhysicalPlanGenerator(schemaInfo.toPath(), 
templateInfo.toPath());
+    int count = 0;
+    for (ConfigPhysicalPlan plan : planGenerator) {
+      CreateSchemaTemplatePlan templatePlan = (CreateSchemaTemplatePlan) plan;
+      
Assert.assertTrue(answerPlan.get(templatePlan.getTemplate().getName()).equals(templatePlan));
+      count++;
+    }
+    Assert.assertEquals(2, count);
+  }
+
+  @Test
+  public void templateAndDatabaseComplatedTest() throws Exception {
+    setupClusterSchemaInfo();
+    Set<Integer> answerSet = new HashSet<>();
+    Set<String> storageGroupPathList = new TreeSet<>();
+    storageGroupPathList.add("root.sg");
+    storageGroupPathList.add("root.a.sg");
+    storageGroupPathList.add("root.a.b.sg");
+    storageGroupPathList.add("root.a.a.a.b.sg");
+
+    int i = 0;
+    for (String path : storageGroupPathList) {
+      TDatabaseSchema tDatabaseSchema = new TDatabaseSchema();
+      tDatabaseSchema.setName(path);
+      tDatabaseSchema.setTTL(i);
+      tDatabaseSchema.setDataReplicationFactor(i);
+      tDatabaseSchema.setSchemaReplicationFactor(i);
+      tDatabaseSchema.setTimePartitionInterval(i);
+      clusterSchemaInfo.createDatabase(
+          new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, 
tDatabaseSchema));
+      SetTTLPlan plan = new SetTTLPlan(Collections.singletonList(path), 
tDatabaseSchema.getTTL());
+      answerSet.add(plan.hashCode());
+      TDatabaseSchema tDatabaseSchemaBak = new 
TDatabaseSchema(tDatabaseSchema);
+      tDatabaseSchemaBak.unsetTTL();
+      DatabaseSchemaPlan databaseSchemaPlan =
+          new DatabaseSchemaPlan(ConfigPhysicalPlanType.CreateDatabase, 
tDatabaseSchemaBak);
+      answerSet.add(databaseSchemaPlan.hashCode());
+      i++;
+    }
+    Template t1 =
+        new Template(
+            "t1",
+            Arrays.asList("s1", "s2"),
+            Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN),
+            Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN),
+            Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY));
+    Template t2 =
+        new Template(
+            "t2",
+            Arrays.asList("s1", "s2", "s3"),
+            Arrays.asList(TSDataType.INT32, TSDataType.BOOLEAN, 
TSDataType.TEXT),
+            Arrays.asList(TSEncoding.GORILLA, TSEncoding.PLAIN, 
TSEncoding.DIFF),
+            Arrays.asList(CompressionType.GZIP, CompressionType.SNAPPY, 
CompressionType.LZ4));
+    CreateSchemaTemplatePlan plan1 = new 
CreateSchemaTemplatePlan(t1.serialize().array());
+    clusterSchemaInfo.createSchemaTemplate(plan1);
+    answerSet.add(plan1.hashCode());
+
+    CreateSchemaTemplatePlan plan2 = new 
CreateSchemaTemplatePlan(t2.serialize().array());
+    clusterSchemaInfo.createSchemaTemplate(plan2);
+    answerSet.add(plan2.hashCode());
+
+    PreSetSchemaTemplatePlan preSetSchemaTemplatePlan1 =
+        new PreSetSchemaTemplatePlan("t1", "root.sg.t1");
+    PreSetSchemaTemplatePlan preSetSchemaTemplatePlan2 =
+        new PreSetSchemaTemplatePlan("t2", "root.a.sg.t1");
+    CommitSetSchemaTemplatePlan setSchemaTemplatePlan1 =
+        new CommitSetSchemaTemplatePlan("t1", "root.sg.t1");
+    CommitSetSchemaTemplatePlan setSchemaTemplatePlan2 =
+        new CommitSetSchemaTemplatePlan("t2", "root.a.sg.t1");
+    clusterSchemaInfo.preSetSchemaTemplate(preSetSchemaTemplatePlan1);
+    clusterSchemaInfo.preSetSchemaTemplate(preSetSchemaTemplatePlan2);
+    clusterSchemaInfo.commitSetSchemaTemplate(setSchemaTemplatePlan1);
+    clusterSchemaInfo.commitSetSchemaTemplate(setSchemaTemplatePlan2);
+    answerSet.add(setSchemaTemplatePlan1.hashCode());
+    answerSet.add(setSchemaTemplatePlan1.hashCode());
+
+    boolean success = clusterSchemaInfo.processTakeSnapshot(snapshotDir);
+    Assert.assertTrue(success);
+    File schemaInfo =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + 
SCHEMA_INFO_FILE_NAME);
+    File templateInfo =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir + File.separator + 
TEMPLATE_INFO_FILE_NAME);
+    CNPhysicalPlanGenerator planGenerator =
+        new CNPhysicalPlanGenerator(schemaInfo.toPath(), 
templateInfo.toPath());
+    int count = 0;
+    for (ConfigPhysicalPlan plan : planGenerator) {
+      if (plan.getType() == ConfigPhysicalPlanType.CreateDatabase) {
+        Assert.assertTrue(answerSet.contains(((DatabaseSchemaPlan) 
plan).hashCode()));
+      } else if (plan.getType() == ConfigPhysicalPlanType.SetTTL) {
+        Assert.assertTrue(answerSet.contains(((SetTTLPlan) plan).hashCode()));
+      } else if (plan.getType() == 
ConfigPhysicalPlanType.CreateSchemaTemplate) {
+        Assert.assertTrue(answerSet.contains(((CreateSchemaTemplatePlan) 
plan).hashCode()));
+      } else if (plan.getType() == 
ConfigPhysicalPlanType.PreSetSchemaTemplate) {
+        Assert.assertTrue(answerSet.contains(((PreSetSchemaTemplatePlan) 
plan).hashCode()));
+      } else if (plan.getType() == 
ConfigPhysicalPlanType.CommitSetSchemaTemplate) {
+        Assert.assertTrue(answerSet.contains(((CommitSetSchemaTemplatePlan) 
plan).hashCode()));
+      }
+      count++;
+    }
+    Assert.assertEquals(12, count);
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/tools/schema/SRStatementGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/tools/schema/SRStatementGenerator.java
index ced730c1d3c..78a42312d20 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/tools/schema/SRStatementGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/tools/schema/SRStatementGenerator.java
@@ -26,10 +26,12 @@ import 
org.apache.iotdb.commons.schema.node.common.AbstractDatabaseMNode;
 import org.apache.iotdb.commons.schema.node.common.AbstractMeasurementMNode;
 import org.apache.iotdb.commons.schema.node.utils.IMNodeContainer;
 import org.apache.iotdb.commons.schema.node.visitor.MNodeVisitor;
+import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
 import org.apache.iotdb.db.queryengine.plan.statement.Statement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateTimeSeriesStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.template.ActivateTemplateStatement;
+import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.view.CreateLogicalViewStatement;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.IMemMNode;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.snapshot.MemMTreeSnapshotUtil;
 import org.apache.iotdb.tsfile.utils.Pair;
@@ -46,6 +48,7 @@ import java.nio.channels.FileChannel;
 import java.nio.file.Files;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayDeque;
+import java.util.Collections;
 import java.util.Deque;
 import java.util.Iterator;
 import java.util.Map;
@@ -270,8 +273,14 @@ public class SRStatementGenerator implements 
Iterator<Statement>, Iterable<State
     @Override
     public Statement visitMeasurementMNode(
         AbstractMeasurementMNode<?, ? extends IMNode<?>> node, PartialPath 
path) {
-      if (node.isLogicalView() || 
node.getParent().getAsDeviceMNode().isAligned()) {
+      if (node.getParent().getAsDeviceMNode().isAligned()) {
         return null;
+      } else if (node.isLogicalView()) {
+        CreateLogicalViewStatement stmt = new CreateLogicalViewStatement();
+        LogicalViewSchema viewSchema = (LogicalViewSchema) 
node.getAsMeasurementMNode().getSchema();
+        stmt.setTargetFullPaths(Collections.singletonList(path));
+        
stmt.setViewExpressions(Collections.singletonList(viewSchema.getExpression()));
+        return stmt;
       } else {
         CreateTimeSeriesStatement stmt = new CreateTimeSeriesStatement();
         stmt.setPath(path);
@@ -279,7 +288,7 @@ public class SRStatementGenerator implements 
Iterator<Statement>, Iterable<State
         
stmt.setCompressor(node.getAsMeasurementMNode().getSchema().getCompressor());
         stmt.setDataType(node.getDataType());
         
stmt.setEncoding(node.getAsMeasurementMNode().getSchema().getEncodingType());
-        if (node.getOffset() != 0) {
+        if (node.getOffset() >= 0) {
           if (tagFileChannel != null) {
             try {
               ByteBuffer byteBuffer = 
ByteBuffer.allocate(COMMON_CONFIG.getTagAttributeTotalSize());
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/SchemaRegionSnapshotParserTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/SchemaRegionSnapshotParserTest.java
index d0d48b09027..1a676aec9f6 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/SchemaRegionSnapshotParserTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/SchemaRegionSnapshotParserTest.java
@@ -588,7 +588,7 @@ public class SchemaRegionSnapshotParserTest {
             }));
     for (ISchemaRegionPlan plan : planMap.values()) {
       if (plan instanceof ICreateTimeSeriesPlan) {
-        schemaRegion.createTimeseries((ICreateTimeSeriesPlan) plan, 0);
+        schemaRegion.createTimeseries((ICreateTimeSeriesPlan) plan, -1);
       } else if (plan instanceof ICreateAlignedTimeSeriesPlan) {
         schemaRegion.createAlignedTimeSeries((ICreateAlignedTimeSeriesPlan) 
plan);
       } else if (plan instanceof IActivateTemplateInClusterPlan) {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/PathPrivilege.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/PathPrivilege.java
index 4311be521f5..e54ca063199 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/PathPrivilege.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/PathPrivilege.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.commons.auth.entity;
 
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.path.PathDeserializeUtil;
+import org.apache.iotdb.commons.utils.AuthUtils;
 import org.apache.iotdb.commons.utils.SerializeUtils;
 
 import org.slf4j.Logger;
@@ -113,43 +114,13 @@ public class PathPrivilege {
     return false;
   }
 
-  private int posToPri(int pos) {
-    switch (pos) {
-      case 0:
-        return PrivilegeType.READ_DATA.ordinal();
-      case 1:
-        return PrivilegeType.WRITE_DATA.ordinal();
-      case 2:
-        return PrivilegeType.READ_SCHEMA.ordinal();
-      case 3:
-        return PrivilegeType.WRITE_SCHEMA.ordinal();
-      default:
-        return -1;
-    }
-  }
-
-  private int priToPos(PrivilegeType pri) {
-    switch (pri) {
-      case READ_DATA:
-        return 0;
-      case WRITE_DATA:
-        return 1;
-      case READ_SCHEMA:
-        return 2;
-      case WRITE_SCHEMA:
-        return 3;
-      default:
-        return -1;
-    }
-  }
-
   public void setAllPrivileges(int privs) {
     for (int i = 0; i < PATH_PRI_SIZE; i++) {
       if (((1 << i) & privs) != 0) {
-        privileges.add(posToPri(i));
+        privileges.add(AuthUtils.pathPosToPri(i));
       }
-      if (((1 << (i + 16) & privs) != 0)) {
-        grantOpts.add(posToPri(i));
+      if ((1 << (i + 16) & privs) != 0) {
+        grantOpts.add(AuthUtils.pathPosToPri(i));
       }
     }
   }
@@ -157,10 +128,10 @@ public class PathPrivilege {
   public int getAllPrivileges() {
     int privilege = 0;
     for (Integer pri : privileges) {
-      privilege |= 1 << priToPos(PrivilegeType.values()[pri]);
+      privilege |= 1 << AuthUtils.pathPriToPos(PrivilegeType.values()[pri]);
     }
     for (Integer grantOpt : grantOpts) {
-      privilege |= 1 << (priToPos(PrivilegeType.values()[grantOpt]) + 16);
+      privilege |= 1 << 
(AuthUtils.pathPriToPos(PrivilegeType.values()[grantOpt]) + 16);
     }
     return privilege;
   }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
index 2fbd4914af0..017d6d0db9f 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/Role.java
@@ -81,10 +81,10 @@ public class Role {
   public int getAllSysPrivileges() {
     int privs = 0;
     for (Integer sysPri : sysPrivilegeSet) {
-      privs |= 1 << sysPriTopos(sysPri);
+      privs |= 1 << AuthUtils.sysPriTopos(sysPri);
     }
     for (Integer sysGrantOpt : sysPriGrantOpt) {
-      privs |= 1 << (sysPriTopos(sysGrantOpt) + 16);
+      privs |= 1 << (AuthUtils.sysPriTopos(sysGrantOpt) + 16);
     }
     return privs;
   }
@@ -126,61 +126,6 @@ public class Role {
     this.sysPriGrantOpt = grantOpt;
   }
 
-  private int posToSysPri(int pos) {
-    switch (pos) {
-      case 0:
-        return PrivilegeType.MANAGE_DATABASE.ordinal();
-      case 1:
-        return PrivilegeType.MANAGE_USER.ordinal();
-      case 2:
-        return PrivilegeType.MANAGE_ROLE.ordinal();
-      case 3:
-        return PrivilegeType.USE_TRIGGER.ordinal();
-      case 4:
-        return PrivilegeType.USE_UDF.ordinal();
-      case 5:
-        return PrivilegeType.USE_CQ.ordinal();
-      case 6:
-        return PrivilegeType.USE_PIPE.ordinal();
-      case 7:
-        return PrivilegeType.EXTEND_TEMPLATE.ordinal();
-      case 8:
-        return PrivilegeType.MAINTAIN.ordinal();
-      case 9:
-        return PrivilegeType.USE_MODEL.ordinal();
-      default:
-        return -1;
-    }
-  }
-
-  private int sysPriTopos(int privilegeId) {
-    PrivilegeType type = PrivilegeType.values()[privilegeId];
-    switch (type) {
-      case MANAGE_DATABASE:
-        return 0;
-      case MANAGE_USER:
-        return 1;
-      case MANAGE_ROLE:
-        return 2;
-      case USE_TRIGGER:
-        return 3;
-      case USE_UDF:
-        return 4;
-      case USE_CQ:
-        return 5;
-      case USE_PIPE:
-        return 6;
-      case EXTEND_TEMPLATE:
-        return 7;
-      case MAINTAIN:
-        return 8;
-      case USE_MODEL:
-        return 9;
-      default:
-        return -1;
-    }
-  }
-
   public void setSysPrivilegeSet(int privilegeMask) {
     if (sysPrivilegeSet == null) {
       sysPrivilegeSet = new HashSet<>();
@@ -190,10 +135,10 @@ public class Role {
     }
     for (int i = 0; i < SYS_PRI_SIZE; i++) {
       if ((privilegeMask & (1 << i)) != 0) {
-        sysPrivilegeSet.add(posToSysPri(i));
+        sysPrivilegeSet.add(AuthUtils.posToSysPri(i));
       }
       if ((privilegeMask & (1 << (i + 16))) != 0) {
-        sysPriGrantOpt.add(posToSysPri(i));
+        sysPriGrantOpt.add(AuthUtils.posToSysPri(i));
       }
     }
   }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/AuthUtils.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/AuthUtils.java
index 87e277ac76e..f4079b4dd15 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/AuthUtils.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/AuthUtils.java
@@ -490,4 +490,89 @@ public class AuthUtils {
     }
     role.setServiceReady(true);
   }
+
+  public static int posToSysPri(int pos) {
+    switch (pos) {
+      case 0:
+        return PrivilegeType.MANAGE_DATABASE.ordinal();
+      case 1:
+        return PrivilegeType.MANAGE_USER.ordinal();
+      case 2:
+        return PrivilegeType.MANAGE_ROLE.ordinal();
+      case 3:
+        return PrivilegeType.USE_TRIGGER.ordinal();
+      case 4:
+        return PrivilegeType.USE_UDF.ordinal();
+      case 5:
+        return PrivilegeType.USE_CQ.ordinal();
+      case 6:
+        return PrivilegeType.USE_PIPE.ordinal();
+      case 7:
+        return PrivilegeType.EXTEND_TEMPLATE.ordinal();
+      case 8:
+        return PrivilegeType.MAINTAIN.ordinal();
+      case 9:
+        return PrivilegeType.USE_MODEL.ordinal();
+      default:
+        return -1;
+    }
+  }
+
+  public static int sysPriTopos(int privilegeId) {
+    PrivilegeType type = PrivilegeType.values()[privilegeId];
+    switch (type) {
+      case MANAGE_DATABASE:
+        return 0;
+      case MANAGE_USER:
+        return 1;
+      case MANAGE_ROLE:
+        return 2;
+      case USE_TRIGGER:
+        return 3;
+      case USE_UDF:
+        return 4;
+      case USE_CQ:
+        return 5;
+      case USE_PIPE:
+        return 6;
+      case EXTEND_TEMPLATE:
+        return 7;
+      case MAINTAIN:
+        return 8;
+      case USE_MODEL:
+        return 9;
+      default:
+        return -1;
+    }
+  }
+
+  public static int pathPosToPri(int pos) {
+    switch (pos) {
+      case 0:
+        return PrivilegeType.READ_DATA.ordinal();
+      case 1:
+        return PrivilegeType.WRITE_DATA.ordinal();
+      case 2:
+        return PrivilegeType.READ_SCHEMA.ordinal();
+      case 3:
+        return PrivilegeType.WRITE_SCHEMA.ordinal();
+      default:
+        return -1;
+    }
+  }
+
+  public static int pathPriToPos(PrivilegeType pri) {
+    switch (pri) {
+      case READ_DATA:
+        return 0;
+      case WRITE_DATA:
+        return 1;
+      case READ_SCHEMA:
+        return 2;
+      case WRITE_SCHEMA:
+        return 3;
+      default:
+        return -1;
+    }
+  }
 }

Reply via email to